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

768 lines
23 KiB
C
Raw Permalink Normal View History

#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;
}