Re: [PATCH v4 3/4] v4l: ti-vpe: Add VPE mem to mem driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Archit,

I've got a few comments below...

On 09/06/2013 12:12 PM, Archit Taneja wrote:
> VPE is a block which consists of a single memory to memory path which can
> perform chrominance up/down sampling, de-interlacing, scaling, and color space
> conversion of raster or tiled YUV420 coplanar, YUV422 coplanar or YUV422
> interleaved video formats.
> 
> We create a mem2mem driver based primarily on the mem2mem-testdev example.
> The de-interlacer, scaler and color space converter are all bypassed for now
> to keep the driver simple. Chroma up/down sampler blocks are implemented, so
> conversion beteen different YUV formats is possible.
> 
> Each mem2mem context allocates a buffer for VPE MMR values which it will use
> when it gets access to the VPE HW via the mem2mem queue, it also allocates
> a VPDMA descriptor list to which configuration and data descriptors are added.
> 
> Based on the information received via v4l2 ioctls for the source and
> destination queues, the driver configures the values for the MMRs, and stores
> them in the buffer. There are also some VPDMA parameters like frame start and
> line mode which needs to be configured, these are configured by direct register
> writes via the VPDMA helper functions.
> 
> The driver's device_run() mem2mem op will add each descriptor based on how the
> source and destination queues are set up for the given ctx, once the list is
> prepared, it's submitted to VPDMA, these descriptors when parsed by VPDMA will
> upload MMR registers, start DMA of video buffers on the various input and output
> clients/ports.
> 
> When the list is parsed completely(and the DMAs on all the output ports done),
> an interrupt is generated which we use to notify that the source and destination
> buffers are done.
> 
> The rest of the driver is quite similar to other mem2mem drivers, we use the
> multiplane v4l2 ioctls as the HW support coplanar formats.
> 
> Signed-off-by: Archit Taneja <archit@xxxxxx>
> ---
>  drivers/media/platform/Kconfig           |   16 +
>  drivers/media/platform/Makefile          |    2 +
>  drivers/media/platform/ti-vpe/Makefile   |    5 +
>  drivers/media/platform/ti-vpe/vpe.c      | 1750 ++++++++++++++++++++++++++++++
>  drivers/media/platform/ti-vpe/vpe_regs.h |  496 +++++++++
>  include/uapi/linux/v4l2-controls.h       |    4 +
>  6 files changed, 2273 insertions(+)
>  create mode 100644 drivers/media/platform/ti-vpe/Makefile
>  create mode 100644 drivers/media/platform/ti-vpe/vpe.c
>  create mode 100644 drivers/media/platform/ti-vpe/vpe_regs.h
> 

<snip>

> +
> +static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
> +{
> +	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
> +	struct vpe_ctx *ctx = file2ctx(file);
> +	struct vb2_queue *vq;
> +	struct vpe_q_data *q_data;
> +	int i;
> +
> +	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
> +	if (!vq)
> +		return -EINVAL;
> +
> +	q_data = get_q_data(ctx, f->type);
> +
> +	pix->width = q_data->width;
> +	pix->height = q_data->height;
> +	pix->pixelformat = q_data->fmt->fourcc;
> +	pix->colorspace = q_data->colorspace;
> +	pix->num_planes = q_data->fmt->coplanar ? 2 : 1;
> +
> +	for (i = 0; i < pix->num_planes; i++) {
> +		pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
> +		pix->plane_fmt[i].sizeimage = q_data->sizeimage[i];
> +	}
> +
> +	return 0;
> +}
> +
> +static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f,
> +		       struct vpe_fmt *fmt, int type)
> +{
> +	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
> +	struct v4l2_plane_pix_format *plane_fmt;
> +	int i;
> +
> +	if (!fmt || !(fmt->types & type)) {
> +		vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
> +			pix->pixelformat);
> +		return -EINVAL;
> +	}
> +
> +	pix->field = V4L2_FIELD_NONE;
> +
> +	v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN,
> +			      &pix->height, MIN_H, MAX_H, H_ALIGN,
> +			      S_ALIGN);
> +
> +	pix->num_planes = fmt->coplanar ? 2 : 1;
> +	pix->pixelformat = fmt->fourcc;
> +	pix->colorspace = fmt->fourcc == V4L2_PIX_FMT_RGB24 ?

You do this only for capture. Output sets the colorspace, so try_fmt should
leave the colorspace field untouched for the output direction.

> +			V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;

Zero pix->priv as well:

	pix->priv = 0;

> +
> +	for (i = 0; i < pix->num_planes; i++) {
> +		int depth;
> +
> +		plane_fmt = &pix->plane_fmt[i];
> +		depth = fmt->vpdma_fmt[i]->depth;
> +
> +		if (i == VPE_LUMA)
> +			plane_fmt->bytesperline =
> +					round_up((pix->width * depth) >> 3,
> +						1 << L_ALIGN);
> +		else
> +			plane_fmt->bytesperline = pix->width;
> +
> +		plane_fmt->sizeimage =
> +				(pix->height * pix->width * depth) >> 3;
> +	}
> +
> +	return 0;
> +}
> +
> +static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +	struct vpe_fmt *fmt = find_format(f);
> +
> +	if (V4L2_TYPE_IS_OUTPUT(f->type))
> +		return __vpe_try_fmt(ctx, f, fmt, VPE_FMT_TYPE_OUTPUT);
> +	else
> +		return __vpe_try_fmt(ctx, f, fmt, VPE_FMT_TYPE_CAPTURE);
> +}
> +
> +static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f)
> +{
> +	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
> +	struct v4l2_plane_pix_format *plane_fmt;
> +	struct vpe_q_data *q_data;
> +	struct vb2_queue *vq;
> +	int i;
> +
> +	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
> +	if (!vq)
> +		return -EINVAL;
> +
> +	if (vb2_is_busy(vq)) {
> +		vpe_err(ctx->dev, "queue busy\n");
> +		return -EBUSY;
> +	}
> +
> +	q_data = get_q_data(ctx, f->type);
> +	if (!q_data)
> +		return -EINVAL;
> +
> +	q_data->fmt		= find_format(f);
> +	q_data->width		= pix->width;
> +	q_data->height		= pix->height;
> +	q_data->colorspace	= pix->colorspace;

Does this make sense for output devices? See comment in try_fmt.

> +
> +	for (i = 0; i < pix->num_planes; i++) {
> +		plane_fmt = &pix->plane_fmt[i];
> +
> +		q_data->bytesperline[i]	= plane_fmt->bytesperline;
> +		q_data->sizeimage[i]	= plane_fmt->sizeimage;
> +	}
> +
> +	q_data->c_rect.left	= 0;
> +	q_data->c_rect.top	= 0;
> +	q_data->c_rect.width	= q_data->width;
> +	q_data->c_rect.height	= q_data->height;
> +
> +	vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d",
> +		f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
> +		q_data->bytesperline[VPE_LUMA]);
> +	if (q_data->fmt->coplanar)
> +		vpe_dbg(ctx->dev, " bpl_uv %d\n",
> +			q_data->bytesperline[VPE_CHROMA]);
> +
> +	return 0;
> +}
> +
> +static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> +{
> +	int ret;
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	ret = vpe_try_fmt(file, priv, f);
> +	if (ret)
> +		return ret;
> +
> +	ret = __vpe_s_fmt(ctx, f);
> +	if (ret)
> +		return ret;
> +
> +	if (V4L2_TYPE_IS_OUTPUT(f->type))
> +		set_src_registers(ctx);
> +	else
> +		set_dst_registers(ctx);
> +
> +	return set_srcdst_params(ctx);
> +}
> +
> +static int vpe_reqbufs(struct file *file, void *priv,
> +		       struct v4l2_requestbuffers *reqbufs)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
> +}
> +
> +static int vpe_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
> +}
> +
> +static int vpe_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
> +}
> +
> +static int vpe_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
> +}
> +
> +static int vpe_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
> +}
> +
> +static int vpe_streamoff(struct file *file, void *priv, enum v4l2_buf_type type)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	vpe_dump_regs(ctx->dev);
> +	vpdma_dump_regs(ctx->dev->vpdma);
> +
> +	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
> +}
> +
> +#define V4L2_CID_VPE_BUFS_PER_JOB		(V4L2_CID_USER_TI_VPE_BASE + 0)

