summaryrefslogtreecommitdiff
authorSong Zhao <song.zhao@amlogic.com>2019-12-18 05:35:41 (GMT)
committer Nanxin Qin <nanxin.qin@amlogic.com>2020-02-13 06:12:46 (GMT)
commit68fcded9327dc8dfbd06fe9fefa4f4f715e8ab3a (patch)
tree565760cea9868ce429a30dd14912236a4b0ea5df
parenta20abedfa9b73263836765158c84e4ab5b10fd7d (diff)
downloadmedia_modules-68fcded9327dc8dfbd06fe9fefa4f4f715e8ab3a.zip
media_modules-68fcded9327dc8dfbd06fe9fefa4f4f715e8ab3a.tar.gz
media_modules-68fcded9327dc8dfbd06fe9fefa4f4f715e8ab3a.tar.bz2
v4l2: mpeg2: support multi-planar [1/1]
PD#SWPL-12624 Problem: 1. Enable V4L2 Mpeg2 decoder 2. Enable V4L2 Mpeg2 ucode parser to support secure mode Solution: * Use canvas linear mode * Support NV21 * Add frame dump feature in aml_port * Use width/heigh from IF layer before ucode is enable to parse it, it will make sure canvas is correctly configured (not 0 width and height). * Add 00 00 01 00 padding for every frame in unsecure mode * pass buffer margin number from interface to decoder. Make sure vdec_mpeg12_hw_s->buf_num and aml_vcodec_ctx->dpb_size are in sync. * use completion to wait for decoder to parse the stream * Also limite the buffer number returned from REQBUFS to ctx->dbp_size It will prevent application from allocate more memory than enough. Verify: U212 Change-Id: Ib7542fccdde6a10f9ec38b5584b8b523d4d378dc Signed-off-by: Song Zhao <song.zhao@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c34
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c4
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c108
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c139
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c15
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h4
6 files changed, 263 insertions, 41 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index bd36b4d..880f3a5 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -160,6 +160,7 @@ static const struct aml_codec_framesizes aml_vdec_framesizes[] = {
#define NUM_FORMATS ARRAY_SIZE(aml_video_formats)
extern bool multiplanar;
+extern bool dump_capture_frame;
extern int dmabuf_fd_install_data(int fd, void* data, u32 size);
extern bool is_v4l2_buf_file(struct file *file);
@@ -514,6 +515,20 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
dstbuf->vb.vb2_buf.timestamp = vf->timestamp;
dstbuf->ready_to_display = true;
+ if (dump_capture_frame) {
+ struct file *fp;
+ fp = filp_open("/data/dec_dump.raw",
+ O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
+ if (!IS_ERR(fp)) {
+ struct vb2_buffer *vb = &dstbuf->vb.vb2_buf;
+ kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].bytesused, 0);
+ if (dstbuf->frame_buffer.num_planes == 2)
+ kernel_write(fp,vb2_plane_vaddr(vb, 1),
+ vb->planes[1].bytesused, 0);
+ filp_close(fp, NULL);
+ }
+ }
+
if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
dstbuf->lastframe = true;
dstbuf->vb.flags = V4L2_BUF_FLAG_LAST;
@@ -1158,6 +1173,16 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv,
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"%s, type: %d\n", __func__, q->type);
+ if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
+ /* driver needs match v4l buffer number with dpb_size */
+ if (rb->count > ctx->dpb_size) {
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+ "reqbufs (st:%d) %d -> %d\n",
+ ctx->state, rb->count, ctx->dpb_size);
+ rb->count = ctx->dpb_size;
+ }
+ }
+
return v4l2_m2m_ioctl_reqbufs(file, priv, rb);
}
@@ -1936,10 +1961,17 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
if (vb->index >= ctx->dpb_size) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "enque capture buf idx %d is invalid.\n", vb->index);
+ "enque capture buf idx %d/%d is invalid.\n",
+ vb->index, ctx->dpb_size);
return;
}
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+ "y_addr: %lx, vf_h: %lx, state: %d",
+ buf->frame_buffer.m.mem[0].addr,
+ buf->frame_buffer.vf_handle,
+ buf->frame_buffer.status);
+
if (!buf->que_in_m2m) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
"enque capture buf idx %d, vf: %lx\n",
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
index f1505fb..beb5c00 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -608,6 +608,10 @@ bool multiplanar;
EXPORT_SYMBOL(multiplanar);
module_param(multiplanar, bool, 0644);
+bool dump_capture_frame;
+EXPORT_SYMBOL(dump_capture_frame);
+module_param(dump_capture_frame, bool, 0644);
+
EXPORT_SYMBOL(scatter_mem_enable);
module_param(scatter_mem_enable, bool, 0644);
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
index c35a80d..89725fa 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -111,6 +111,8 @@ struct vdec_mpeg12_inst {
struct aml_vdec_adapt vdec;
struct vdec_mpeg12_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
+ struct completion comp;
};
static void get_pic_info(struct vdec_mpeg12_inst *inst,
@@ -146,6 +148,39 @@ static void get_dpb_size(struct vdec_mpeg12_inst *inst, unsigned int *dpb_sz)
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
}
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:0;");
+
+ return pbuf - parm;
+}
+
+static void vdec_parser_parms(struct vdec_mpeg12_inst *inst)
+{
+ struct aml_vcodec_ctx *ctx = inst->ctx;
+
+ if (ctx->config.parm.dec.parms_status &
+ V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+ u8 *pbuf = ctx->config.buf;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ ctx->config.parm.dec.cfg.ref_buf_margin);
+ ctx->config.length = pbuf - ctx->config.buf;
+ } else {
+ ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+ }
+
+ inst->vdec.config = ctx->config;
+ inst->parms.cfg = ctx->config.parm.dec.cfg;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_mpeg12_inst *inst = NULL;
@@ -162,6 +197,8 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vdec.ctx = ctx;
inst->ctx = ctx;
+ vdec_parser_parms(inst);
+
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
@@ -242,13 +279,13 @@ static void fill_vdec_params(struct vdec_mpeg12_inst *inst,
/* config canvas size that be used for decoder. */
pic->coded_width = ALIGN(dec_ps->coded_width, 64);
- pic->coded_height = ALIGN(dec_ps->coded_height, 64);;
+ pic->coded_height = ALIGN(dec_ps->coded_height, 32);
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
- /* calc DPB size */
- dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+ /*1(EOS) + 8(DECODE_BUFFER_NUM_DEF)*/
+ dec->dpb_sz = 9;
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
@@ -256,6 +293,24 @@ static void fill_vdec_params(struct vdec_mpeg12_inst *inst,
pic->visible_width, pic->visible_height, dec->dpb_sz);
}
+static int stream_parse_by_ucode(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write(vdec, buf, size, 0);
+ if (ret < 0) {
+ pr_err("write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
static int stream_parse(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
@@ -296,7 +351,9 @@ static int vdec_mpeg12_probe(unsigned long h_vdec,
if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
return 0;
- if (st->magic == NORe || st->magic == NORn)
+ if (inst->ctx->param_sets_from_ucode)
+ ret = stream_parse_by_ucode(inst, buf, size);
+ else if (st->magic == NORe || st->magic == NORn)
ret = stream_parse(inst, st->data, st->length);
else
ret = stream_parse(inst, buf, size);
@@ -453,10 +510,48 @@ static int vdec_mpeg12_get_param(unsigned long h_vdec,
return ret;
}
+static void set_param_write_sync(struct vdec_mpeg12_inst *inst)
+{
+ complete(&inst->comp);
+}
+
static void set_param_ps_info(struct vdec_mpeg12_inst *inst,
struct aml_vdec_ps_infos *ps)
{
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "\n");
+ struct vdec_pic_info *pic = &inst->vsi->pic;
+ struct vdec_mpeg12_dec_info *dec = &inst->vsi->dec;
+ struct v4l2_rect *rect = &inst->vsi->crop;
+
+ /* fill visible area size that be used for EGL. */
+ pic->visible_width = ps->visible_width;
+ pic->visible_height = ps->visible_height;
+
+ /* calc visible ares. */
+ rect->left = 0;
+ rect->top = 0;
+ rect->width = pic->visible_width;
+ rect->height = pic->visible_height;
+
+ /* config canvas size that be used for decoder. */
+ pic->coded_width = ps->coded_width;
+ pic->coded_height = ps->coded_height;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+
+ dec->dpb_sz = ps->dpb_size + 1;
+
+ inst->parms.ps = *ps;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+ /*wake up*/
+ complete(&inst->comp);
+
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
+ ps->visible_width, ps->visible_height,
+ ps->coded_width, ps->coded_height,
+ dec->dpb_sz);
}
static int vdec_mpeg12_set_param(unsigned long h_vdec,
@@ -472,6 +567,9 @@ static int vdec_mpeg12_set_param(unsigned long h_vdec,
}
switch (type) {
+ case SET_PARAM_WRITE_FRAME_SYNC:
+ set_param_write_sync(inst);
+ break;
case SET_PARAM_PS_INFO:
set_param_ps_info(inst, in);
break;
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index 8bb1d6b..356506d 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -46,6 +46,7 @@
#include "../utils/decoder_bmmu_box.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/config_parser.h"
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
#include "../utils/config_parser.h"
@@ -385,11 +386,13 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
{
int ret;
u32 canvas;
- ulong decbuf_start = 0;
- int decbuf_y_size = 0;
+ ulong decbuf_start = 0, decbuf_uv_start = 0;
+ int decbuf_y_size = 0, decbuf_uv_size = 0;
u32 canvas_width = 0, canvas_height = 0;
struct vdec_s *vdec = hw_to_vdec(hw);
struct vdec_v4l2_buffer *fb = NULL;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (hw->pics[i].v4l_ref_buf_addr)
return 0;
@@ -397,44 +400,57 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
if (ret < 0) {
debug_print(DECODE_ID(hw), 0,
- "[%d] get fb fail.\n",
- ((struct aml_vcodec_ctx *)
- (hw->v4l2_ctx))->id);
+ "[%d] get fb fail %d/%d.\n",
+ ctx->id, i, hw->buf_num);
return ret;
}
+ if (!hw->frame_width || !hw->frame_height) {
+ struct vdec_pic_info pic;
+ vdec_v4l_get_pic_info(ctx, &pic);
+ hw->frame_width = pic.coded_width;
+ hw->frame_height = pic.coded_height;
+ debug_print(DECODE_ID(hw), 0,
+ "[%d] set %d x %d from IF layer\n", ctx->id,
+ hw->frame_width, hw->frame_height);
+ }
+
hw->pics[i].v4l_ref_buf_addr = (ulong)fb;
if (fb->num_planes == 1) {
decbuf_start = fb->m.mem[0].addr;
decbuf_y_size = fb->m.mem[0].offset;
+ decbuf_uv_start = decbuf_start + decbuf_y_size;
+ decbuf_uv_size = decbuf_y_size / 2;
canvas_width = ALIGN(hw->frame_width, 64);
canvas_height = ALIGN(hw->frame_height, 32);
fb->m.mem[0].bytes_used = fb->m.mem[0].size;
} else if (fb->num_planes == 2) {
decbuf_start = fb->m.mem[0].addr;
decbuf_y_size = fb->m.mem[0].size;
+ decbuf_uv_start = fb->m.mem[1].addr;
+ decbuf_uv_size = fb->m.mem[1].size;
canvas_width = ALIGN(hw->frame_width, 64);
canvas_height = ALIGN(hw->frame_height, 32);
fb->m.mem[0].bytes_used = decbuf_y_size;
- fb->m.mem[1].bytes_used = decbuf_y_size << 1;
+ fb->m.mem[1].bytes_used = decbuf_uv_size;
}
debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n",
- ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb);
+ ctx->id, __func__, fb);
if (vdec->parallel_dec == 1) {
u32 tmp;
- if (canvas_y(hw->canvas_spec[i]) == 0xff) {
- tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
- hw->canvas_spec[i] &= ~0xff;
- hw->canvas_spec[i] |= tmp;
- }
if (canvas_u(hw->canvas_spec[i]) == 0xff) {
tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
hw->canvas_spec[i] &= ~(0xffff << 8);
hw->canvas_spec[i] |= tmp << 8;
hw->canvas_spec[i] |= tmp << 16;
}
+ if (canvas_y(hw->canvas_spec[i]) == 0xff) {
+ tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+ hw->canvas_spec[i] &= ~0xff;
+ hw->canvas_spec[i] |= tmp;
+ }
canvas = hw->canvas_spec[i];
} else {
canvas = vdec->get_canvas(i, 2);
@@ -449,7 +465,7 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
(hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]);
- hw->canvas_config[i][1].phy_addr = decbuf_start + decbuf_y_size;
+ hw->canvas_config[i][1].phy_addr = decbuf_uv_start;
hw->canvas_config[i][1].width = canvas_width;
hw->canvas_config[i][1].height = canvas_height / 2;
hw->canvas_config[i][1].block_mode = hw->canvas_mode;
@@ -457,6 +473,12 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
(hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]);
+ debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL,
+ "[%d] %s(), canvas: 0x%x mode: %d y: %x uv: %x w: %d h: %d\n",
+ ctx->id, __func__, canvas, hw->canvas_mode,
+ decbuf_start, decbuf_uv_start,
+ canvas_width, canvas_height);
+
return 0;
}
@@ -1778,7 +1800,7 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
ps.visible_width = hw->frame_width;
ps.visible_height = hw->frame_height;
ps.coded_width = ALIGN(hw->frame_width, 64);
- ps.coded_height = ALIGN(hw->frame_height, 64);
+ ps.coded_height = ALIGN(hw->frame_height, 32);
ps.dpb_size = hw->buf_num;
hw->v4l_params_parsed = true;
vdec_v4l_set_ps_infos(ctx, &ps);
@@ -2072,6 +2094,15 @@ static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw,
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
+ if (hw->is_used_v4l) {
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ if (ctx->param_sets_from_ucode &&
+ !hw->v4l_params_parsed)
+ vdec_v4l_write_frame_sync(ctx);
+ }
+
if (hw->vdec_cb)
hw->vdec_cb(vdec, hw->vdec_cb_arg);
}
@@ -2507,15 +2538,17 @@ static void check_timer_func(unsigned long arg)
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
{
- int index, i;
+ u32 index, i;
+ struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+
index = find_free_buffer(hw);
if (index < 0 || index >= hw->buf_num)
return -1;
if (!hw->init_flag)
vmpeg12_canvas_init(hw);
else {
+ WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
if (!hw->is_used_v4l) {
- WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
for (i = 0; i < hw->buf_num; i++) {
canvas_config_config(canvas_y(hw->canvas_spec[i]),
&hw->canvas_config[i][0]);
@@ -2585,6 +2618,13 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg);
WRITE_VREG(AV_SCRATCH_H, hw->reg_signal_type);
+ if (READ_VREG(MREG_ERROR_COUNT) != 0 ||
+ READ_VREG(MREG_FATAL_ERROR) != 0)
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE,
+ "err_cnt:%d fa_err:%d\n",
+ READ_VREG(MREG_ERROR_COUNT),
+ READ_VREG(MREG_FATAL_ERROR));
+
/* clear error count */
WRITE_VREG(MREG_ERROR_COUNT, 0);
WRITE_VREG(MREG_FATAL_ERROR, 0);
@@ -2593,6 +2633,13 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
#ifdef NV21
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17);
#endif
+
+ /* cbcr_merge_swap_en */
+ if (hw->is_used_v4l
+ && (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21
+ || v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
+ SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
if (!hw->ctx_valid)
WRITE_VREG(AV_SCRATCH_J, hw->userdata_wp_ctx);
@@ -2822,15 +2869,31 @@ void (*callback)(struct vdec_s *, void *),
if (size < 0) {
hw->input_empty++;
hw->dec_result = DEC_RESULT_AGAIN;
+
+ debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+ "vdec_prepare_input: Insufficient data\n");
vdec_schedule_work(&hw->work);
return;
}
+
+ if (vdec_frame_based(vdec) && !vdec_secure(vdec)) {
+ /* HW needs padding (NAL start) for frame ending */
+ char* tail = (char *)hw->chunk->block->start_virt;
+
+ tail += hw->chunk->offset + hw->chunk->size;
+ tail[0] = 0;
+ tail[1] = 0;
+ tail[2] = 1;
+ tail[3] = 0;
+ codec_mm_dma_flush(tail, 4, DMA_TO_DEVICE);
+ }
+
if (vdec_frame_based(vdec) && debug_enable) {
u8 *data = NULL;
-
- debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
- "run: chunk offset 0x%x, size %d\n",
- hw->chunk->offset, hw->chunk->size);
+ if (hw->chunk)
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "run: chunk offset 0x%x, size %d\n",
+ hw->chunk->offset, hw->chunk->size);
if (!hw->chunk->block->is_mapped)
data = codec_mm_vmap(hw->chunk->block->start +
@@ -2981,25 +3044,34 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
&vf_provider_ops, pdata);
- if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
- debug_print(DECODE_ID(hw), 0, "pdata->config: %s\n", pdata->config);
- if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
- &config_val) == 0)
- hw->dynamic_buf_num_margin = config_val;
- else
- hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
- } else {
- hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
- }
- hw->buf_num = vmpeg12_get_buf_num(hw);
-
if (pdata->parallel_dec == 1) {
int i;
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
hw->canvas_spec[i] = 0xffffff;
}
platform_set_drvdata(pdev, pdata);
+
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
hw->canvas_mode = pdata->canvas_mode;
+ if (pdata->config_len) {
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ hw->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_canvas_mem_mode",
+ &config_val) == 0)
+ hw->canvas_mode = config_val;
+
+ if ((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0 &&
+ get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ hw->dynamic_buf_num_margin= config_val;
+ }
+
+ hw->buf_num = vmpeg12_get_buf_num(hw);
hw->platform_dev = pdev;
hw->tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0;
@@ -3037,9 +3109,6 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
reset_user_data_buf(hw);
#endif
- hw->is_used_v4l = (((unsigned long)
- hw->vmpeg12_amstream_dec_info.param & 0x80) >> 7);
-
/*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/
return 0;
}
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
index 107efec..88d2947 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -15,6 +15,21 @@ int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
}
EXPORT_SYMBOL(vdec_v4l_get_buffer);
+int vdec_v4l_get_pic_info(struct aml_vcodec_ctx *ctx,
+ struct vdec_pic_info *pic)
+{
+ int ret = 0;
+
+ if (ctx->drv_handle == 0)
+ return -EIO;
+
+ ret = ctx->dec_if->get_param(ctx->drv_handle,
+ GET_PARAM_PIC_INFO, pic);
+
+ return ret;
+}
+EXPORT_SYMBOL(vdec_v4l_get_pic_info);
+
int vdec_v4l_set_ps_infos(struct aml_vcodec_ctx *ctx,
struct aml_vdec_ps_infos *ps)
{
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
index 13f3543..6254509 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
@@ -8,6 +8,10 @@ int vdec_v4l_get_buffer(
struct aml_vcodec_ctx *ctx,
struct vdec_v4l2_buffer **out);
+int vdec_v4l_get_pic_info(
+ struct aml_vcodec_ctx *ctx,
+ struct vdec_pic_info *pic);
+
int vdec_v4l_set_ps_infos(
struct aml_vcodec_ctx *ctx,
struct aml_vdec_ps_infos *ps);