mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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 <renjiang.han@amlogic.com>
This commit is contained in:
@@ -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. */
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,6 @@
|
||||
#include <linux/sched/rt.h>
|
||||
|
||||
#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 */
|
||||
|
||||
Reference in New Issue
Block a user