[media] coda: add support for partial interleaved YCbCr 4:2:0 (NV12) format

This patch adds support for the two-plane NV12 format with one luma plane
and one interleaved chroma plane.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Kamil Debski <k.debski@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Philipp Zabel 2014-09-29 09:53:47 -03:00 committed by Mauro Carvalho Chehab
parent 2bf299cd46
commit 1cb12cf3c0
2 changed files with 29 additions and 5 deletions

View File

@ -729,6 +729,9 @@ static int coda_start_encoding(struct coda_ctx *ctx)
break; break;
} }
ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
if (q_data_src->fourcc == V4L2_PIX_FMT_NV12)
ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
if (dev->devtype->product == CODA_DX6) { if (dev->devtype->product == CODA_DX6) {
@ -1128,7 +1131,6 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE); coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
if (dev->devtype->product == CODA_960) { if (dev->devtype->product == CODA_960) {
coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX); coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE); coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE);
@ -1273,7 +1275,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
u32 bitstream_buf, bitstream_size; u32 bitstream_buf, bitstream_size;
struct coda_dev *dev = ctx->dev; struct coda_dev *dev = ctx->dev;
int width, height; int width, height;
u32 src_fourcc; u32 src_fourcc, dst_fourcc;
u32 val; u32 val;
int ret; int ret;
@ -1283,6 +1285,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
bitstream_buf = ctx->bitstream.paddr; bitstream_buf = ctx->bitstream.paddr;
bitstream_size = ctx->bitstream.size; bitstream_size = ctx->bitstream.size;
src_fourcc = q_data_src->fourcc; src_fourcc = q_data_src->fourcc;
dst_fourcc = q_data_dst->fourcc;
/* Allocate per-instance buffers */ /* Allocate per-instance buffers */
ret = coda_alloc_context_buffers(ctx, q_data_src); ret = coda_alloc_context_buffers(ctx, q_data_src);
@ -1294,6 +1297,9 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
/* Update coda bitstream read and write pointers from kfifo */ /* Update coda bitstream read and write pointers from kfifo */
coda_kfifo_sync_to_device_full(ctx); coda_kfifo_sync_to_device_full(ctx);
ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
if (dst_fourcc == V4L2_PIX_FMT_NV12)
ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
ctx->display_idx = -1; ctx->display_idx = -1;
@ -1424,13 +1430,23 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
} }
if (dev->devtype->product == CODA_960) { if (dev->devtype->product == CODA_960) {
coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); int cbb_size, crb_size;
coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
/* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */
coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE); coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
if (dst_fourcc == V4L2_PIX_FMT_NV12) {
cbb_size = 0;
crb_size = 16;
} else {
cbb_size = 8;
crb_size = 8;
}
coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET | coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | cbb_size << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, crb_size << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
CODA9_CMD_SET_FRAME_CACHE_CONFIG); CODA9_CMD_SET_FRAME_CACHE_CONFIG);
} }

View File

@ -95,6 +95,7 @@ void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
base_cb = base_cr + q_data->bytesperline * q_data->height / 4; base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
break; break;
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_NV12:
default: default:
base_cb = base_y + q_data->bytesperline * q_data->height; base_cb = base_y + q_data->bytesperline * q_data->height;
base_cr = base_cb + q_data->bytesperline * q_data->height / 4; base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
@ -118,6 +119,10 @@ static const struct coda_fmt coda_formats[] = {
.name = "YUV 4:2:0 Planar, YCrCb", .name = "YUV 4:2:0 Planar, YCrCb",
.fourcc = V4L2_PIX_FMT_YVU420, .fourcc = V4L2_PIX_FMT_YVU420,
}, },
{
.name = "YUV 4:2:0 Partial interleaved Y/CbCr",
.fourcc = V4L2_PIX_FMT_NV12,
},
{ {
.name = "H264 Encoded Stream", .name = "H264 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H264, .fourcc = V4L2_PIX_FMT_H264,
@ -162,6 +167,7 @@ static bool coda_format_is_yuv(u32 fourcc)
switch (fourcc) { switch (fourcc) {
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
return true; return true;
default: default:
return false; return false;
@ -366,6 +372,7 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
switch (f->fmt.pix.pixelformat) { switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_MPEG4: case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_JPEG:
@ -380,6 +387,7 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
switch (f->fmt.pix.pixelformat) { switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
/* Frame stride must be multiple of 8, but 16 for h.264 */ /* Frame stride must be multiple of 8, but 16 for h.264 */
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *