diff options
author | Michael Tretter <m.tretter@pengutronix.de> | 2017-01-20 12:00:24 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-01-31 08:37:43 -0200 |
commit | e7f3c54810350827823d241905fb7823eee30c21 (patch) | |
tree | 8e040c223fa88f397abf24826860cea454342f38 /drivers/media/platform/coda/coda-common.c | |
parent | 7691f821ff19af21b1768d8f347764e61f9f5d2b (diff) |
[media] coda: use VDOA for un-tiling custom macroblock format
If the CODA driver is configured to produce NV12 output and the VDOA is
available, the VDOA can be used to transform the custom macroblock tiled
format to a raster-ordered format for scanout.
In this case, set the output format of the CODA to the custom macroblock
tiled format, disable the rotator, and use the VDOA to write to the v4l2
buffer. The VDOA is synchronized with the CODA to always un-tile the
frame that the CODA finished in the previous run.
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/platform/coda/coda-common.c')
-rw-r--r-- | drivers/media/platform/coda/coda-common.c | 104 |
1 files changed, 99 insertions, 5 deletions
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index b23fe0f0fb56..13ee6cba6847 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -41,6 +41,7 @@ #include <media/videobuf2-vmalloc.h> #include "coda.h" +#include "imx-vdoa.h" #define CODA_NAME "coda" @@ -66,6 +67,10 @@ static int disable_tiling; module_param(disable_tiling, int, 0644); MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers"); +static int disable_vdoa; +module_param(disable_vdoa, int, 0644); +MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion"); + void coda_write(struct coda_dev *dev, u32 data, u32 reg) { v4l2_dbg(2, coda_debug, &dev->v4l2_dev, @@ -325,6 +330,31 @@ const char *coda_product_name(int product) } } +static struct vdoa_data *coda_get_vdoa_data(void) +{ + struct device_node *vdoa_node; + struct platform_device *vdoa_pdev; + struct vdoa_data *vdoa_data = NULL; + + vdoa_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-vdoa"); + if (!vdoa_node) + return NULL; + + vdoa_pdev = of_find_device_by_node(vdoa_node); + if (!vdoa_pdev) + goto out; + + vdoa_data = platform_get_drvdata(vdoa_pdev); + if (!vdoa_data) + vdoa_data = ERR_PTR(-EPROBE_DEFER); + +out: + if (vdoa_node) + of_node_put(vdoa_node); + + return vdoa_data; +} + /* * V4L2 ioctl() operations. */ @@ -417,6 +447,33 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f) return 0; } +static int coda_try_fmt_vdoa(struct coda_ctx *ctx, struct v4l2_format *f, + bool *use_vdoa) +{ + int err; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (!use_vdoa) + return -EINVAL; + + if (!ctx->vdoa) { + *use_vdoa = false; + return 0; + } + + err = vdoa_context_configure(NULL, f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.pixelformat); + if (err) { + *use_vdoa = false; + return 0; + } + + *use_vdoa = true; + return 0; +} + static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage, u32 width, u32 height) { @@ -495,6 +552,7 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, const struct coda_codec *codec; struct vb2_queue *src_vq; int ret; + bool use_vdoa; ret = coda_try_pixelformat(ctx, f); if (ret < 0) @@ -531,6 +589,10 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height * 3 / 2; + + ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa); + if (ret < 0) + return ret; } return 0; @@ -601,11 +663,9 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, switch (f->fmt.pix.pixelformat) { case V4L2_PIX_FMT_NV12: - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; - if (!disable_tiling) - break; - } + ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; + if (!disable_tiling) + break; /* else fall through */ case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: @@ -615,6 +675,15 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, break; } + if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP && + !coda_try_fmt_vdoa(ctx, f, &ctx->use_vdoa) && + ctx->use_vdoa) + vdoa_context_configure(ctx->vdoa, f->fmt.pix.width, + f->fmt.pix.height, + f->fmt.pix.pixelformat); + else + ctx->use_vdoa = false; + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %4.4s %c\n", f->type, q_data->width, q_data->height, @@ -1041,6 +1110,16 @@ static int coda_job_ready(void *m2m_priv) bool stream_end = ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG; int num_metas = ctx->num_metas; + unsigned int count; + + count = hweight32(ctx->frm_dis_flg); + if (ctx->use_vdoa && count >= (ctx->num_internal_frames - 1)) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%d: not ready: all internal buffers in use: %d/%d (0x%x)", + ctx->idx, count, ctx->num_internal_frames, + ctx->frm_dis_flg); + return 0; + } if (ctx->hold && !src_bufs) { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, @@ -1731,6 +1810,13 @@ static int coda_open(struct file *file) default: ctx->reg_idx = idx; } + if (ctx->dev->vdoa && !disable_vdoa) { + ctx->vdoa = vdoa_context_create(dev->vdoa); + if (!ctx->vdoa) + v4l2_warn(&dev->v4l2_dev, + "Failed to create vdoa context: not using vdoa"); + } + ctx->use_vdoa = false; /* Power up and upload firmware if necessary */ ret = pm_runtime_get_sync(&dev->plat_dev->dev); @@ -1812,6 +1898,9 @@ static int coda_release(struct file *file) /* If this instance is running, call .job_abort and wait for it to end */ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + if (ctx->vdoa) + vdoa_context_destroy(ctx->vdoa); + /* In case the instance was not running, we still need to call SEQ_END */ if (ctx->ops->seq_end_work) { queue_work(dev->workqueue, &ctx->seq_end_work); @@ -2258,6 +2347,11 @@ static int coda_probe(struct platform_device *pdev) } dev->iram_pool = pool; + /* Get vdoa_data if supported by the platform */ + dev->vdoa = coda_get_vdoa_data(); + if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER) + return -EPROBE_DEFER; + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) return ret; |