diff options
Diffstat (limited to 'drivers/media/platform/coda/coda-bit.c')
-rw-r--r-- | drivers/media/platform/coda/coda-bit.c | 322 |
1 files changed, 199 insertions, 123 deletions
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 9b8ea8bbeb4e..b4029ae293d3 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -217,11 +217,34 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx, void coda_fill_bitstream(struct coda_ctx *ctx) { struct vb2_buffer *src_buf; - struct coda_timestamp *ts; + struct coda_buffer_meta *meta; + u32 start; while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { + /* + * Only queue a single JPEG into the bitstream buffer, except + * to increase payload over 512 bytes or if in hold state. + */ + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && + (coda_get_bitstream_payload(ctx) >= 512) && !ctx->hold) + break; + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + /* Drop frames that do not start/end with a SOI/EOI markers */ + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && + !coda_jpeg_check_buffer(ctx, src_buf)) { + v4l2_err(&ctx->dev->v4l2_dev, + "dropping invalid JPEG frame\n"); + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); + continue; + } + + /* Buffer start position */ + start = ctx->bitstream_fifo.kfifo.in & + ctx->bitstream_fifo.kfifo.mask; + if (coda_bitstream_try_queue(ctx, src_buf)) { /* * Source buffer is queued in the bitstream ringbuffer; @@ -229,12 +252,16 @@ void coda_fill_bitstream(struct coda_ctx *ctx) */ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - ts = kmalloc(sizeof(*ts), GFP_KERNEL); - if (ts) { - ts->sequence = src_buf->v4l2_buf.sequence; - ts->timecode = src_buf->v4l2_buf.timecode; - ts->timestamp = src_buf->v4l2_buf.timestamp; - list_add_tail(&ts->list, &ctx->timestamp_list); + meta = kmalloc(sizeof(*meta), GFP_KERNEL); + if (meta) { + meta->sequence = src_buf->v4l2_buf.sequence; + meta->timecode = src_buf->v4l2_buf.timecode; + meta->timestamp = src_buf->v4l2_buf.timestamp; + meta->start = start; + meta->end = ctx->bitstream_fifo.kfifo.in & + ctx->bitstream_fifo.kfifo.mask; + list_add_tail(&meta->list, + &ctx->buffer_meta_list); } v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); @@ -691,6 +718,7 @@ static int coda_start_encoding(struct coda_ctx *ctx) struct vb2_buffer *buf; int gamma, ret, value; u32 dst_fourcc; + u32 stride; q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); @@ -710,6 +738,14 @@ static int coda_start_encoding(struct coda_ctx *ctx) return -EFAULT; } + if (dst_fourcc == V4L2_PIX_FMT_JPEG) { + if (!ctx->params.jpeg_qmat_tab[0]) + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); + if (!ctx->params.jpeg_qmat_tab[1]) + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); + } + mutex_lock(&dev->coda_mutex); coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); @@ -729,10 +765,10 @@ static int coda_start_encoding(struct coda_ctx *ctx) break; } - value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL); - value &= ~(1 << 2 | 0x7 << 9); - ctx->frame_mem_ctrl = value; - coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL); + 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); if (dev->devtype->product == CODA_DX6) { /* Configure the coda */ @@ -741,6 +777,7 @@ static int coda_start_encoding(struct coda_ctx *ctx) } /* Could set rotation here if needed */ + value = 0; switch (dev->devtype->product) { case CODA_DX6: value = (q_data_src->width & CODADX6_PICWIDTH_MASK) @@ -764,6 +801,8 @@ static int coda_start_encoding(struct coda_ctx *ctx) << CODA_PICHEIGHT_OFFSET; } coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); + if (dst_fourcc == V4L2_PIX_FMT_JPEG) + ctx->params.framerate = 0; coda_write(dev, ctx->params.framerate, CODA_CMD_ENC_SEQ_SRC_F_RATE); @@ -797,6 +836,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) } coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); break; + case V4L2_PIX_FMT_JPEG: + coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA); + coda_write(dev, ctx->params.jpeg_restart_interval, + CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET); + + coda_jpeg_write_tables(ctx); + break; default: v4l2_err(v4l2_dev, "dst format (0x%08x) invalid.\n", dst_fourcc); @@ -804,28 +853,36 @@ static int coda_start_encoding(struct coda_ctx *ctx) goto out; } - switch (ctx->params.slice_mode) { - case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: - value = 0; - break; - case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: - value = (ctx->params.slice_max_mb & CODA_SLICING_SIZE_MASK) - << CODA_SLICING_SIZE_OFFSET; - value |= (1 & CODA_SLICING_UNIT_MASK) - << CODA_SLICING_UNIT_OFFSET; - value |= 1 & CODA_SLICING_MODE_MASK; - break; - case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: - value = (ctx->params.slice_max_bits & CODA_SLICING_SIZE_MASK) - << CODA_SLICING_SIZE_OFFSET; - value |= (0 & CODA_SLICING_UNIT_MASK) - << CODA_SLICING_UNIT_OFFSET; - value |= 1 & CODA_SLICING_MODE_MASK; - break; + /* + * slice mode and GOP size registers are used for thumb size/offset + * in JPEG mode + */ + if (dst_fourcc != V4L2_PIX_FMT_JPEG) { + switch (ctx->params.slice_mode) { + case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: + value = 0; + break; + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: + value = (ctx->params.slice_max_mb & + CODA_SLICING_SIZE_MASK) + << CODA_SLICING_SIZE_OFFSET; + value |= (1 & CODA_SLICING_UNIT_MASK) + << CODA_SLICING_UNIT_OFFSET; + value |= 1 & CODA_SLICING_MODE_MASK; + break; + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: + value = (ctx->params.slice_max_bits & + CODA_SLICING_SIZE_MASK) + << CODA_SLICING_SIZE_OFFSET; + value |= (0 & CODA_SLICING_UNIT_MASK) + << CODA_SLICING_UNIT_OFFSET; + value |= 1 & CODA_SLICING_MODE_MASK; + break; + } + coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); + value = ctx->params.gop_size & CODA_GOP_SIZE_MASK; + coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); } - coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); - value = ctx->params.gop_size & CODA_GOP_SIZE_MASK; - coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); if (ctx->params.bitrate) { /* Rate control enabled */ @@ -916,19 +973,24 @@ static int coda_start_encoding(struct coda_ctx *ctx) goto out; } - if (dev->devtype->product == CODA_960) - ctx->num_internal_frames = 4; - else - ctx->num_internal_frames = 2; - ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); - if (ret < 0) { - v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); - goto out; + if (dst_fourcc != V4L2_PIX_FMT_JPEG) { + if (dev->devtype->product == CODA_960) + ctx->num_internal_frames = 4; + else + ctx->num_internal_frames = 2; + ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); + if (ret < 0) { + v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); + goto out; + } + stride = q_data_src->bytesperline; + } else { + ctx->num_internal_frames = 0; + stride = 0; } - coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); - coda_write(dev, q_data_src->bytesperline, - CODA_CMD_SET_FRAME_BUF_STRIDE); + coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE); + if (dev->devtype->product == CODA_7541) { coda_write(dev, q_data_src->bytesperline, CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); @@ -1036,9 +1098,10 @@ static int coda_prepare_encode(struct coda_ctx *ctx) struct coda_dev *dev = ctx->dev; int force_ipicture; int quant_param = 0; - u32 picture_y, picture_cb, picture_cr; u32 pic_stream_buffer_addr, pic_stream_buffer_size; + u32 rot_mode = 0; u32 dst_fourcc; + u32 reg; src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); @@ -1076,7 +1139,7 @@ static int coda_prepare_encode(struct coda_ctx *ctx) ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]; - pic_stream_buffer_size = CODA_MAX_FRAME_SIZE - + pic_stream_buffer_size = q_data_dst->sizeimage - ctx->vpu_header_size[0] - ctx->vpu_header_size[1] - ctx->vpu_header_size[2]; @@ -1090,7 +1153,7 @@ static int coda_prepare_encode(struct coda_ctx *ctx) } else { pic_stream_buffer_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); - pic_stream_buffer_size = CODA_MAX_FRAME_SIZE; + pic_stream_buffer_size = q_data_dst->sizeimage; } if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { @@ -1102,6 +1165,9 @@ static int coda_prepare_encode(struct coda_ctx *ctx) case V4L2_PIX_FMT_MPEG4: quant_param = ctx->params.mpeg4_intra_qp; break; + case V4L2_PIX_FMT_JPEG: + quant_param = 30; + break; default: v4l2_warn(&ctx->dev->v4l2_dev, "cannot set intra qp, fmt not supported\n"); @@ -1124,42 +1190,22 @@ static int coda_prepare_encode(struct coda_ctx *ctx) } /* submit */ - coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, - CODA_CMD_ENC_PIC_ROT_MODE); + if (ctx->params.rot_mode) + rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode; + coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE); coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); - - picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); - switch (q_data_src->fourcc) { - case V4L2_PIX_FMT_YVU420: - /* Switch Cb and Cr for YVU420 format */ - picture_cr = picture_y + q_data_src->bytesperline * - q_data_src->height; - picture_cb = picture_cr + q_data_src->bytesperline / 2 * - q_data_src->height / 2; - break; - case V4L2_PIX_FMT_YUV420: - default: - picture_cb = picture_y + q_data_src->bytesperline * - q_data_src->height; - picture_cr = picture_cb + q_data_src->bytesperline / 2 * - q_data_src->height / 2; - break; - } - if (dev->devtype->product == CODA_960) { 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, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); - coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y); - coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB); - coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR); + reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y; } else { - coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); - coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); - coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); + reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y; } + coda_write_base(ctx, q_data_src, src_buf, reg); + coda_write(dev, force_ipicture << 1 & 0x2, CODA_CMD_ENC_PIC_OPTION); @@ -1293,7 +1339,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx) u32 bitstream_buf, bitstream_size; struct coda_dev *dev = ctx->dev; int width, height; - u32 src_fourcc; + u32 src_fourcc, dst_fourcc; u32 val; int ret; @@ -1303,6 +1349,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx) bitstream_buf = ctx->bitstream.paddr; bitstream_size = ctx->bitstream.size; src_fourcc = q_data_src->fourcc; + dst_fourcc = q_data_dst->fourcc; /* Allocate per-instance buffers */ ret = coda_alloc_context_buffers(ctx, q_data_src); @@ -1314,6 +1361,11 @@ static int __coda_start_decoding(struct coda_ctx *ctx) /* Update coda bitstream read and write pointers from kfifo */ 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); + ctx->display_idx = -1; ctx->frm_dis_flg = 0; coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); @@ -1327,6 +1379,8 @@ static int __coda_start_decoding(struct coda_ctx *ctx) if ((dev->devtype->product == CODA_7541) || (dev->devtype->product == CODA_960)) val |= CODA_REORDER_ENABLE; + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) + val |= CODA_NO_INT_ENABLE; coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); ctx->params.codec_mode = ctx->codec->mode; @@ -1442,13 +1496,23 @@ static int __coda_start_decoding(struct coda_ctx *ctx) } 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); + + 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 | 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | - 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | - 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, + cbb_size << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | + crb_size << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, CODA9_CMD_SET_FRAME_CACHE_CONFIG); } @@ -1501,20 +1565,11 @@ static int coda_prepare_decode(struct coda_ctx *ctx) struct vb2_buffer *dst_buf; struct coda_dev *dev = ctx->dev; struct coda_q_data *q_data_dst; - u32 stridey, height; - u32 picture_y, picture_cb, picture_cr; + u32 reg_addr, reg_stride; dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ctx->params.rot_mode & CODA_ROT_90) { - stridey = q_data_dst->height; - height = q_data_dst->width; - } else { - stridey = q_data_dst->width; - height = q_data_dst->height; - } - /* Try to copy source buffer contents into the bitstream ringbuffer */ mutex_lock(&ctx->bitstream_mutex); coda_fill_bitstream(ctx); @@ -1545,17 +1600,6 @@ static int coda_prepare_decode(struct coda_ctx *ctx) if (dev->devtype->product == CODA_960) coda_set_gdi_regs(ctx); - /* Set rotator output */ - picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); - if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { - /* Switch Cr and Cb for YVU420 format */ - picture_cr = picture_y + stridey * height; - picture_cb = picture_cr + stridey / 2 * height / 2; - } else { - picture_cb = picture_y + stridey * height; - picture_cr = picture_cb + stridey / 2 * height / 2; - } - if (dev->devtype->product == CODA_960) { /* * The CODA960 seems to have an internal list of buffers with @@ -1565,16 +1609,16 @@ static int coda_prepare_decode(struct coda_ctx *ctx) */ coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index, CODA9_CMD_DEC_PIC_ROT_INDEX); - coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y); - coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB); - coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR); - coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE); + + reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y; + reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE; } else { - coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); - coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); - coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); - coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); + reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y; + reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE; } + coda_write_base(ctx, q_data_dst, dst_buf, reg_addr); + coda_write(dev, q_data_dst->bytesperline, reg_stride); + coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, CODA_CMD_DEC_PIC_ROT_MODE); @@ -1599,6 +1643,26 @@ static int coda_prepare_decode(struct coda_ctx *ctx) coda_write(dev, ctx->iram_info.axi_sram_use, CODA7_REG_BIT_AXI_SRAM_USE); + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) { + struct coda_buffer_meta *meta; + + /* If this is the last buffer in the bitstream, add padding */ + meta = list_first_entry(&ctx->buffer_meta_list, + struct coda_buffer_meta, list); + if (meta->end == (ctx->bitstream_fifo.kfifo.in & + ctx->bitstream_fifo.kfifo.mask)) { + static unsigned char buf[512]; + unsigned int pad; + + /* Pad to multiple of 256 and then add 256 more */ + pad = ((0 - meta->end) & 0xff) + 256; + + memset(buf, 0xff, sizeof(buf)); + + kfifo_in(&ctx->bitstream_fifo, buf, pad); + } + } + coda_kfifo_sync_to_device_full(ctx); coda_command_async(ctx, CODA_COMMAND_PIC_RUN); @@ -1612,7 +1676,8 @@ static void coda_finish_decode(struct coda_ctx *ctx) struct coda_q_data *q_data_src; struct coda_q_data *q_data_dst; struct vb2_buffer *dst_buf; - struct coda_timestamp *ts; + struct coda_buffer_meta *meta; + unsigned long payload; int width, height; int decoded_idx; int display_idx; @@ -1739,23 +1804,23 @@ static void coda_finish_decode(struct coda_ctx *ctx) val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; val -= ctx->sequence_offset; mutex_lock(&ctx->bitstream_mutex); - if (!list_empty(&ctx->timestamp_list)) { - ts = list_first_entry(&ctx->timestamp_list, - struct coda_timestamp, list); - list_del(&ts->list); - if (val != (ts->sequence & 0xffff)) { + if (!list_empty(&ctx->buffer_meta_list)) { + meta = list_first_entry(&ctx->buffer_meta_list, + struct coda_buffer_meta, list); + list_del(&meta->list); + if (val != (meta->sequence & 0xffff)) { v4l2_err(&dev->v4l2_dev, "sequence number mismatch (%d(%d) != %d)\n", val, ctx->sequence_offset, - ts->sequence); + meta->sequence); } - ctx->frame_timestamps[decoded_idx] = *ts; - kfree(ts); + ctx->frame_metas[decoded_idx] = *meta; + kfree(meta); } else { v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n"); - memset(&ctx->frame_timestamps[decoded_idx], 0, - sizeof(struct coda_timestamp)); - ctx->frame_timestamps[decoded_idx].sequence = val; + memset(&ctx->frame_metas[decoded_idx], 0, + sizeof(struct coda_buffer_meta)); + ctx->frame_metas[decoded_idx].sequence = val; } mutex_unlock(&ctx->bitstream_mutex); @@ -1794,11 +1859,22 @@ static void coda_finish_decode(struct coda_ctx *ctx) V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME); dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx]; - ts = &ctx->frame_timestamps[ctx->display_idx]; - dst_buf->v4l2_buf.timecode = ts->timecode; - dst_buf->v4l2_buf.timestamp = ts->timestamp; - - vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); + meta = &ctx->frame_metas[ctx->display_idx]; + dst_buf->v4l2_buf.timecode = meta->timecode; + dst_buf->v4l2_buf.timestamp = meta->timestamp; + + switch (q_data_dst->fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_NV12: + default: + payload = width * height * 3 / 2; + break; + case V4L2_PIX_FMT_YUV422P: + payload = width * height * 2; + break; + } + vb2_set_plane_payload(dst_buf, 0, payload); v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); |