|
@@ -41,6 +41,7 @@
|
|
#include <media/videobuf2-vmalloc.h>
|
|
#include <media/videobuf2-vmalloc.h>
|
|
|
|
|
|
#include "coda.h"
|
|
#include "coda.h"
|
|
|
|
+#include "imx-vdoa.h"
|
|
|
|
|
|
#define CODA_NAME "coda"
|
|
#define CODA_NAME "coda"
|
|
|
|
|
|
@@ -66,6 +67,10 @@ static int disable_tiling;
|
|
module_param(disable_tiling, int, 0644);
|
|
module_param(disable_tiling, int, 0644);
|
|
MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
|
|
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)
|
|
void coda_write(struct coda_dev *dev, u32 data, u32 reg)
|
|
{
|
|
{
|
|
v4l2_dbg(2, coda_debug, &dev->v4l2_dev,
|
|
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.
|
|
* V4L2 ioctl() operations.
|
|
*/
|
|
*/
|
|
@@ -417,6 +447,33 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
|
|
return 0;
|
|
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,
|
|
static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
|
|
u32 width, u32 height)
|
|
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;
|
|
const struct coda_codec *codec;
|
|
struct vb2_queue *src_vq;
|
|
struct vb2_queue *src_vq;
|
|
int ret;
|
|
int ret;
|
|
|
|
+ bool use_vdoa;
|
|
|
|
|
|
ret = coda_try_pixelformat(ctx, f);
|
|
ret = coda_try_pixelformat(ctx, f);
|
|
if (ret < 0)
|
|
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.bytesperline = round_up(f->fmt.pix.width, 16);
|
|
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
|
|
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
|
|
f->fmt.pix.height * 3 / 2;
|
|
f->fmt.pix.height * 3 / 2;
|
|
|
|
+
|
|
|
|
+ ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -601,11 +663,9 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
|
|
|
|
|
|
switch (f->fmt.pix.pixelformat) {
|
|
switch (f->fmt.pix.pixelformat) {
|
|
case V4L2_PIX_FMT_NV12:
|
|
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 */
|
|
/* else fall through */
|
|
case V4L2_PIX_FMT_YUV420:
|
|
case V4L2_PIX_FMT_YUV420:
|
|
case V4L2_PIX_FMT_YVU420:
|
|
case V4L2_PIX_FMT_YVU420:
|
|
@@ -615,6 +675,15 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
|
|
break;
|
|
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,
|
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
|
"Setting format for type %d, wxh: %dx%d, fmt: %4.4s %c\n",
|
|
"Setting format for type %d, wxh: %dx%d, fmt: %4.4s %c\n",
|
|
f->type, q_data->width, q_data->height,
|
|
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 &
|
|
bool stream_end = ctx->bit_stream_param &
|
|
CODA_BIT_STREAM_END_FLAG;
|
|
CODA_BIT_STREAM_END_FLAG;
|
|
int num_metas = ctx->num_metas;
|
|
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) {
|
|
if (ctx->hold && !src_bufs) {
|
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
|
@@ -1731,6 +1810,13 @@ static int coda_open(struct file *file)
|
|
default:
|
|
default:
|
|
ctx->reg_idx = idx;
|
|
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 */
|
|
/* Power up and upload firmware if necessary */
|
|
ret = pm_runtime_get_sync(&dev->plat_dev->dev);
|
|
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 */
|
|
/* If this instance is running, call .job_abort and wait for it to end */
|
|
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
|
|
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 */
|
|
/* In case the instance was not running, we still need to call SEQ_END */
|
|
if (ctx->ops->seq_end_work) {
|
|
if (ctx->ops->seq_end_work) {
|
|
queue_work(dev->workqueue, &ctx->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;
|
|
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);
|
|
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|