aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/coda
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/coda')
-rw-r--r--drivers/media/platform/coda/coda-bit.c29
-rw-r--r--drivers/media/platform/coda/coda-common.c78
-rw-r--r--drivers/media/platform/coda/coda_regs.h1
-rw-r--r--drivers/media/platform/coda/imx-vdoa.c2
4 files changed, 89 insertions, 21 deletions
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index bba1eb43b5d8..291c40933935 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -394,7 +394,8 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx,
int i;
if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
- ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264) {
+ ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 ||
+ ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4) {
width = round_up(q_data->width, 16);
height = round_up(q_data->height, 16);
} else {
@@ -702,6 +703,8 @@ static u32 coda_supported_firmwares[] = {
CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
+ CODA_FIRMWARE_VERNUM(CODA_960, 2, 3, 10),
+ CODA_FIRMWARE_VERNUM(CODA_960, 3, 1, 1),
};
static bool coda_firmware_supported(u32 vernum)
@@ -1006,7 +1009,7 @@ static int coda_start_encoding(struct coda_ctx *ctx)
break;
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
- value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
+ value = ctx->params.gop_size;
coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
}
@@ -1250,7 +1253,8 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
force_ipicture = ctx->params.force_ipicture;
if (force_ipicture)
ctx->params.force_ipicture = false;
- else if ((src_buf->sequence % ctx->params.gop_size) == 0)
+ else if (ctx->params.gop_size != 0 &&
+ (src_buf->sequence % ctx->params.gop_size) == 0)
force_ipicture = 1;
/*
@@ -1411,6 +1415,7 @@ static void coda_finish_encode(struct coda_ctx *ctx)
}
dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
+ dst_buf->field = src_buf->field;
dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
dst_buf->flags |=
src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
@@ -1634,9 +1639,6 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
ctx->frm_dis_flg = 0;
coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
- coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE,
- CODA_REG_BIT_BIT_STREAM_PARAM);
-
coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
val = 0;
@@ -1652,6 +1654,10 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
else
ctx->params.codec_mode_aux = 0;
+ if (src_fourcc == V4L2_PIX_FMT_MPEG4) {
+ coda_write(dev, CODA_MP4_CLASS_MPEG4,
+ CODA_CMD_DEC_SEQ_MP4_ASP_CLASS);
+ }
if (src_fourcc == V4L2_PIX_FMT_H264) {
if (dev->devtype->product == CODA_7541) {
coda_write(dev, ctx->psbuf.paddr,
@@ -1667,18 +1673,18 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
if (dev->devtype->product != CODA_960)
coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
- if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
+ ctx->bit_stream_param = CODA_BIT_DEC_SEQ_INIT_ESCAPE;
+ ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
+ ctx->bit_stream_param = 0;
+ if (ret) {
v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
- coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
- return -ETIMEDOUT;
+ return ret;
}
ctx->initialized = 1;
/* Update kfifo out pointer from coda bitstream read pointer */
coda_kfifo_sync_from_device(ctx);
- coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
-
if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
v4l2_err(&dev->v4l2_dev,
"CODA_COMMAND_SEQ_INIT failed, error code = %d\n",
@@ -2153,6 +2159,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
dst_buf->sequence = ctx->osequence++;
+ dst_buf->field = V4L2_FIELD_NONE;
dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 829c7895a98a..15eb5dc4dff9 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster
static int enable_bwb = 0;
module_param(enable_bwb, int, 0644);
-MODULE_PARM_DESC(enable_bwb, "Enable BWB unit, may crash on certain streams");
+MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams");
void coda_write(struct coda_dev *dev, u32 data, u32 reg)
{
@@ -714,9 +714,10 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
break;
case V4L2_PIX_FMT_NV12:
- ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
- if (!disable_tiling)
+ if (!disable_tiling) {
+ ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
break;
+ }
/* else fall through */
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
@@ -932,7 +933,7 @@ static int coda_encoder_cmd(struct file *file, void *fh,
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
/* If there is no buffer in flight, wake up */
- if (ctx->qsequence == ctx->osequence) {
+ if (!ctx->streamon_out || ctx->qsequence == ctx->osequence) {
dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
dst_vq->last_buffer_dequeued = true;
@@ -1683,12 +1684,23 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
ctx->params.h264_deblk_enabled = (ctrl->val ==
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ /* TODO: switch between baseline and constrained baseline */
+ ctx->params.h264_profile_idc = 66;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ /* nothing to do, this is set by the encoder */
+ break;
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
ctx->params.mpeg4_intra_qp = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
ctx->params.mpeg4_inter_qp = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+ /* nothing to do, these are fixed */
+ break;
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
ctx->params.slice_mode = ctrl->val;
break;
@@ -1734,10 +1746,12 @@ static const struct v4l2_ctrl_ops coda_ctrl_ops = {
static void coda_encode_ctrls(struct coda_ctx *ctx)
{
+ int max_gop_size = (ctx->dev->devtype->product == CODA_DX6) ? 60 : 99;
+
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16);
+ V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, max_gop_size, 1, 16);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -1756,11 +1770,47 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0,
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, 0x0,
+ V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
+ if (ctx->dev->devtype->product == CODA_7541) {
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+ V4L2_MPEG_VIDEO_H264_LEVEL_3_1,
+ ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1)),
+ V4L2_MPEG_VIDEO_H264_LEVEL_3_1);
+ }
+ if (ctx->dev->devtype->product == CODA_960) {
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+ V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
+ ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
+ V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
+ }
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2);
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+ V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE, 0x0,
+ V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
+ if (ctx->dev->devtype->product == CODA_7541 ||
+ ctx->dev->devtype->product == CODA_960) {
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+ ~(1 << V4L2_MPEG_VIDEO_MPEG4_LEVEL_5),
+ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5);
+ }
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, 0x0,
V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);
@@ -1938,7 +1988,13 @@ static int coda_open(struct file *file)
ctx->idx = idx;
switch (dev->devtype->product) {
case CODA_960:
- if (enable_bwb)
+ /*
+ * Enabling the BWB when decoding can hang the firmware with
+ * certain streams. The issue was tracked as ENGR00293425 by
+ * Freescale. As a workaround, disable BWB for all decoders.
+ * The enable_bwb module parameter allows to override this.
+ */
+ if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER)
ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB;
/* fallthrough */
case CODA_7541:
@@ -2142,7 +2198,8 @@ static int coda_hw_init(struct coda_dev *dev)
CODA_REG_BIT_STREAM_CTRL);
}
if (dev->devtype->product == CODA_960)
- coda_write(dev, 1 << 12, CODA_REG_BIT_FRAME_MEM_CTRL);
+ coda_write(dev, CODA9_FRAME_ENABLE_BWB,
+ CODA_REG_BIT_FRAME_MEM_CTRL);
else
coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
@@ -2386,11 +2443,11 @@ static const struct coda_devtype coda_devdata[] = {
.num_vdevs = ARRAY_SIZE(coda9_video_devices),
.workbuf_size = 80 * 1024,
.tempbuf_size = 204 * 1024,
- .iram_size = 0x20000,
+ .iram_size = 0x1f000, /* leave 4k for suspend code */
},
};
-static struct platform_device_id coda_platform_ids[] = {
+static const struct platform_device_id coda_platform_ids[] = {
{ .name = "coda-imx27", .driver_data = CODA_IMX27 },
{ /* sentinel */ }
};
@@ -2470,7 +2527,8 @@ static int coda_probe(struct platform_device *pdev)
return ret;
}
- dev->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
+ dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev,
+ NULL);
if (IS_ERR(dev->rstc)) {
ret = PTR_ERR(dev->rstc);
dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 77ee46a93427..38df5fd9a2fa 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -158,6 +158,7 @@
#define CODA_CMD_DEC_SEQ_PS_BB_START 0x194
#define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198
#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c
+#define CODA_MP4_CLASS_MPEG4 0
#define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c
#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0
diff --git a/drivers/media/platform/coda/imx-vdoa.c b/drivers/media/platform/coda/imx-vdoa.c
index df9b71621420..8eb3e0c05473 100644
--- a/drivers/media/platform/coda/imx-vdoa.c
+++ b/drivers/media/platform/coda/imx-vdoa.c
@@ -314,6 +314,8 @@ static int vdoa_probe(struct platform_device *pdev)
return PTR_ERR(vdoa->regs);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res)
+ return -EINVAL;
vdoa->irq = devm_request_threaded_irq(&pdev->dev, res->start, NULL,
vdoa_irq_handler, IRQF_ONESHOT,
"vdoa", vdoa);