Please comment here what this control does. If applications are supposed to explicitly
set this control, then you need to put it in a public driver-specific header, otherwise
they can never get hold of the control.

> +
> +static int vpe_s_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct vpe_ctx *ctx =
> +		container_of(ctrl->handler, struct vpe_ctx, hdl);
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_VPE_BUFS_PER_JOB:
> +		ctx->bufs_per_job = ctrl->val;
> +		break;
> +
> +	default:
> +		vpe_err(ctx->dev, "Invalid control\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops vpe_ctrl_ops = {
> +	.s_ctrl = vpe_s_ctrl,
> +};
> +
> +static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
> +	.vidioc_querycap	= vpe_querycap,
> +
> +	.vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt,
> +	.vidioc_g_fmt_vid_cap_mplane	= vpe_g_fmt,
> +	.vidioc_try_fmt_vid_cap_mplane	= vpe_try_fmt,
> +	.vidioc_s_fmt_vid_cap_mplane	= vpe_s_fmt,
> +
> +	.vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt,
> +	.vidioc_g_fmt_vid_out_mplane	= vpe_g_fmt,
> +	.vidioc_try_fmt_vid_out_mplane	= vpe_try_fmt,
> +	.vidioc_s_fmt_vid_out_mplane	= vpe_s_fmt,
> +
> +	.vidioc_reqbufs		= vpe_reqbufs,
> +	.vidioc_querybuf	= vpe_querybuf,
> +
> +	.vidioc_qbuf		= vpe_qbuf,
> +	.vidioc_dqbuf		= vpe_dqbuf,
> +
> +	.vidioc_streamon	= vpe_streamon,
> +	.vidioc_streamoff	= vpe_streamoff,
> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> +};
> +
> +/*
> + * Queue operations
> + */
> +static int vpe_queue_setup(struct vb2_queue *vq,
> +			   const struct v4l2_format *fmt,
> +			   unsigned int *nbuffers, unsigned int *nplanes,
> +			   unsigned int sizes[], void *alloc_ctxs[])
> +{
> +	int i;
> +	struct vpe_ctx *ctx = vb2_get_drv_priv(vq);
> +	struct vpe_q_data *q_data;
> +
> +	q_data = get_q_data(ctx, vq->type);
> +
> +	*nplanes = q_data->fmt->coplanar ? 2 : 1;
> +
> +	for (i = 0; i < *nplanes; i++) {
> +		sizes[i] = q_data->sizeimage[i];
> +		alloc_ctxs[i] = ctx->dev->alloc_ctx;
> +	}
> +
> +	vpe_dbg(ctx->dev, "get %d buffer(s) of size %d", *nbuffers,
> +		sizes[VPE_LUMA]);
> +	if (q_data->fmt->coplanar)
> +		vpe_dbg(ctx->dev, " and %d\n", sizes[VPE_CHROMA]);
> +
> +	return 0;
> +}
> +
> +static int vpe_buf_prepare(struct vb2_buffer *vb)
> +{
> +	struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> +	struct vpe_q_data *q_data;
> +	int i, num_planes;
> +
> +	vpe_dbg(ctx->dev, "type: %d\n", vb->vb2_queue->type);
> +
> +	q_data = get_q_data(ctx, vb->vb2_queue->type);
> +	num_planes = q_data->fmt->coplanar ? 2 : 1;
> +
> +	for (i = 0; i < num_planes; i++) {
> +		if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
> +			vpe_err(ctx->dev,
> +				"data will not fit into plane (%lu < %lu)\n",
> +				vb2_plane_size(vb, i),
> +				(long) q_data->sizeimage[i]);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	for (i = 0; i < num_planes; i++)
> +		vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
> +
> +	return 0;
> +}
> +
> +static void vpe_buf_queue(struct vb2_buffer *vb)
> +{
> +	struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> +	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
> +}
> +
> +static void vpe_wait_prepare(struct vb2_queue *q)
> +{
> +	struct vpe_ctx *ctx = vb2_get_drv_priv(q);
> +	vpe_unlock(ctx);
> +}
> +
> +static void vpe_wait_finish(struct vb2_queue *q)
> +{
> +	struct vpe_ctx *ctx = vb2_get_drv_priv(q);
> +	vpe_lock(ctx);
> +}
> +
> +static struct vb2_ops vpe_qops = {
> +	.queue_setup	 = vpe_queue_setup,
> +	.buf_prepare	 = vpe_buf_prepare,
> +	.buf_queue	 = vpe_buf_queue,
> +	.wait_prepare	 = vpe_wait_prepare,
> +	.wait_finish	 = vpe_wait_finish,
> +};
> +
> +static int queue_init(void *priv, struct vb2_queue *src_vq,
> +		      struct vb2_queue *dst_vq)
> +{
> +	struct vpe_ctx *ctx = priv;
> +	int ret;
> +
> +	memset(src_vq, 0, sizeof(*src_vq));
> +	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> +	src_vq->io_modes = VB2_MMAP;
> +	src_vq->drv_priv = ctx;
> +	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
> +	src_vq->ops = &vpe_qops;
> +	src_vq->mem_ops = &vb2_dma_contig_memops;
> +	src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +
> +	ret = vb2_queue_init(src_vq);
> +	if (ret)
> +		return ret;
> +
> +	memset(dst_vq, 0, sizeof(*dst_vq));
> +	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> +	dst_vq->io_modes = VB2_MMAP;
> +	dst_vq->drv_priv = ctx;
> +	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
> +	dst_vq->ops = &vpe_qops;
> +	dst_vq->mem_ops = &vb2_dma_contig_memops;
> +	dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +
> +	return vb2_queue_init(dst_vq);
> +}
> +
> +static const struct v4l2_ctrl_config vpe_bufs_per_job = {
> +	.ops = &vpe_ctrl_ops,
> +	.id = V4L2_CID_VPE_BUFS_PER_JOB,
> +	.name = "Buffers Per Transaction",
> +	.type = V4L2_CTRL_TYPE_INTEGER,
> +	.def = VPE_DEF_BUFS_PER_JOB,
> +	.min = 1,
> +	.max = VIDEO_MAX_FRAME,
> +	.step = 1,
> +};
> +
> +/*
> + * File operations
> + */
> +static int vpe_open(struct file *file)
> +{
> +	struct vpe_dev *dev = video_drvdata(file);
> +	struct vpe_ctx *ctx = NULL;
> +	struct vpe_q_data *s_q_data;
> +	struct v4l2_ctrl_handler *hdl;
> +	int ret;
> +
> +	vpe_dbg(dev, "vpe_open\n");
> +
> +	if (!dev->vpdma->ready) {
> +		vpe_err(dev, "vpdma firmware not loaded\n");
> +		return -ENODEV;
> +	}
> +
> +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	ctx->dev = dev;
> +
> +	if (mutex_lock_interruptible(&dev->dev_mutex)) {
> +		ret = -ERESTARTSYS;
> +		goto free_ctx;
> +	}
> +
> +	ret = vpdma_create_desc_list(&ctx->desc_list, VPE_DESC_LIST_SIZE,
> +			VPDMA_LIST_TYPE_NORMAL);
> +	if (ret != 0)
> +		goto unlock;
> +
> +	ret = vpdma_alloc_desc_buf(&ctx->mmr_adb, sizeof(struct vpe_mmr_adb));
> +	if (ret != 0)
> +		goto free_desc_list;
> +
> +	init_adb_hdrs(ctx);
> +
> +	v4l2_fh_init(&ctx->fh, video_devdata(file));
> +	file->private_data = &ctx->fh;
> +
> +	hdl = &ctx->hdl;
> +	v4l2_ctrl_handler_init(hdl, 1);
> +	v4l2_ctrl_new_custom(hdl, &vpe_bufs_per_job, NULL);
> +	if (hdl->error) {
> +		ret = hdl->error;
> +		goto exit_fh;
> +	}
> +	ctx->fh.ctrl_handler = hdl;
> +	v4l2_ctrl_handler_setup(hdl);
> +
> +	s_q_data = &ctx->q_data[Q_DATA_SRC];
> +	s_q_data->fmt = &vpe_formats[2];
> +	s_q_data->width = 1920;
> +	s_q_data->height = 1080;
> +	s_q_data->sizeimage[VPE_LUMA] = (s_q_data->width * s_q_data->height *
> +			s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3;
> +	s_q_data->colorspace = V4L2_COLORSPACE_SMPTE240M;
> +	s_q_data->c_rect.left = 0;
> +	s_q_data->c_rect.top = 0;
> +	s_q_data->c_rect.width = s_q_data->width;
> +	s_q_data->c_rect.height = s_q_data->height;
> +	s_q_data->flags = 0;
> +
> +	ctx->q_data[Q_DATA_DST] = *s_q_data;
> +
> +	set_src_registers(ctx);
> +	set_dst_registers(ctx);
> +	ret = set_srcdst_params(ctx);
> +	if (ret)
> +		goto exit_fh;
> +
> +	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
> +
> +	if (IS_ERR(ctx->m2m_ctx)) {
> +		ret = PTR_ERR(ctx->m2m_ctx);
> +		goto exit_fh;
> +	}
> +
> +	v4l2_fh_add(&ctx->fh);
> +
> +	/*
> +	 * for now, just report the creation of the first instance, we can later
> +	 * optimize the driver to enable or disable clocks when the first
> +	 * instance is created or the last instance released
> +	 */
> +	if (atomic_inc_return(&dev->num_instances) == 1)
> +		vpe_dbg(dev, "first instance created\n");
> +
> +	ctx->bufs_per_job = VPE_DEF_BUFS_PER_JOB;
> +
> +	ctx->load_mmrs = true;
> +
> +	vpe_dbg(dev, "created instance %p, m2m_ctx: %p\n",
> +		ctx, ctx->m2m_ctx);
> +
> +	mutex_unlock(&dev->dev_mutex);
> +
> +	return 0;
> +exit_fh:
> +	v4l2_ctrl_handler_free(hdl);
> +	v4l2_fh_exit(&ctx->fh);
> +	vpdma_free_desc_buf(&ctx->mmr_adb);
> +free_desc_list:
> +	vpdma_free_desc_list(&ctx->desc_list);
> +unlock:
> +	mutex_unlock(&dev->dev_mutex);
> +free_ctx:
> +	kfree(ctx);
> +	return ret;
> +}
> +
> +static int vpe_release(struct file *file)
> +{
> +	struct vpe_dev *dev = video_drvdata(file);
> +	struct vpe_ctx *ctx = file2ctx(file);
> +
> +	vpe_dbg(dev, "releasing instance %p\n", ctx);
> +
> +	mutex_lock(&dev->dev_mutex);
> +	vpdma_free_desc_list(&ctx->desc_list);
> +	vpdma_free_desc_buf(&ctx->mmr_adb);
> +
> +	v4l2_fh_del(&ctx->fh);
> +	v4l2_fh_exit(&ctx->fh);
> +	v4l2_ctrl_handler_free(&ctx->hdl);
> +	v4l2_m2m_ctx_release(ctx->m2m_ctx);
> +
> +	kfree(ctx);
> +
> +	/*
> +	 * for now, just report the release of the last instance, we can later
> +	 * optimize the driver to enable or disable clocks when the first
> +	 * instance is created or the last instance released
> +	 */
> +	if (atomic_dec_return(&dev->num_instances) == 0)
> +		vpe_dbg(dev, "last instance released\n");
> +
> +	mutex_unlock(&dev->dev_mutex);
> +
> +	return 0;
> +}
> +
> +static unsigned int vpe_poll(struct file *file,
> +			     struct poll_table_struct *wait)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +	struct vpe_dev *dev = ctx->dev;
> +	int ret;
> +
> +	mutex_lock(&dev->dev_mutex);
> +	ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
> +	mutex_unlock(&dev->dev_mutex);
> +	return ret;
> +}
> +
> +static int vpe_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct vpe_ctx *ctx = file2ctx(file);
> +	struct vpe_dev *dev = ctx->dev;
> +	int ret;
> +
> +	if (mutex_lock_interruptible(&dev->dev_mutex))
> +		return -ERESTARTSYS;
> +	ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
> +	mutex_unlock(&dev->dev_mutex);
> +	return ret;
> +}
> +
> +static const struct v4l2_file_operations vpe_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= vpe_open,
> +	.release	= vpe_release,
> +	.poll		= vpe_poll,
> +	.unlocked_ioctl	= video_ioctl2,
> +	.mmap		= vpe_mmap,
> +};
> +
> +static struct video_device vpe_videodev = {
> +	.name		= VPE_MODULE_NAME,
> +	.fops		= &vpe_fops,
> +	.ioctl_ops	= &vpe_ioctl_ops,
> +	.minor		= -1,
> +	.release	= video_device_release,
> +	.vfl_dir	= VFL_DIR_M2M,
> +};
> +
> +static struct v4l2_m2m_ops m2m_ops = {
> +	.device_run	= device_run,
> +	.job_ready	= job_ready,
> +	.job_abort	= job_abort,
> +	.lock		= vpe_lock,
> +	.unlock		= vpe_unlock,
> +};
> +
> +static int vpe_runtime_get(struct platform_device *pdev)
> +{
> +	int r;
> +
> +	dev_dbg(&pdev->dev, "vpe_runtime_get\n");
> +
> +	r = pm_runtime_get_sync(&pdev->dev);
> +	WARN_ON(r < 0);
> +	return r < 0 ? r : 0;
> +}
> +
> +static void vpe_runtime_put(struct platform_device *pdev)
> +{
> +
> +	int r;
> +
> +	dev_dbg(&pdev->dev, "vpe_runtime_put\n");
> +
> +	r = pm_runtime_put_sync(&pdev->dev);
> +	WARN_ON(r < 0 && r != -ENOSYS);
> +}
> +
> +static int vpe_probe(struct platform_device *pdev)
> +{
> +	struct vpe_dev *dev;
> +	struct video_device *vfd;
> +	struct resource *res;
> +	int ret, irq, func;
> +
> +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> +	if (IS_ERR(dev))
> +		return PTR_ERR(dev);
> +
> +	spin_lock_init(&dev->lock);
> +
> +	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> +	if (ret)
> +		return ret;
> +
> +	atomic_set(&dev->num_instances, 0);
> +	mutex_init(&dev->dev_mutex);
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpe_top");
> +	/*
> +	 * HACK: we get resource info from device tree in the form of a list of
> +	 * VPE sub blocks, the driver currently uses only the base of vpe_top
> +	 * for register access, the driver should be changed later to access
> +	 * registers based on the sub block base addresses
> +	 */
> +	dev->base = devm_ioremap(&pdev->dev, res->start, SZ_32K);
> +	if (IS_ERR(dev->base)) {
> +		ret = PTR_ERR(dev->base);
> +		goto v4l2_dev_unreg;
> +	}
> +
> +	irq = platform_get_irq(pdev, 0);
> +	ret = devm_request_irq(&pdev->dev, irq, vpe_irq, 0, VPE_MODULE_NAME,
> +			dev);
> +	if (ret)
> +		goto v4l2_dev_unreg;
> +
> +	platform_set_drvdata(pdev, dev);
> +
> +	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	if (IS_ERR(dev->alloc_ctx)) {
> +		vpe_err(dev, "Failed to alloc vb2 context\n");
> +		ret = PTR_ERR(dev->alloc_ctx);
> +		goto v4l2_dev_unreg;
> +	}
> +
> +	dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
> +	if (IS_ERR(dev->m2m_dev)) {
> +		vpe_err(dev, "Failed to init mem2mem device\n");
> +		ret = PTR_ERR(dev->m2m_dev);
> +		goto rel_ctx;
> +	}
> +
> +	pm_runtime_enable(&pdev->dev);
> +
> +	ret = vpe_runtime_get(pdev);
> +	if (ret)
> +		goto rel_m2m;
> +
> +	/* Perform clk enable followed by reset */
> +	vpe_set_clock_enable(dev, 1);
> +
> +	vpe_top_reset(dev);
> +
> +	func = read_field_reg(dev, VPE_PID, VPE_PID_FUNC_MASK,
> +		VPE_PID_FUNC_SHIFT);
> +	vpe_dbg(dev, "VPE PID function %x\n", func);
> +
> +	vpe_top_vpdma_reset(dev);
> +
> +	dev->vpdma = vpdma_create(pdev);
> +	if (IS_ERR(dev->vpdma))
> +		goto runtime_put;
> +
> +	vfd = &dev->vfd;
> +	*vfd = vpe_videodev;
> +	vfd->lock = &dev->dev_mutex;
> +	vfd->v4l2_dev = &dev->v4l2_dev;
> +
> +	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> +	if (ret) {
> +		vpe_err(dev, "Failed to register video device\n");
> +		goto runtime_put;
> +	}
> +
> +	video_set_drvdata(vfd, dev);
> +	snprintf(vfd->name, sizeof(vfd->name), "%s", vpe_videodev.name);
> +	dev_info(dev->v4l2_dev.dev, "Device registered as /dev/video%d\n",
> +		vfd->num);
> +
> +	return 0;
> +
> +runtime_put:
> +	vpe_runtime_put(pdev);
> +rel_m2m:
> +	pm_runtime_disable(&pdev->dev);
> +	v4l2_m2m_release(dev->m2m_dev);
> +rel_ctx:
> +	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
> +v4l2_dev_unreg:
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +
> +	return ret;
> +}
> +
> +static int vpe_remove(struct platform_device *pdev)
> +{
> +	struct vpe_dev *dev =
> +		(struct vpe_dev *) platform_get_drvdata(pdev);
> +
> +	v4l2_info(&dev->v4l2_dev, "Removing " VPE_MODULE_NAME);
> +
> +	v4l2_m2m_release(dev->m2m_dev);
> +	video_unregister_device(&dev->vfd);
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
> +
> +	vpe_set_clock_enable(dev, 0);
> +	vpe_runtime_put(pdev);
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id vpe_of_match[] = {
> +	{
> +		.compatible = "ti,vpe",
> +	},
> +	{},
> +};
> +#else
> +#define vpe_of_match NULL
> +#endif
> +
> +static struct platform_driver vpe_pdrv = {
> +	.probe		= vpe_probe,
> +	.remove		= vpe_remove,
> +	.driver		= {
> +		.name	= VPE_MODULE_NAME,
> +		.owner	= THIS_MODULE,
> +		.of_match_table = vpe_of_match,
> +	},
> +};
> +
> +static void __exit vpe_exit(void)
> +{
> +	platform_driver_unregister(&vpe_pdrv);
> +}
> +
> +static int __init vpe_init(void)
> +{
> +	return platform_driver_register(&vpe_pdrv);
> +}
> +
> +module_init(vpe_init);
> +module_exit(vpe_exit);
> +
> +MODULE_DESCRIPTION("TI VPE driver");
> +MODULE_AUTHOR("Dale Farnsworth, <dale@xxxxxxxxxxxxxx>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/platform/ti-vpe/vpe_regs.h b/drivers/media/platform/ti-vpe/vpe_regs.h
> new file mode 100644
> index 0000000..ed214e8
> --- /dev/null
> +++ b/drivers/media/platform/ti-vpe/vpe_regs.h
> @@ -0,0 +1,496 @@
> +/*
> + * Copyright (c) 2013 Texas Instruments Inc.
> + *
> + * David Griego, <dagriego@xxxxxxxxxxxxxxxxxxx>
> + * Dale Farnsworth, <dale@xxxxxxxxxxxxxx>
> + * Archit Taneja, <archit@xxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + */
> +
> +#ifndef __TI_VPE_REGS_H
> +#define __TI_VPE_REGS_H
> +
> +/* VPE register offsets and field selectors */
> +
> +/* VPE top level regs */
> +#define VPE_PID				0x0000
> +#define VPE_PID_MINOR_MASK		0x3f
> +#define VPE_PID_MINOR_SHIFT		0
> +#define VPE_PID_CUSTOM_MASK		0x03
> +#define VPE_PID_CUSTOM_SHIFT		6
> +#define VPE_PID_MAJOR_MASK		0x07
> +#define VPE_PID_MAJOR_SHIFT		8
> +#define VPE_PID_RTL_MASK		0x1f
> +#define VPE_PID_RTL_SHIFT		11
> +#define VPE_PID_FUNC_MASK		0xfff
> +#define VPE_PID_FUNC_SHIFT		16
> +#define VPE_PID_SCHEME_MASK		0x03
> +#define VPE_PID_SCHEME_SHIFT		30
> +
> +#define VPE_SYSCONFIG			0x0010
> +#define VPE_SYSCONFIG_IDLE_MASK		0x03
> +#define VPE_SYSCONFIG_IDLE_SHIFT	2
> +#define VPE_SYSCONFIG_STANDBY_MASK	0x03
> +#define VPE_SYSCONFIG_STANDBY_SHIFT	4
> +#define VPE_FORCE_IDLE_MODE		0
> +#define VPE_NO_IDLE_MODE		1
> +#define VPE_SMART_IDLE_MODE		2
> +#define VPE_SMART_IDLE_WAKEUP_MODE	3
> +#define VPE_FORCE_STANDBY_MODE		0
> +#define VPE_NO_STANDBY_MODE		1
> +#define VPE_SMART_STANDBY_MODE		2
> +#define VPE_SMART_STANDBY_WAKEUP_MODE	3
> +
> +#define VPE_INT0_STATUS0_RAW_SET	0x0020
> +#define VPE_INT0_STATUS0_RAW		VPE_INT0_STATUS0_RAW_SET
> +#define VPE_INT0_STATUS0_CLR		0x0028
> +#define VPE_INT0_STATUS0		VPE_INT0_STATUS0_CLR
> +#define VPE_INT0_ENABLE0_SET		0x0030
> +#define VPE_INT0_ENABLE0		VPE_INT0_ENABLE0_SET
> +#define VPE_INT0_ENABLE0_CLR		0x0038
> +#define VPE_INT0_LIST0_COMPLETE		(1 << 0)
> +#define VPE_INT0_LIST0_NOTIFY		(1 << 1)
> +#define VPE_INT0_LIST1_COMPLETE		(1 << 2)
> +#define VPE_INT0_LIST1_NOTIFY		(1 << 3)
> +#define VPE_INT0_LIST2_COMPLETE		(1 << 4)
> +#define VPE_INT0_LIST2_NOTIFY		(1 << 5)
> +#define VPE_INT0_LIST3_COMPLETE		(1 << 6)
> +#define VPE_INT0_LIST3_NOTIFY		(1 << 7)
> +#define VPE_INT0_LIST4_COMPLETE		(1 << 8)
> +#define VPE_INT0_LIST4_NOTIFY		(1 << 9)
> +#define VPE_INT0_LIST5_COMPLETE		(1 << 10)
> +#define VPE_INT0_LIST5_NOTIFY		(1 << 11)
> +#define VPE_INT0_LIST6_COMPLETE		(1 << 12)
> +#define VPE_INT0_LIST6_NOTIFY		(1 << 13)
> +#define VPE_INT0_LIST7_COMPLETE		(1 << 14)
> +#define VPE_INT0_LIST7_NOTIFY		(1 << 15)
> +#define VPE_INT0_DESCRIPTOR		(1 << 16)
> +#define VPE_DEI_FMD_INT			(1 << 18)
> +
> +#define VPE_INT0_STATUS1_RAW_SET	0x0024
> +#define VPE_INT0_STATUS1_RAW		VPE_INT0_STATUS1_RAW_SET
> +#define VPE_INT0_STATUS1_CLR		0x002c
> +#define VPE_INT0_STATUS1		VPE_INT0_STATUS1_CLR
> +#define VPE_INT0_ENABLE1_SET		0x0034
> +#define VPE_INT0_ENABLE1		VPE_INT0_ENABLE1_SET
> +#define VPE_INT0_ENABLE1_CLR		0x003c
> +#define VPE_INT0_CHANNEL_GROUP0		(1 << 0)
> +#define VPE_INT0_CHANNEL_GROUP1		(1 << 1)
> +#define VPE_INT0_CHANNEL_GROUP2		(1 << 2)
> +#define VPE_INT0_CHANNEL_GROUP3		(1 << 3)
> +#define VPE_INT0_CHANNEL_GROUP4		(1 << 4)
> +#define VPE_INT0_CHANNEL_GROUP5		(1 << 5)
> +#define VPE_INT0_CLIENT			(1 << 7)
> +#define VPE_DEI_ERROR_INT		(1 << 16)
> +#define VPE_DS1_UV_ERROR_INT		(1 << 22)
> +
> +#define VPE_INTC_EOI			0x00a0
> +
> +#define VPE_CLK_ENABLE			0x0100
> +#define VPE_VPEDMA_CLK_ENABLE		(1 << 0)
> +#define VPE_DATA_PATH_CLK_ENABLE	(1 << 1)
> +
> +#define VPE_CLK_RESET			0x0104
> +#define VPE_VPDMA_CLK_RESET_MASK	0x1
> +#define VPE_VPDMA_CLK_RESET_SHIFT	0
> +#define VPE_DATA_PATH_CLK_RESET_MASK	0x1
> +#define VPE_DATA_PATH_CLK_RESET_SHIFT	1
> +#define VPE_MAIN_RESET_MASK		0x1
> +#define VPE_MAIN_RESET_SHIFT		31
> +
> +#define VPE_CLK_FORMAT_SELECT		0x010c
> +#define VPE_CSC_SRC_SELECT_MASK		0x03
> +#define VPE_CSC_SRC_SELECT_SHIFT	0
> +#define VPE_RGB_OUT_SELECT		(1 << 8)
> +#define VPE_DS_SRC_SELECT_MASK		0x07
> +#define VPE_DS_SRC_SELECT_SHIFT		9
> +#define VPE_DS_BYPASS			(1 << 16)
> +#define VPE_COLOR_SEPARATE_422		(1 << 18)
> +
> +#define VPE_DS_SRC_DEI_SCALER		(5 << VPE_DS_SRC_SELECT_SHIFT)
> +#define VPE_CSC_SRC_DEI_SCALER		(3 << VPE_CSC_SRC_SELECT_SHIFT)
> +
> +#define VPE_CLK_RANGE_MAP		0x011c
> +#define VPE_RANGE_RANGE_MAP_Y_MASK	0x07
> +#define VPE_RANGE_RANGE_MAP_Y_SHIFT	0
> +#define VPE_RANGE_RANGE_MAP_UV_MASK	0x07
> +#define VPE_RANGE_RANGE_MAP_UV_SHIFT	3
> +#define VPE_RANGE_MAP_ON		(1 << 6)
> +#define VPE_RANGE_REDUCTION_ON		(1 << 28)
> +
> +/* VPE chrominance upsampler regs */
> +#define VPE_US1_R0			0x0304
> +#define VPE_US2_R0			0x0404
> +#define VPE_US3_R0			0x0504
> +#define VPE_US_C1_MASK			0x3fff
> +#define VPE_US_C1_SHIFT			2
> +#define VPE_US_C0_MASK			0x3fff
> +#define VPE_US_C0_SHIFT			18
> +#define VPE_US_MODE_MASK		0x03
> +#define VPE_US_MODE_SHIFT		16
> +#define VPE_ANCHOR_FID0_C1_MASK		0x3fff
> +#define VPE_ANCHOR_FID0_C1_SHIFT	2
> +#define VPE_ANCHOR_FID0_C0_MASK		0x3fff
> +#define VPE_ANCHOR_FID0_C0_SHIFT	18
> +
> +#define VPE_US1_R1			0x0308
> +#define VPE_US2_R1			0x0408
> +#define VPE_US3_R1			0x0508
> +#define VPE_ANCHOR_FID0_C3_MASK		0x3fff
> +#define VPE_ANCHOR_FID0_C3_SHIFT	2
> +#define VPE_ANCHOR_FID0_C2_MASK		0x3fff
> +#define VPE_ANCHOR_FID0_C2_SHIFT	18
> +
> +#define VPE_US1_R2			0x030c
> +#define VPE_US2_R2			0x040c
> +#define VPE_US3_R2			0x050c
> +#define VPE_INTERP_FID0_C1_MASK		0x3fff
> +#define VPE_INTERP_FID0_C1_SHIFT	2
> +#define VPE_INTERP_FID0_C0_MASK		0x3fff
> +#define VPE_INTERP_FID0_C0_SHIFT	18
> +
> +#define VPE_US1_R3			0x0310
> +#define VPE_US2_R3			0x0410
> +#define VPE_US3_R3			0x0510
> +#define VPE_INTERP_FID0_C3_MASK		0x3fff
> +#define VPE_INTERP_FID0_C3_SHIFT	2
> +#define VPE_INTERP_FID0_C2_MASK		0x3fff
> +#define VPE_INTERP_FID0_C2_SHIFT	18
> +
> +#define VPE_US1_R4			0x0314
> +#define VPE_US2_R4			0x0414
> +#define VPE_US3_R4			0x0514
> +#define VPE_ANCHOR_FID1_C1_MASK		0x3fff
> +#define VPE_ANCHOR_FID1_C1_SHIFT	2
> +#define VPE_ANCHOR_FID1_C0_MASK		0x3fff
> +#define VPE_ANCHOR_FID1_C0_SHIFT	18
> +
> +#define VPE_US1_R5			0x0318
> +#define VPE_US2_R5			0x0418
> +#define VPE_US3_R5			0x0518
> +#define VPE_ANCHOR_FID1_C3_MASK		0x3fff
> +#define VPE_ANCHOR_FID1_C3_SHIFT	2
> +#define VPE_ANCHOR_FID1_C2_MASK		0x3fff
> +#define VPE_ANCHOR_FID1_C2_SHIFT	18
> +
> +#define VPE_US1_R6			0x031c
> +#define VPE_US2_R6			0x041c
> +#define VPE_US3_R6			0x051c
> +#define VPE_INTERP_FID1_C1_MASK		0x3fff
> +#define VPE_INTERP_FID1_C1_SHIFT	2
> +#define VPE_INTERP_FID1_C0_MASK		0x3fff
> +#define VPE_INTERP_FID1_C0_SHIFT	18
> +
> +#define VPE_US1_R7			0x0320
> +#define VPE_US2_R7			0x0420
> +#define VPE_US3_R7			0x0520
> +#define VPE_INTERP_FID0_C3_MASK		0x3fff
> +#define VPE_INTERP_FID0_C3_SHIFT	2
> +#define VPE_INTERP_FID0_C2_MASK		0x3fff
> +#define VPE_INTERP_FID0_C2_SHIFT	18
> +
> +/* VPE de-interlacer regs */
> +#define VPE_DEI_FRAME_SIZE		0x0600
> +#define VPE_DEI_WIDTH_MASK		0x07ff
> +#define VPE_DEI_WIDTH_SHIFT		0
> +#define VPE_DEI_HEIGHT_MASK		0x07ff
> +#define VPE_DEI_HEIGHT_SHIFT		16
> +#define VPE_DEI_INTERLACE_BYPASS	(1 << 29)
> +#define VPE_DEI_FIELD_FLUSH		(1 << 30)
> +#define VPE_DEI_PROGRESSIVE		(1 << 31)
> +
> +#define VPE_MDT_BYPASS			0x0604
> +#define VPE_MDT_TEMPMAX_BYPASS		(1 << 0)
> +#define VPE_MDT_SPATMAX_BYPASS		(1 << 1)
> +
> +#define VPE_MDT_SF_THRESHOLD		0x0608
> +#define VPE_MDT_SF_SC_THR1_MASK		0xff
> +#define VPE_MDT_SF_SC_THR1_SHIFT	0
> +#define VPE_MDT_SF_SC_THR2_MASK		0xff
> +#define VPE_MDT_SF_SC_THR2_SHIFT	0
> +#define VPE_MDT_SF_SC_THR3_MASK		0xff
> +#define VPE_MDT_SF_SC_THR3_SHIFT	0
> +
> +#define VPE_EDI_CONFIG			0x060c
> +#define VPE_EDI_INP_MODE_MASK		0x03
> +#define VPE_EDI_INP_MODE_SHIFT		0
> +#define VPE_EDI_ENABLE_3D		(1 << 2)
> +#define VPE_EDI_ENABLE_CHROMA_3D	(1 << 3)
> +#define VPE_EDI_CHROMA3D_COR_THR_MASK	0xff
> +#define VPE_EDI_CHROMA3D_COR_THR_SHIFT	8
> +#define VPE_EDI_DIR_COR_LOWER_THR_MASK	0xff
> +#define VPE_EDI_DIR_COR_LOWER_THR_SHIFT	16
> +#define VPE_EDI_COR_SCALE_FACTOR_MASK	0xff
> +#define VPE_EDI_COR_SCALE_FACTOR_SHIFT	23
> +
> +#define VPE_DEI_EDI_LUT_R0		0x0610
> +#define VPE_EDI_LUT0_MASK		0x1f
> +#define VPE_EDI_LUT0_SHIFT		0
> +#define VPE_EDI_LUT1_MASK		0x1f
> +#define VPE_EDI_LUT1_SHIFT		8
> +#define VPE_EDI_LUT2_MASK		0x1f
> +#define VPE_EDI_LUT2_SHIFT		16
> +#define VPE_EDI_LUT3_MASK		0x1f
> +#define VPE_EDI_LUT3_SHIFT		24
> +
> +#define VPE_DEI_EDI_LUT_R1		0x0614
> +#define VPE_EDI_LUT0_MASK		0x1f
> +#define VPE_EDI_LUT0_SHIFT		0
> +#define VPE_EDI_LUT1_MASK		0x1f
> +#define VPE_EDI_LUT1_SHIFT		8
> +#define VPE_EDI_LUT2_MASK		0x1f
> +#define VPE_EDI_LUT2_SHIFT		16
> +#define VPE_EDI_LUT3_MASK		0x1f
> +#define VPE_EDI_LUT3_SHIFT		24
> +
> +#define VPE_DEI_EDI_LUT_R2		0x0618
> +#define VPE_EDI_LUT4_MASK		0x1f
> +#define VPE_EDI_LUT4_SHIFT		0
> +#define VPE_EDI_LUT5_MASK		0x1f
> +#define VPE_EDI_LUT5_SHIFT		8
> +#define VPE_EDI_LUT6_MASK		0x1f
> +#define VPE_EDI_LUT6_SHIFT		16
> +#define VPE_EDI_LUT7_MASK		0x1f
> +#define VPE_EDI_LUT7_SHIFT		24
> +
> +#define VPE_DEI_EDI_LUT_R3		0x061c
> +#define VPE_EDI_LUT8_MASK		0x1f
> +#define VPE_EDI_LUT8_SHIFT		0
> +#define VPE_EDI_LUT9_MASK		0x1f
> +#define VPE_EDI_LUT9_SHIFT		8
> +#define VPE_EDI_LUT10_MASK		0x1f
> +#define VPE_EDI_LUT10_SHIFT		16
> +#define VPE_EDI_LUT11_MASK		0x1f
> +#define VPE_EDI_LUT11_SHIFT		24
> +
> +#define VPE_DEI_FMD_WINDOW_R0		0x0620
> +#define VPE_FMD_WINDOW_MINX_MASK	0x07ff
> +#define VPE_FMD_WINDOW_MINX_SHIFT	0
> +#define VPE_FMD_WINDOW_MAXX_MASK	0x07ff
> +#define VPE_FMD_WINDOW_MAXX_SHIFT	16
> +#define VPE_FMD_WINDOW_ENABLE		(1 << 31)
> +
> +#define VPE_DEI_FMD_WINDOW_R1		0x0624
> +#define VPE_FMD_WINDOW_MINY_MASK	0x07ff
> +#define VPE_FMD_WINDOW_MINY_SHIFT	0
> +#define VPE_FMD_WINDOW_MAXY_MASK	0x07ff
> +#define VPE_FMD_WINDOW_MAXY_SHIFT	16
> +
> +#define VPE_DEI_FMD_CONTROL_R0		0x0628
> +#define VPE_FMD_ENABLE			(1 << 0)
> +#define VPE_FMD_LOCK			(1 << 1)
> +#define VPE_FMD_JAM_DIR			(1 << 2)
> +#define VPE_FMD_BED_ENABLE		(1 << 3)
> +#define VPE_FMD_CAF_FIELD_THR_MASK	0xff
> +#define VPE_FMD_CAF_FIELD_THR_SHIFT	16
> +#define VPE_FMD_CAF_LINE_THR_MASK	0xff
> +#define VPE_FMD_CAF_LINE_THR_SHIFT	24
> +
> +#define VPE_DEI_FMD_CONTROL_R1		0x062c
> +#define VPE_FMD_CAF_THR_MASK		0x000fffff
> +#define VPE_FMD_CAF_THR_SHIFT		0
> +
> +#define VPE_DEI_FMD_STATUS_R0		0x0630
> +#define VPE_FMD_CAF_MASK		0x000fffff
> +#define VPE_FMD_CAF_SHIFT		0
> +#define VPE_FMD_RESET			(1 << 24)
> +
> +#define VPE_DEI_FMD_STATUS_R1		0x0634
> +#define VPE_FMD_FIELD_DIFF_MASK		0x0fffffff
> +#define VPE_FMD_FIELD_DIFF_SHIFT	0
> +
> +#define VPE_DEI_FMD_STATUS_R2		0x0638
> +#define VPE_FMD_FRAME_DIFF_MASK		0x000fffff
> +#define VPE_FMD_FRAME_DIFF_SHIFT	0
> +
> +/* VPE scaler regs */
> +#define VPE_SC_MP_SC0			0x0700
> +#define VPE_INTERLACE_O			(1 << 0)
> +#define VPE_LINEAR			(1 << 1)
> +#define VPE_SC_BYPASS			(1 << 2)
> +#define VPE_INVT_FID			(1 << 3)
> +#define VPE_USE_RAV			(1 << 4)
> +#define VPE_ENABLE_EV			(1 << 5)
> +#define VPE_AUTO_HS			(1 << 6)
> +#define VPE_DCM_2X			(1 << 7)
> +#define VPE_DCM_4X			(1 << 8)
> +#define VPE_HP_BYPASS			(1 << 9)
> +#define VPE_INTERLACE_I			(1 << 10)
> +#define VPE_ENABLE_SIN2_VER_INTP	(1 << 11)
> +#define VPE_Y_PK_EN			(1 << 14)
> +#define VPE_TRIM			(1 << 15)
> +#define VPE_SELFGEN_FID			(1 << 16)
> +
> +#define VPE_SC_MP_SC1			0x0704
> +#define VPE_ROW_ACC_INC_MASK		0x07ffffff
> +#define VPE_ROW_ACC_INC_SHIFT		0
> +
> +#define VPE_SC_MP_SC2			0x0708
> +#define VPE_ROW_ACC_OFFSET_MASK		0x0fffffff
> +#define VPE_ROW_ACC_OFFSET_SHIFT	0
> +
> +#define VPE_SC_MP_SC3			0x070c
> +#define VPE_ROW_ACC_OFFSET_B_MASK	0x0fffffff
> +#define VPE_ROW_ACC_OFFSET_B_SHIFT	0
> +
> +#define VPE_SC_MP_SC4			0x0710
> +#define VPE_TAR_H_MASK			0x07ff
> +#define VPE_TAR_H_SHIFT			0
> +#define VPE_TAR_W_MASK			0x07ff
> +#define VPE_TAR_W_SHIFT			12
> +#define VPE_LIN_ACC_INC_U_MASK		0x07
> +#define VPE_LIN_ACC_INC_U_SHIFT		24
> +#define VPE_NLIN_ACC_INIT_U_MASK	0x07
> +#define VPE_NLIN_ACC_INIT_U_SHIFT	28
> +
> +#define VPE_SC_MP_SC5			0x0714
> +#define VPE_SRC_H_MASK			0x07ff
> +#define VPE_SRC_H_SHIFT			0
> +#define VPE_SRC_W_MASK			0x07ff
> +#define VPE_SRC_W_SHIFT			12
> +#define VPE_NLIN_ACC_INC_U_MASK		0x07
> +#define VPE_NLIN_ACC_INC_U_SHIFT	24
> +
> +#define VPE_SC_MP_SC6			0x0718
> +#define VPE_ROW_ACC_INIT_RAV_MASK	0x03ff
> +#define VPE_ROW_ACC_INIT_RAV_SHIFT	0
> +#define VPE_ROW_ACC_INIT_RAV_B_MASK	0x03ff
> +#define VPE_ROW_ACC_INIT_RAV_B_SHIFT	10
> +
> +#define VPE_SC_MP_SC8			0x0720
> +#define VPE_NLIN_LEFT_MASK		0x07ff
> +#define VPE_NLIN_LEFT_SHIFT		0
> +#define VPE_NLIN_RIGHT_MASK		0x07ff
> +#define VPE_NLIN_RIGHT_SHIFT		12
> +
> +#define VPE_SC_MP_SC9			0x0724
> +#define VPE_LIN_ACC_INC			VPE_SC_MP_SC9
> +
> +#define VPE_SC_MP_SC10			0x0728
> +#define VPE_NLIN_ACC_INIT		VPE_SC_MP_SC10
> +
> +#define VPE_SC_MP_SC11			0x072c
> +#define VPE_NLIN_ACC_INC		VPE_SC_MP_SC11
> +
> +#define VPE_SC_MP_SC12			0x0730
> +#define VPE_COL_ACC_OFFSET_MASK		0x01ffffff
> +#define VPE_COL_ACC_OFFSET_SHIFT	0
> +
> +#define VPE_SC_MP_SC13			0x0734
> +#define VPE_SC_FACTOR_RAV_MASK		0x03ff
> +#define VPE_SC_FACTOR_RAV_SHIFT		0
> +#define VPE_CHROMA_INTP_THR_MASK	0x03ff
> +#define VPE_CHROMA_INTP_THR_SHIFT	12
> +#define VPE_DELTA_CHROMA_THR_MASK	0x0f
> +#define VPE_DELTA_CHROMA_THR_SHIFT	24
> +
> +#define VPE_SC_MP_SC17			0x0744
> +#define VPE_EV_THR_MASK			0x03ff
> +#define VPE_EV_THR_SHIFT		12
> +#define VPE_DELTA_LUMA_THR_MASK		0x0f
> +#define VPE_DELTA_LUMA_THR_SHIFT	24
> +#define VPE_DELTA_EV_THR_MASK		0x0f
> +#define VPE_DELTA_EV_THR_SHIFT		28
> +
> +#define VPE_SC_MP_SC18			0x0748
> +#define VPE_HS_FACTOR_MASK		0x03ff
> +#define VPE_HS_FACTOR_SHIFT		0
> +#define VPE_CONF_DEFAULT_MASK		0x01ff
> +#define VPE_CONF_DEFAULT_SHIFT		16
> +
> +#define VPE_SC_MP_SC19			0x074c
> +#define VPE_HPF_COEFF0_MASK		0xff
> +#define VPE_HPF_COEFF0_SHIFT		0
> +#define VPE_HPF_COEFF1_MASK		0xff
> +#define VPE_HPF_COEFF1_SHIFT		8
> +#define VPE_HPF_COEFF2_MASK		0xff
> +#define VPE_HPF_COEFF2_SHIFT		16
> +#define VPE_HPF_COEFF3_MASK		0xff
> +#define VPE_HPF_COEFF3_SHIFT		23
> +
> +#define VPE_SC_MP_SC20			0x0750
> +#define VPE_HPF_COEFF4_MASK		0xff
> +#define VPE_HPF_COEFF4_SHIFT		0
> +#define VPE_HPF_COEFF5_MASK		0xff
> +#define VPE_HPF_COEFF5_SHIFT		8
> +#define VPE_HPF_NORM_SHIFT_MASK		0x07
> +#define VPE_HPF_NORM_SHIFT_SHIFT	16
> +#define VPE_NL_LIMIT_MASK		0x1ff
> +#define VPE_NL_LIMIT_SHIFT		20
> +
> +#define VPE_SC_MP_SC21			0x0754
> +#define VPE_NL_LO_THR_MASK		0x01ff
> +#define VPE_NL_LO_THR_SHIFT		0
> +#define VPE_NL_LO_SLOPE_MASK		0xff
> +#define VPE_NL_LO_SLOPE_SHIFT		16
> +
> +#define VPE_SC_MP_SC22			0x0758
> +#define VPE_NL_HI_THR_MASK		0x01ff
> +#define VPE_NL_HI_THR_SHIFT		0
> +#define VPE_NL_HI_SLOPE_SH_MASK		0x07
> +#define VPE_NL_HI_SLOPE_SH_SHIFT	16
> +
> +#define VPE_SC_MP_SC23			0x075c
> +#define VPE_GRADIENT_THR_MASK		0x07ff
> +#define VPE_GRADIENT_THR_SHIFT		0
> +#define VPE_GRADIENT_THR_RANGE_MASK	0x0f
> +#define VPE_GRADIENT_THR_RANGE_SHIFT	12
> +#define VPE_MIN_GY_THR_MASK		0xff
> +#define VPE_MIN_GY_THR_SHIFT		16
> +#define VPE_MIN_GY_THR_RANGE_MASK	0x0f
> +#define VPE_MIN_GY_THR_RANGE_SHIFT	28
> +
> +#define VPE_SC_MP_SC24			0x0760
> +#define VPE_ORG_H_MASK			0x07ff
> +#define VPE_ORG_H_SHIFT			0
> +#define VPE_ORG_W_MASK			0x07ff
> +#define VPE_ORG_W_SHIFT			16
> +
> +#define VPE_SC_MP_SC25			0x0764
> +#define VPE_OFF_H_MASK			0x07ff
> +#define VPE_OFF_H_SHIFT			0
> +#define VPE_OFF_W_MASK			0x07ff
> +#define VPE_OFF_W_SHIFT			16
> +
> +/* VPE color space converter regs */
> +#define VPE_CSC_CSC00			0x5700
> +#define VPE_CSC_A0_MASK			0x1fff
> +#define VPE_CSC_A0_SHIFT		0
> +#define VPE_CSC_B0_MASK			0x1fff
> +#define VPE_CSC_B0_SHIFT		16
> +
> +#define VPE_CSC_CSC01			0x5704
> +#define VPE_CSC_C0_MASK			0x1fff
> +#define VPE_CSC_C0_SHIFT		0
> +#define VPE_CSC_A1_MASK			0x1fff
> +#define VPE_CSC_A1_SHIFT		16
> +
> +#define VPE_CSC_CSC02			0x5708
> +#define VPE_CSC_B1_MASK			0x1fff
> +#define VPE_CSC_B1_SHIFT		0
> +#define VPE_CSC_C1_MASK			0x1fff
> +#define VPE_CSC_C1_SHIFT		16
> +
> +#define VPE_CSC_CSC03			0x570c
> +#define VPE_CSC_A2_MASK			0x1fff
> +#define VPE_CSC_A2_SHIFT		0
> +#define VPE_CSC_B2_MASK			0x1fff
> +#define VPE_CSC_B2_SHIFT		16
> +
> +#define VPE_CSC_CSC04			0x5710
> +#define VPE_CSC_C2_MASK			0x1fff
> +#define VPE_CSC_C2_SHIFT		0
> +#define VPE_CSC_D0_MASK			0x0fff
> +#define VPE_CSC_D0_SHIFT		16
> +
> +#define VPE_CSC_CSC05			0x5714
> +#define VPE_CSC_D1_MASK			0x0fff
> +#define VPE_CSC_D1_SHIFT		0
> +#define VPE_CSC_D2_MASK			0x0fff
> +#define VPE_CSC_D2_SHIFT		16
> +#define VPE_CSC_BYPASS			(1 << 28)
> +
> +#endif
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 083bb5a..1666aab 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -160,6 +160,10 @@ enum v4l2_colorfx {
>   * of controls. Total of 16 controls is reserved for this driver */
>  #define V4L2_CID_USER_SI476X_BASE		(V4L2_CID_USER_BASE + 0x1040)
>  
> +/* The base for the TI VPE driver controls. Total of 16 controls is reserved for
> + * this driver */
> +#define V4L2_CID_USER_TI_VPE_BASE		(V4L2_CID_USER_BASE + 0x1050)
> +
>  /* MPEG-class control IDs */
>  /* The MPEG controls are applicable to all codec controls
>   * and the 'MPEG' part of the define is historical */
> 

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux