From 6e07d0e7137f6e7dea29ca7078ae4e60426fa25d Mon Sep 17 00:00:00 2001 From: "renjiang.han" Date: Wed, 15 Jul 2020 16:16:55 +0800 Subject: [PATCH] amlvideo2: The buffer is equipped with canvas every time it is used. [1/1] PD#SWPL-29593 Problem: Because each buffer is equipped with canvas, the canvas is not enough. Solution: Only use the canvas when the buffer is used, and allocate the canvas to the next buffer after use. Verify: on tm2-ab301 Change-Id: I98a5986f80471c05dfb5638c5404305c03aec867 Signed-off-by: renjiang.han --- .../amlogic/media/common/canvas/canvas_mgr.c | 1 - .../video_processor/video_dev/amlvideo2.c | 314 ++++++++++++------ 2 files changed, 210 insertions(+), 105 deletions(-) diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index d1b65d93d9a3..b4563e883d64 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -521,7 +521,6 @@ static void canvas_pool_config(void) canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr"); canvas_pool_register_const_canvas(0xe4, 0xef, "encoder"); canvas_pool_register_const_canvas(0x40, 0x48, "osd"); - canvas_pool_register_const_canvas(0xc0, 0xd7, "amlvideo2"); /*please add static canvas later. */ } diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index a136cf9fcdf4..38748dcf8c84 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -71,8 +71,6 @@ #include #define AVMLVIDEO2_MODULE_NAME "amlvideo2" -#define AMLVIDEO2_RES_CANVAS 0xc0 -#define AMLVIDEO2_1_RES_CANVAS 0xcc #define MULTI_NODE /* #define USE_SEMA_QBUF */ @@ -111,9 +109,7 @@ KERNEL_VERSION(\ #define DEVICE_NAME "amlvideo2.0" #endif -#define AMLVIDEO2_RES0_CANVAS_INDEX AMLVIDEO2_RES_CANVAS -#define AMLVIDEO2_RES1_CANVAS_INDEX AMLVIDEO2_1_RES_CANVAS - +#define BUFFER_COUNT 4 #define DUR2PTS(x) ((x) - ((x) >> 4)) #define DUR2PTS_RM(x) ((x) & 0xf) @@ -438,114 +434,162 @@ static struct v4l2_frmsize_discrete amlvideo2_prev_resolution[] = {{160, 120}, { static struct v4l2_frmsize_discrete amlvideo2_pic_resolution[] = {{1280, 960} }; +static int amlvideo2_canvas[2][2 * BUFFER_COUNT] = { + {-1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1} +}; + +static int yuv420_canvas[2][BUFFER_COUNT] = { + {-1, -1, -1, -1}, + {-1, -1, -1, -1} +}; + static unsigned int print_cvs_idx; module_param(print_cvs_idx, uint, 0644); MODULE_PARM_DESC(print_cvs_idx, "print canvas index\n"); int get_amlvideo2_canvas_index(struct amlvideo2_output *output, - int start_canvas) + int inst, int buffer_id) { -int canvas = start_canvas; -int v4l2_format = output->v4l2_format; -void *buf = (void *)output->vbuf; -int width = output->width; -int height = output->height; -int canvas_height = height; - -switch (v4l2_format) { -case V4L2_PIX_FMT_RGB565X: -case V4L2_PIX_FMT_VYUY: - canvas = start_canvas; - canvas_config(canvas, (unsigned long)buf, width * 2, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - break; -case V4L2_PIX_FMT_YUV444: -case V4L2_PIX_FMT_BGR24: -case V4L2_PIX_FMT_RGB24: - canvas = start_canvas; - canvas_config(canvas, (unsigned long)buf, width * 3, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - break; -case V4L2_PIX_FMT_RGB32: - canvas = start_canvas; - canvas_config(canvas, (unsigned long)buf, width * 4, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - break; -case V4L2_PIX_FMT_NV12: -case V4L2_PIX_FMT_NV21: - canvas_config(start_canvas, (unsigned long)buf, width, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(start_canvas + 1, (unsigned long)(buf + width * height), - width, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas = start_canvas | ((start_canvas + 1) << 8); - break; -case V4L2_PIX_FMT_YVU420: -case V4L2_PIX_FMT_YUV420: - canvas_config(start_canvas, (unsigned long)buf, width, canvas_height, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(start_canvas + 1, (unsigned long)(buf + width * height), - width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - canvas_config(start_canvas + 2, - (unsigned long)(buf + width * height * 5 / 4), - width / 2, canvas_height / 2, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); - if (v4l2_format == V4L2_PIX_FMT_YUV420) { - canvas = start_canvas | ((start_canvas + 1) << 8) - | ((start_canvas + 2) << 16); - } else { - canvas = start_canvas | ((start_canvas + 2) << 8) - | ((start_canvas + 1) << 16); - } - break; -default: - break; -} -if (print_cvs_idx == 1) { - pr_err("v4l2_format=%x, canvas=%x\n", v4l2_format, canvas); - print_cvs_idx = 0; -} -return canvas; -} -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ -int convert_canvas_index(struct amlvideo2_output *output, int start_canvas) -{ - int canvas = start_canvas; + int canvas = amlvideo2_canvas[inst][2 * buffer_id]; int v4l2_format = output->v4l2_format; + void *buf = (void *)output->vbuf; + int width = output->width; + int height = output->height; + int canvas_height = height; + const char *canvas_owner0 = "amlvideo2.0"; + const char *canvas_owner1 = "amlvideo2.1"; + + if (canvas < 0) + return -1; switch (v4l2_format) { case V4L2_PIX_FMT_RGB565X: case V4L2_PIX_FMT_VYUY: - canvas = start_canvas; + canvas_config(canvas, (unsigned long)buf, + width * 2, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + break; + case V4L2_PIX_FMT_YUV444: + case V4L2_PIX_FMT_BGR24: + case V4L2_PIX_FMT_RGB24: + canvas_config(canvas, (unsigned long)buf, + width * 3, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + break; + case V4L2_PIX_FMT_RGB32: + canvas_config(canvas, (unsigned long)buf, + width * 4, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + if (amlvideo2_canvas[inst][2 * buffer_id + 1] < 0) + return -1; + canvas_config(amlvideo2_canvas[inst][2 * buffer_id], + (unsigned long)buf, width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(amlvideo2_canvas[inst][2 * buffer_id + 1], + (unsigned long)(buf + width * height), + width, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (amlvideo2_canvas[inst][2 * buffer_id + 1] << 8); + break; + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV420: + if (amlvideo2_canvas[inst][2 * buffer_id + 1] < 0) + return -1; + + if (yuv420_canvas[inst][buffer_id] < 0) + yuv420_canvas[inst][buffer_id] = + canvas_pool_map_alloc_canvas((inst == 0) ? + canvas_owner0 : + canvas_owner1); + if (yuv420_canvas[inst][buffer_id] < 0) + return -1; + canvas_config(amlvideo2_canvas[inst][2 * buffer_id], + (unsigned long)buf, width, canvas_height, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(amlvideo2_canvas[inst][2 * buffer_id + 1], + (unsigned long)(buf + width * height), + width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(yuv420_canvas[inst][buffer_id], + (unsigned long)(buf + width * height * 5 / 4), + width / 2, canvas_height / 2, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + if (v4l2_format == V4L2_PIX_FMT_YUV420) { + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (amlvideo2_canvas[inst][2 * buffer_id + 1] + << 8) | (yuv420_canvas[inst][buffer_id] + << 16); + } else { + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (yuv420_canvas[inst][buffer_id] << 8) + | (amlvideo2_canvas[inst][2 * buffer_id + 1] + << 16); + } + break; + default: + break; + } + if (print_cvs_idx == 1) { + pr_err("v4l2_format=%x, canvas=%x\n", v4l2_format, canvas); + print_cvs_idx = 0; + } + return canvas; +} +/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ +int convert_canvas_index(struct amlvideo2_output *output, + int inst, int buffer_id) +{ + int canvas = amlvideo2_canvas[inst][2 * buffer_id]; + int v4l2_format = output->v4l2_format; + const char *canvas_owner0 = "amlvideo2.0"; + const char *canvas_owner1 = "amlvideo2.1"; + + if (canvas < 0) + return -1; + + switch (v4l2_format) { + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_VYUY: + canvas = amlvideo2_canvas[inst][2 * buffer_id]; break; case V4L2_PIX_FMT_YUV444: case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_RGB32: - canvas = start_canvas; + canvas = amlvideo2_canvas[inst][2 * buffer_id]; break; case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: - canvas = start_canvas | ((start_canvas + 1) << 8); + if (amlvideo2_canvas[inst][2 * buffer_id + 1] < 0) + return -1; + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (amlvideo2_canvas[inst][2 * buffer_id + 1] << 8); break; case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YUV420: - if (v4l2_format == V4L2_PIX_FMT_YUV420) { - canvas = start_canvas | ((start_canvas + 1) << 8) - | ((start_canvas + 2) << 16); - } else { - canvas = start_canvas | ((start_canvas + 2) << 8) - | ((start_canvas + 1) << 16); - } + if (amlvideo2_canvas[inst][2 * buffer_id + 1] < 0) + return -1; + if (yuv420_canvas[inst][buffer_id] < 0) + yuv420_canvas[inst][buffer_id] = + canvas_pool_map_alloc_canvas((inst == 0) ? + canvas_owner0 : + canvas_owner1); + if (yuv420_canvas[inst][buffer_id] < 0) + return -1; + + if (v4l2_format == V4L2_PIX_FMT_YUV420) + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (amlvideo2_canvas[inst][2 * buffer_id + 1] << 8) + | (yuv420_canvas[inst][buffer_id] << 16); + else + canvas = amlvideo2_canvas[inst][2 * buffer_id] + | (yuv420_canvas[inst][buffer_id] << 8) + | (amlvideo2_canvas[inst][2 * buffer_id + 1] << 16); break; default: break; @@ -3022,7 +3066,7 @@ int amlvideo2_ge2d_multi_pre_process(struct vframe_s *vf, int current_mirror; int cur_angle = 0; int output_canvas = output->canvas_id; - int temp_canvas = AMLVIDEO2_1_RES_CANVAS + 8; + int temp_canvas; unsigned long temp_start = node->vid_dev->buffer_start + (CMA_ALLOC_SIZE * SZ_1M); int temp_w = vf->width/4; @@ -3040,6 +3084,16 @@ int amlvideo2_ge2d_multi_pre_process(struct vframe_s *vf, vf->width, vf->height); } + if (yuv420_canvas[node->vid][0] < 0) + yuv420_canvas[node->vid][0] = + canvas_pool_map_alloc_canvas("amlvideo2.1"); + if (yuv420_canvas[node->vid][0] < 0) { + pr_info("amlvideo2 has no canvas to use %d\n", __LINE__); + return -1; + } + + temp_canvas = yuv420_canvas[node->vid][0]; + if (amlvideo2_scaledown1 == 0) { context->config.h_scale_coef_type = FILTER_TYPE_BICUBIC; context->config.v_scale_coef_type = FILTER_TYPE_BICUBIC; @@ -3722,21 +3776,21 @@ static int amlvideo2_fillbuff(struct amlvideo2_fh *fh, output.vbuf = vbuf; output.width = buf->vb.width; output.height = buf->vb.height; - output.canvas_id = buf->canvas_id; output.angle = node->qctl_regs[0]; output.frame = &buf->axis; output.info.mode = node->mode; memcpy(&output.info.display_info, &(node->display_info), sizeof(struct vdisplay_info_s)); - if (output.canvas_id == 0) { - output.canvas_id = get_amlvideo2_canvas_index( - &output, (node->vid == 0) ? - (AMLVIDEO2_RES0_CANVAS_INDEX + buf->vb.i * 3) : - (AMLVIDEO2_RES1_CANVAS_INDEX + buf->vb.i * 3)); - buf->canvas_id = output.canvas_id; + output.canvas_id = + get_amlvideo2_canvas_index(&output, node->vid, buf->vb.i); + if (output.canvas_id < 0) { + pr_info("amlvideo2: has no canvas value, %d\n", __LINE__); + return -1; } + //buf->canvas_id = output.canvas_id; + switch (output.v4l2_format) { case V4L2_PIX_FMT_RGB565X: case V4L2_PIX_FMT_YUV444: @@ -4132,7 +4186,8 @@ static int amlvideo2_thread_tick(struct amlvideo2_fh *fh) else pr_info("node1 fillbuff start .\n"); } - amlvideo2_fillbuff(fh, buf, vf); + if (amlvideo2_fillbuff(fh, buf, vf) < 0) + pr_info("amlvideo2 fill buff error!\n"); if (amlvideo2_dbg_en & 2) { if (node->vid == 0) pr_info("node0 fillbuff end .\n"); @@ -4907,10 +4962,10 @@ static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) output.width = fh->width; output.height = fh->height; output.canvas_id = -1; - p->reserved = convert_canvas_index( - &output, fh->node->vid == 0 ? - (AMLVIDEO2_RES0_CANVAS_INDEX + p->index * 3) : - (AMLVIDEO2_RES1_CANVAS_INDEX + p->index * 3)); + p->reserved = + convert_canvas_index(&output, fh->node->vid, p->index); + if (p->reserved == (u32)-1) + pr_info("amlvideo2 canvas alloc failed, %d\n", __LINE__); } else { p->reserved = 0; } @@ -5830,6 +5885,10 @@ static int amlvideo2_open(struct file *file) struct amlvideo2_fh *fh = NULL; struct videobuf_res_privdata *res = NULL; struct resource *reserve = NULL; + int temp_canvas; + const char *canvas_owner0 = "amlvideo2.0"; + const char *canvas_owner1 = "amlvideo2.1"; + int i; int ret; mutex_lock(&node->mutex); @@ -5869,6 +5928,35 @@ static int amlvideo2_open(struct file *file) return -ENOMEM; } + if (node->vid == 0) { + for (i = 0; i < 2 * BUFFER_COUNT; i++) { + amlvideo2_canvas[0][i] = + canvas_pool_map_alloc_canvas(canvas_owner0); + } + } else { + for (i = 0; i < 2 * BUFFER_COUNT; i++) { + amlvideo2_canvas[1][i] = + canvas_pool_map_alloc_canvas(canvas_owner1); + } + } + + for (i = 0; i < 2 * BUFFER_COUNT; i++) + if (amlvideo2_canvas[node->vid][i] < 0) + break; + if (i != 2 * BUFFER_COUNT && amlvideo2_canvas[node->vid][i] < 0) { + for (i = 0; i < 2 * BUFFER_COUNT; i++) { + if (amlvideo2_canvas[node->vid][i] >= 0) { + temp_canvas = amlvideo2_canvas[node->vid][i]; + canvas_pool_map_free_canvas(temp_canvas); + amlvideo2_canvas[node->vid][i] = -1; + } + } + pr_info("%s: %s alloc canvas failed, %d\n", + (node->vid == 0) ? canvas_owner0 : canvas_owner1, + __func__, __LINE__); + return -ENOMEM; + } + fh = node->fh; if (fh == NULL) { node->users--; @@ -5954,10 +6042,28 @@ static int amlvideo2_close(struct file *file) { struct amlvideo2_fh *fh = file->private_data; struct amlvideo2_node *node = fh->node; + int temp_canvas; + int i; videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); amlvideo2_cma_buf_uninit(node->vid_dev, node->vid); + + for (i = 0; i < 2 * BUFFER_COUNT; i++) { + if (amlvideo2_canvas[node->vid][i] >= 0) { + temp_canvas = amlvideo2_canvas[node->vid][i]; + canvas_pool_map_free_canvas(temp_canvas); + amlvideo2_canvas[node->vid][i] = -1; + } + } + + for (i = 0; i < BUFFER_COUNT; i++) { + if (yuv420_canvas[node->vid][i] >= 0) { + temp_canvas = yuv420_canvas[node->vid][i]; + canvas_pool_map_free_canvas(temp_canvas); + yuv420_canvas[node->vid][i] = -1; + } + } mutex_lock(&node->mutex); if (node->r_type == AML_RECEIVER_NONE) { /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */