Files
TAIXIN/sdk/app/scale_msi/scale3_msi.c

768 lines
23 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "scale_msi.h"
#include "dev/vpp/hgvpp.h"
#include "lib/video/vpp/vpp_dev.h"
#include "dev/scale/hgscale.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
// data申请空间函数
#define STREAM_MALLOC av_psram_malloc
#define STREAM_FREE av_psram_free
#define STREAM_ZALLOC av_psram_zalloc
// 结构体申请空间函数
#define STREAM_LIBC_MALLOC av_malloc
#define STREAM_LIBC_FREE av_free
#define STREAM_LIBC_ZALLOC av_zalloc
struct scale3_yuv_arg_s
{
struct yuv_arg_s yuv_arg;
uint16_t ow,oh;
uint16_t ox,oy;
uint8_t tx_type; //0~3 :video 4:error fb
};
//暂时这里去控制scale3从哪个buf过来
//请配合VPP那边配置
#define SCALE3_YUVBUF_0_1 SCALE3_FROM_VPPBF
extern uint8 *yuvbuf;
extern uint8 *yuvbuf1;
#if SCALE3_YUVBUF_0_1 == 0
#define SCALE3_LINE_BUF yuvbuf
#define SCALE3_YUVBUF_Y_OFF_LINE ((VPP_BUF0_MODE == VPP_MODE_2N) ? (VPP_BUF0_LINEBUF_NUM * 2) : (VPP_BUF0_LINEBUF_NUM * 2 + 16))
#elif SCALE3_YUVBUF_0_1 == 1
#define SCALE3_LINE_BUF yuvbuf1
#define SCALE3_YUVBUF_Y_OFF_LINE ((VPP_BUF1_MODE == VPP_MODE_2N) ? (VPP_BUF1_LINEBUF_NUM * 2) : (VPP_BUF1_LINEBUF_NUM * 2 + 16))
#endif
// 暂定这个scale3是在存在dvp的时候使用,所以用宏隔离
// 实际scale3还有另一种模式不需要dvp那边启动的
// 这里可能采用信号量的形式,通知到线程去处理数据
struct scale_msg_t scale3_msg[3] = {
//ISP_VIDEO_0
{
.ow = 320,
.oh = 180,
.x = 0,
.y = 0,
.video_only = 0,
},
//ISP_VIDEO_1
{
.ow = 320,
.oh = 180,
.x = 320,
.y = 0,
.video_only = 0,
},
//ISP_VIDEO_2
{
.ow = 320,
.oh = 180,
.x = 0,
.y = 180,
.video_only = 0,
},
};
static int32_t scale3_vpp_done_func(uint32 irq_data){
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)irq_data;
struct framebuff *fb = NULL;
uint8_t *p_buf;
uint16_t xm,ym;
uint16_t videow,videoh;
uint8_t sennum = 0;
struct scale3_yuv_arg_s *arg;
uint8_t errfb;
if (SCALE3_YUVBUF_0_1 == 0)
{
extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
get_vpp_w_h(&videow, &videoh);
}
else if (SCALE3_YUVBUF_0_1 == 1)
{
extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
get_vpp1_w_h(&videow, &videoh);
}
// static uint32_t scaler_cnt;
//判断序号,有可能双镜头
// scale3->seq++;
if(scale3->txpool_type == 1){
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
}else{
if(video_msg.video_type_cur == ISP_VIDEO_0){
if(video_msg.video_num == 2){
fb = fbpool_get(&scale3->tx_pool1, 0, scale3->msi);
}else{
if(video_msg.video_type_last == ISP_VIDEO_1){
fb = fbpool_get(&scale3->tx_pool2, 0, scale3->msi);
}else{
fb = fbpool_get(&scale3->tx_pool1, 0, scale3->msi);
}
}
}
if(video_msg.video_type_cur == ISP_VIDEO_1){
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
}
if(video_msg.video_type_cur == ISP_VIDEO_2){
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
}
}
errfb = 0;
if(fb == NULL){
fb = fbpool_get(&scale3->tx_poolerr, 0, scale3->msi);
errfb = 1;
}
if(video_msg.video_num == 1){
sennum = 0;
}else if(video_msg.video_num == 2){
if(video_msg.video_type_cur == ISP_VIDEO_0){
sennum = 1;
}else{
sennum = 0;
}
}else{
if((video_msg.video_type_cur == ISP_VIDEO_1)||(video_msg.video_type_cur == ISP_VIDEO_2)){
sennum = 0;
}else if(video_msg.video_type_last == ISP_VIDEO_1){
sennum = 2;
}else if(video_msg.video_type_last == ISP_VIDEO_2){
sennum = 1;
}
}
arg = (struct scale3_yuv_arg_s*)fb->priv;
if(errfb){
scale3->ow = 128;//ow;
scale3->oh = 96;//oh;
xm = 0;
ym = 0;
}else{
if(fb->len != (scale3_msg[sennum].ow * scale3_msg[sennum].oh * 3)/2 ){
scale3->ow = arg->ow;
scale3->oh = arg->oh;
xm = arg->ox;
ym = arg->oy;
}else{
scale3->ow = scale3_msg[sennum].ow;//ow;
scale3->oh = scale3_msg[sennum].oh;//oh;
xm = scale3_msg[sennum].x;
ym = scale3_msg[sennum].y;
}
}
scale3->iw = videow;//scale3_msg[sennum].iw;//iw;
scale3->ih = videoh;//scale3_msg[sennum].ih;//ih;
arg->yuv_arg.x = xm;//scale3_msg[sennum].x;
arg->yuv_arg.y = ym;//scale3_msg[sennum].y;
arg->yuv_arg.video_only = scale3_msg[sennum].video_only;
arg->yuv_arg.y_size = scale3->ow*scale3->oh;
arg->yuv_arg.out_w = scale3->ow;
arg->yuv_arg.out_h = scale3->oh;
// 暂时用同样的iw ih ow oh
scale_set_in_out_size(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
scale_set_step(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
scale_set_in_yaddr(scale3->scale_dev, (uint32)scale3->scaler3buf);
scale_set_in_uaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE);
scale_set_in_vaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE/4);
// _os_printf("M(%x %x)",fb,fb->data);
fb->len = scale3->ow * scale3->oh * 3 / 2;
// 配置新的空间地址
p_buf = (uint8_t *)fb->data;
scale_set_out_yaddr(scale3->scale_dev, (uint32)p_buf);
scale_set_out_uaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh);
scale_set_out_vaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh + scale3->ow * scale3->oh / 4);
if(errfb){
msi_delete_fb(NULL, fb);
return 0;
}
arg = (struct scale3_yuv_arg_s *)scale3->now_fb->priv;
scale3->now_fb->stype = FSTYPE_YUV_P0+video_msg.video_type_cur;
// 发送now_data,发送失败也要返回
if(arg->tx_type == video_msg.video_type_cur){
if (os_msgq_put(&scale3->msgq, (uint32_t)scale3->now_fb, 0))
{
// 正常不能中断del,但是这个模块是内部,只要del没有一些等待信号量操作,问题不大
msi_delete_fb(NULL, scale3->now_fb);
scale3->now_fb = NULL;
//return 0;
}
}else{
msi_delete_fb(NULL, scale3->now_fb);
}
scale3->now_fb = fb;
// os_printf("%s:%d\n",__FUNCTION__,__LINE__);
return 0;
}
static int32_t scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
{
//*(volatile uint32_t*)0x400e0124 |= (1<<14);
//*(volatile uint32_t*)0x400e0124 &= ~(1<<14);
return 0;
}
static int32_t scale3_stream_ov(uint32 irq_flag, uint32 irq_data, uint32 param1)
{
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
return 0;
}
static int32 scale3_stream_work(struct os_work *work)
{
int32_t ret;
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)work;
struct framebuff *fb;
struct scale3_yuv_arg_s *arg;
int32_t err = -1;
fb = (struct framebuff *)os_msgq_get2(&scale3->msgq, 0, &err);
// 没有数据
if (err)
{
goto scale3_stream_work_end;
}
arg = (struct scale3_yuv_arg_s*)fb->priv;
arg->yuv_arg.dispcnt++;
fb->mtype = F_YUV;
//_os_printf("P(%d x:%d y:%d)",fb->stype,arg->yuv_arg.x,arg->yuv_arg.y);
//os_printf("scale3 fb:%X type:%d x:%d y:%d w:%d h:%d\r\n",fb,fb->stype,arg->yuv_arg.x,arg->yuv_arg.y,arg->yuv_arg.out_w,arg->yuv_arg.out_h);
if(arg->tx_type == 4){
fbpool_put(&scale3->tx_poolerr, fb);
}else{
//_os_printf("<S %08x>",fb->data);
ret = msi_output_fb(scale3->msi, fb);
}
scale3_stream_work_end:
// 过1ms就去轮询一遍,实际如果用信号量,可以改成任务形式,等待信号量,可以节约cpu(实际cache影响可能更大,cpu占用很少)
// 由于workqueue没有支持等待信号量,只能通过1ms轮询一下
os_run_work_delay(work, 1);
return 0;
}
static int32_t scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
uint32 ie;
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)msi->priv;
struct scale3_yuv_arg_s *arg;
switch (cmd_id)
{
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
// 能进来这里,就是代表所有fb都已经用完了
case MSI_CMD_POST_DESTROY:
{
struct framebuff *fb;
// 释放资源fb资源文件
int temp_video_num = scale3->init_txpool_num;
for(int init_txpool_num = 0; init_txpool_num < temp_video_num ; init_txpool_num++) {
while (1)
{
fb = fbpool_get(&scale3->tx_pool0 + init_txpool_num, 0, NULL);
if (!fb)
{
break;
}
if(fb->data)
{
//os_printf("D(%x %x)\n",fb,fb->data);
STREAM_FREE(fb->data);
fb->data = NULL;
}
// 预分配空间释放
if (fb->priv)
{
//os_printf("D(%x %x)\n",fb,fb->priv);
STREAM_LIBC_FREE(fb->priv);
fb->priv = NULL;
}
}
fbpool_destroy(&scale3->tx_pool0 + init_txpool_num);
}
while (1)
{
fb = fbpool_get(&scale3->tx_poolerr, 0, NULL);
if (!fb)
{
break;
}
if(fb->data)
{
//os_printf("E(%x %x)\n",fb,fb->data);
STREAM_FREE(fb->data);
fb->data = NULL;
}
// 预分配空间释放
if (fb->priv)
{
//os_printf("E(%x %x)\n",fb,fb->priv);
STREAM_LIBC_FREE(fb->priv);
fb->priv = NULL;
}
}
fbpool_destroy(&scale3->tx_poolerr);
STREAM_LIBC_FREE(scale3);
msi->priv = NULL;
}
break;
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
case MSI_CMD_PRE_DESTROY:
{
os_work_cancle2(&scale3->work, 1);
scale_close(scale3->scale_dev);
// os_printf("%s:%d MSI_CMD_PRE_DESTROY\n", __FUNCTION__, __LINE__);
// 移除信号量里面的数据
struct framebuff *fb = NULL;
int32_t err = 0;
while (!err)
{
fb = (struct framebuff *)os_msgq_get2(&scale3->msgq, 0, &err);
if (fb)
{
msi_delete_fb(NULL, fb);
}
fb = NULL;
}
vppdone_func_unregister(SCALER3_DONE);
if (scale3->msgq.hdl) {
os_msgq_del(&scale3->msgq);
}
fb = scale3->now_fb;
if (scale3->now_fb)
{
msi_delete_fb(NULL, scale3->now_fb);
scale3->now_fb = NULL;
}
}
break;
// 接收,判断是类型是否可以支持压缩
case MSI_CMD_TRANS_FB:
{
}
break;
// 预先分配的,默认不需要释放fb->data,除非是MSI_CMD_DESTROY后,就要释放
case MSI_CMD_FREE_FB:
{
struct framebuff *fb = (struct framebuff *)param1;
uint8_t type = 0;
arg = (struct scale3_yuv_arg_s*)fb->priv;
if(arg->tx_type == 0){
type = 0;
}else if(arg->tx_type == 1){
type = 1;
}else if(arg->tx_type == 2){
type = 2;
}else{
type = 4;
}
if (fb->data && (type < 4))
{
ie = disable_irq();
if(fb->len != (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2){
STREAM_FREE(fb->data); //释放之前的空间
fb->data = (uint8_t *)STREAM_MALLOC((scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2); //申请到新的大空间
sys_dcache_invalid_range((void *)fb->data, (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2);
fb->len = (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2;
arg->ow = scale3_msg[type].ow;
arg->oh = scale3_msg[type].oh;
arg->ox = scale3_msg[type].x;
arg->oy = scale3_msg[type].y;
}
enable_irq(ie);
}
//这里要更改一下看put到哪里去
if(type == 0){
fbpool_put(&scale3->tx_pool0, fb);
}else if(type == 1){
fbpool_put(&scale3->tx_pool1, fb);
}else if(type == 2){
fbpool_put(&scale3->tx_pool2, fb);
}else{
fbpool_put(&scale3->tx_poolerr, fb);
}
// 不需要内核去释放fb
ret = RET_OK + 1;
}
break;
case MSI_CMD_SCALE3:
{
uint32_t cmd_self = (uint32_t)param1;
//uint32_t arg = param2;
// 自定义命令
switch (cmd_self)
{
case MSI_SCALE3_START:
{
//注意,这里需要根据vpp那边配置来决定用哪个
//注意line buf的数量
uint8_t video_type = 0;
uint8_t *p_buf;
uint16_t videow,videoh;
struct fbpool * tx_pool;
struct framebuff *fb;
scale3->scaler3buf = SCALE3_LINE_BUF;
os_msgq_init(&scale3->msgq, MAX_SCALE3_TX);
OS_WORK_INIT(&scale3->work, scale3_stream_work, 0);
os_run_work_delay(&scale3->work, 1);
if(video_msg.video_num == 1){
video_type = ISP_VIDEO_0;
}else if(video_msg.video_num == 2){
video_type = video_msg.video_type_last; //
}else{
if((video_msg.video_type_cur == ISP_VIDEO_1)||(video_msg.video_type_cur == ISP_VIDEO_2)){
video_type = ISP_VIDEO_0;
}else if(video_msg.video_type_last == ISP_VIDEO_1){
video_type = ISP_VIDEO_2;
}else if(video_msg.video_type_last == ISP_VIDEO_2){
video_type = ISP_VIDEO_1;
}
}
if (SCALE3_YUVBUF_0_1 == 0)
{
extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
get_vpp_w_h(&videow, &videoh);
}
else if (SCALE3_YUVBUF_0_1 == 1)
{
extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
get_vpp1_w_h(&videow, &videoh);
}
scale_set_start_addr(scale3->scale_dev, 0, 0);
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
scale_set_dma_to_memory(scale3->scale_dev, 1);
scale_set_data_from_vpp(scale3->scale_dev, 1);
scale_set_line_buf_num(scale3->scale_dev, SCALE3_YUVBUF_Y_OFF_LINE);
scale3->ow = scale3_msg[video_type].ow;//ow;
scale3->oh = scale3_msg[video_type].oh;//oh;
scale3->iw = videow;//scale3_msg[video_type].iw;//iw;
scale3->ih = videoh;//scale3_msg[video_type].ih;//ih;
// 暂时用同样的iw ih ow oh
scale_set_in_out_size(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
scale_set_step(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
scale_set_in_yaddr(scale3->scale_dev, (uint32)scale3->scaler3buf);
scale_set_in_uaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE);
scale_set_in_vaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE/4);
// 这里分配一下scale3的空间,通过标准接口去分配吧,理论这里一定能获取到,这里就不判断异常情况了
// 正常应该要获取到fb
if(scale3->txpool_type == 1){
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
}else{
if(video_type == ISP_VIDEO_0){
tx_pool = &scale3->tx_pool0;
}else if(video_type == ISP_VIDEO_1){
tx_pool = &scale3->tx_pool1;
}else{
tx_pool = &scale3->tx_pool2;
}
fb = fbpool_get(tx_pool, 0, scale3->msi);
}
arg = (struct scale3_yuv_arg_s*)fb->priv;
arg->yuv_arg.x = scale3_msg[video_type].x;
arg->yuv_arg.y = scale3_msg[video_type].y;
//os_printf("arg w:%d arg h:%d\r\n",arg->yuv_arg.out_w,arg->yuv_arg.out_h);
p_buf = fb->data;
scale3->now_fb = fb;
scale_set_out_yaddr(scale3->scale_dev, (uint32)p_buf);
scale_set_out_uaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh);
scale_set_out_vaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh + scale3->ow * scale3->oh / 4);
scale_request_irq(scale3->scale_dev, FRAME_END, scale3_stream_done, (uint32)scale3);
scale_request_irq(scale3->scale_dev, INBUF_OV, scale3_stream_ov, (uint32)scale3);
scale_open(scale3->scale_dev);
// 由于硬件需要vpp参与,所以这里会耦合了其他硬件模块
struct vpp_device *vpp_dev;
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
vpp_open(vpp_dev);
vppdone_func_register(SCALER3_DONE,scale3_vpp_done_func,(uint32)scale3);
}
break;
}
}
break;
default:
break;
}
return ret;
}
extern scale3_kick_fn scale3_kick_func;
int32_t scaler3_kick_start(){
struct msi *msi = msi_find(S_PREVIEW_SCALE3, 0);
msi_do_cmd(msi, MSI_CMD_SCALE3, MSI_SCALE3_START, 0);
msi_put(msi);
scale3_kick_func = NULL;
return 0;
}
// 参数分别是vpp的图像iw和ih,要scale的ow和oh,如果和屏有关,可以传入屏幕的宽高
struct msi *scale3_msi(const char *name)
{
struct msi *msi = msi_new(name, 0, NULL);
if(msi == NULL){
return NULL;
}
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)msi->priv;
struct scale_msg_t *scale_msg[3];
uint8_t *fbuf;
scale_msg[0] = &scale3_msg[0];
scale_msg[1] = &scale3_msg[1];
scale_msg[2] = &scale3_msg[2];
if (!scale3)
{
// os_printf("%s:%d new success\n", __FUNCTION__, __LINE__);
scale3 = (struct scale3_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_msi_s));
msi->action = scale3_msi_action;
msi->priv = (void *)scale3;
scale3->msi = msi;
scale3->scale_dev = (struct scale_device *)dev_get(HG_SCALE3_DEVID);
scale3->txpool_type = 0;
int temp_video_num = video_msg.video_num;
scale3->init_txpool_num = temp_video_num;
for(int init_txpool_num = 0; init_txpool_num < temp_video_num ; init_txpool_num++) {
int fbpool_init_size = 0;
//if (SCALE3_YUVBUF_0_1 == 0)
//{
// extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
//get_vpp_w_h(&scale_msg[init_txpool_num]->iw, &scale_msg[init_txpool_num]->ih);
//}
//else if (SCALE3_YUVBUF_0_1 == 1)
//{
// extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
//get_vpp1_w_h(&scale_msg[init_txpool_num]->iw, &scale_msg[init_txpool_num]->ih);
//}
switch (init_txpool_num)
{
/* txpool0 */
case 0:
{
fbpool_init_size = 2;
if (temp_video_num == 1) {
fbpool_init_size++;
scale3->txpool_type = 1;
}
}
break;
/* txpool1 */
case 1:
{
fbpool_init_size = 2;
if(temp_video_num > 2)
fbpool_init_size--;
}
break;
/* txpool2 */
case 2:
{
fbpool_init_size = 1;
}
break;
default:
break;
}
os_printf("scale3 init txpool num:%d size:%d txpool0:0x%x txpool1:0x%x txpool2:0x%x\r\n",init_txpool_num,fbpool_init_size, &scale3->tx_pool0 + 0, &scale3->tx_pool0 + 1, &scale3->tx_pool0 + 2);
fbpool_init(&scale3->tx_pool0 + init_txpool_num, fbpool_init_size);
for(int i = 0; i < fbpool_init_size; i++) {
struct scale3_yuv_arg_s *yuv_priv = (struct scale3_yuv_arg_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_yuv_arg_s));
struct yuv_arg_s *yuv = (struct yuv_arg_s *)yuv_priv;
scale3->ow = scale_msg[init_txpool_num]->ow;
scale3->oh = scale_msg[init_txpool_num]->oh;
yuv->y_size = scale3->ow * scale3->oh;
yuv->uv_off = 0;
yuv->y_off = 0;
yuv->out_w = scale3->ow;
yuv->out_h = scale3->oh;
yuv->del = &scale3->del;
yuv_priv->tx_type = init_txpool_num;
yuv_priv->ow = scale3->ow;
yuv_priv->oh = scale3->oh;
fbuf = (uint8_t *)STREAM_MALLOC(scale3->ow * scale3->oh * 3 / 2);
FBPOOL_SET_INFO(&scale3->tx_pool0 + init_txpool_num, i, fbuf, scale3->ow * scale3->oh * 3 / 2, (void *)yuv);
}
}
fbpool_init(&scale3->tx_poolerr, 1);
struct scale3_yuv_arg_s * yuv_priv = (struct scale3_yuv_arg_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_yuv_arg_s));
struct yuv_arg_s *yuv = (struct yuv_arg_s *)yuv_priv;
yuv->y_size = 128 * 96;
yuv->uv_off = 0;
yuv->y_off = 0;
yuv->out_w = 128;
yuv->out_h = 96;
yuv->del = &scale3->del;
scale3->ow = 128;
scale3->oh = 96;
yuv_priv->tx_type = 4;
fbuf = (uint8_t *)STREAM_MALLOC(128 * 96 * 3 / 2);
FBPOOL_SET_INFO(&scale3->tx_poolerr, 0, fbuf, 128 * 96 * 3 / 2, (void *)yuv);
msi->enable = 1;
scale3_kick_func = scaler3_kick_start;
}
os_printf("%s:%d\tmsi:%X\n", __FUNCTION__, __LINE__, msi);
return msi;
}
static int32_t const_scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct const_scale3_msi_s *scale3 = (struct const_scale3_msi_s *)msi->priv;
switch (cmd_id)
{
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
// 能进来这里,就是代表所有fb都已经用完了
case MSI_CMD_POST_DESTROY:
{
STREAM_LIBC_FREE(scale3);
}
break;
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
case MSI_CMD_PRE_DESTROY:
{
}
break;
default:
break;
}
return ret;
}
static int32_t const_scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
{
_os_printf("CO");
return 0;
}
void scale3_output_size_local_change(uint8_t id,uint8_t show_only,uint16 x,uint16 y,uint16 w,uint16 h){
uint32 ie;
ie = disable_irq();
scale3_msg[id].x = x;
scale3_msg[id].y = y;
scale3_msg[id].ow = w;
scale3_msg[id].oh = h;
scale3_msg[id].video_only = show_only;
enable_irq(ie);
}
//固定空间,由外部给空间,不再采用流的方式
//buf需要给够空间,根据ow和oh来计算
struct msi *scale3_msi_const_buf(const char *name, uint8_t *buf,uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh)
{
uint8_t isnew;
struct msi *msi = msi_new(name, 0, &isnew);
if (isnew)
{
struct scale_device *scale_dev = (struct scale_device *)dev_get(HG_SCALE3_DEVID);
os_printf("%s:%d new success\n", __FUNCTION__, __LINE__);
struct const_scale3_msi_s *scale3 = (struct const_scale3_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct const_scale3_msi_s));
scale3->scale_dev = scale_dev;
msi->priv = (void *)scale3;
msi->action = const_scale3_msi_action;
msi->enable = 0;
// 暂时用同样的iw ih ow oh
scale_set_in_out_size(scale_dev, iw, ih, ow, oh);
scale_set_step(scale_dev, iw, ih, ow, oh);
scale_set_start_addr(scale_dev, 0, 0);
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
scale_set_dma_to_memory(scale_dev, 1);
scale_set_data_from_vpp(scale_dev, 1);
scale_set_line_buf_num(scale_dev, 28);
scale_set_in_yaddr(scale_dev, (uint32)yuvbuf);
scale_set_in_uaddr(scale_dev, (uint32)yuvbuf + iw * 28);
scale_set_in_vaddr(scale_dev, (uint32)yuvbuf + iw * 28 + iw * 28/4);
scale_set_out_yaddr(scale_dev, (uint32)buf);
scale_set_out_uaddr(scale_dev, (uint32)buf + ow * oh);
scale_set_out_vaddr(scale_dev, (uint32)buf + ow * oh + ow * oh / 4);
scale_request_irq(scale_dev, FRAME_END, const_scale3_stream_done, (uint32)scale3);
scale_request_irq(scale_dev, INBUF_OV, scale3_stream_ov, (uint32)scale3);
scale_open(scale_dev);
// 由于硬件需要vpp参与,所以这里会耦合了其他硬件模块
struct vpp_device *vpp_dev;
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
vpp_open(vpp_dev);
}
os_printf("%s:%d\tmsi:%X\n", __FUNCTION__, __LINE__, msi);
return msi;
}