From: Hans Verkuil <hverkuil@xs4all.nl>
To: Steve Longerbeam <slongerbeam@gmail.com>,
robh+dt@kernel.org, mark.rutland@arm.com, shawnguo@kernel.org,
kernel@pengutronix.de, fabio.estevam@nxp.com,
linux@armlinux.org.uk, mchehab@kernel.org, nick@shmanahar.org,
markus.heiser@darmarIT.de, p.zabel@pengutronix.de,
laurent.pinchart+renesas@ideasonboard.com, bparrot@ti.com,
geert@linux-m68k.org, arnd@arndb.de, sudipm.mukherjee@gmail.com,
minghsiu.tsai@mediatek.com, tiffany.lin@mediatek.com,
jean-christophe.trotin@st.com, horms+renesas@verge.net.au,
niklas.soderlund+renesas@ragnatech.se, robert.jarzmik@free.fr,
songjun.wu@microchip.com, andrew-ct.chen@mediatek.com,
gregkh@linuxfoundation.org
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-media@vger.kernel.org, devel@driverdev.osuosl.org,
Steve Longerbeam <steve_longerbeam@mentor.com>
Subject: Re: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver
Date: Fri, 20 Jan 2017 15:38:28 +0100 [thread overview]
Message-ID: <b7456d40-040d-41b7-45bc-ef6709ab7933@xs4all.nl> (raw)
In-Reply-To: <1483755102-24785-21-git-send-email-steve_longerbeam@mentor.com>
On 01/07/2017 03:11 AM, Steve Longerbeam wrote:
> This is the camera interface driver that provides the v4l2
> user interface. Frames can be received from various sources:
>
> - directly from SMFC for capturing unconverted images directly from
> camera sensors.
>
> - from the IC pre-process encode task.
>
> - from the IC pre-process viewfinder task.
>
> - from the IC post-process task.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> drivers/staging/media/imx/Makefile | 2 +-
> drivers/staging/media/imx/imx-camif.c | 1000 +++++++++++++++++++++++++++++++++
> 2 files changed, 1001 insertions(+), 1 deletion(-)
> create mode 100644 drivers/staging/media/imx/imx-camif.c
>
> diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
> index d2a962c..fe9e992 100644
> --- a/drivers/staging/media/imx/Makefile
> +++ b/drivers/staging/media/imx/Makefile
> @@ -8,4 +8,4 @@ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-ic.o
>
> obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-csi.o
> obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-smfc.o
> -
> +obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-camif.o
> diff --git a/drivers/staging/media/imx/imx-camif.c b/drivers/staging/media/imx/imx-camif.c
> new file mode 100644
> index 0000000..404f724
> --- /dev/null
> +++ b/drivers/staging/media/imx/imx-camif.c
> @@ -0,0 +1,1000 @@
> +/*
> + * Video Camera Capture Subdev for Freescale i.MX5/6 SOC
> + *
> + * Copyright (c) 2012-2016 Mentor Graphics Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +#include <linux/delay.h>
> +#include <linux/fs.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/timer.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-of.h>
> +#include <media/v4l2-subdev.h>
> +#include <media/videobuf2-dma-contig.h>
> +#include <video/imx-ipu-v3.h>
> +#include <media/imx.h>
> +#include "imx-media.h"
> +
> +#define CAMIF_NUM_PADS 2
> +
> +struct camif_priv {
> + struct device *dev;
> + struct video_device vfd;
> + struct media_pipeline mp;
> + struct imx_media_dev *md;
> + struct v4l2_subdev sd;
> + struct media_pad pad[CAMIF_NUM_PADS];
> + struct media_pad vd_pad;
> + int id;
> + int input_pad;
> + int output_pad;
> +
> + struct v4l2_mbus_framefmt format_mbus[CAMIF_NUM_PADS];
> + const struct imx_media_pixfmt *cc[CAMIF_NUM_PADS];
> +
> + /* dma buffer ring */
> + struct imx_media_dma_buf_ring *in_ring;
> + struct v4l2_subdev *src_sd;
> +
> + struct mutex mutex; /* capture device mutex */
> + spinlock_t q_lock; /* protect ready_q */
> +
> + /* buffer queue used in videobuf2 */
> + struct vb2_queue buffer_queue;
> +
> + /* streaming buffer queue */
> + struct list_head ready_q;
> +
> + /* controls inherited from subdevs */
> + struct v4l2_ctrl_handler ctrl_hdlr;
> +
> + /* misc status */
> + int current_input; /* the current input */
> + v4l2_std_id current_std; /* current standard */
> + bool stop; /* streaming is stopping */
> +};
> +
> +/* In bytes, per queue */
> +#define VID_MEM_LIMIT SZ_64M
> +
> +static struct vb2_ops camif_qops;
> +
> +/*
> + * Video ioctls follow
> + */
> +
> +static int vidioc_querycap(struct file *file, void *fh,
> + struct v4l2_capability *cap)
> +{
> + strncpy(cap->driver, "imx-media-camif", sizeof(cap->driver) - 1);
> + strncpy(cap->card, "imx-media-camif", sizeof(cap->card) - 1);
> + cap->bus_info[0] = 0;
Should be set to something like 'platform:imx-media-camif'. v4l2-compliance should
complain about this.
> + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
> + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Set device_caps in struct video_device, then drop these two lines since
the core will set these up based on the device_caps field in struct video_device.
> +
> + return 0;
> +}
> +
> +static int camif_enum_fmt_vid_cap(struct file *file, void *fh,
> + struct v4l2_fmtdesc *f)
> +{
> + const struct imx_media_pixfmt *cc;
> + u32 code;
> + int ret;
> +
> + ret = imx_media_enum_format(&code, f->index, true, true);
> + if (ret)
> + return ret;
> + cc = imx_media_find_format(0, code, true, true);
> + if (!cc)
> + return -EINVAL;
> +
> + f->pixelformat = cc->fourcc;
> +
> + return 0;
> +}
> +
> +static int camif_g_fmt_vid_cap(struct file *file, void *fh,
> + struct v4l2_format *f)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct v4l2_mbus_framefmt *outfmt;
> +
> + /* user format is the same as the format from output pad */
> + outfmt = &priv->format_mbus[priv->output_pad];
> + return imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, outfmt);
> +}
> +
> +static int camif_try_fmt_vid_cap(struct file *file, void *fh,
> + struct v4l2_format *f)
> +{
> + return camif_g_fmt_vid_cap(file, fh, f);
> +}
> +
> +static int camif_s_fmt_vid_cap(struct file *file, void *fh,
> + struct v4l2_format *f)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> +
> + if (vb2_is_busy(&priv->buffer_queue)) {
> + v4l2_err(&priv->sd, "%s queue busy\n", __func__);
> + return -EBUSY;
> + }
> +
> + return camif_try_fmt_vid_cap(file, priv, f);
> +}
> +
> +static int camif_querystd(struct file *file, void *fh, v4l2_std_id *std)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + return v4l2_subdev_call(sensor->sd, video, querystd, std);
> +}
> +
> +static int camif_g_std(struct file *file, void *fh, v4l2_std_id *std)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> +
> + *std = priv->current_std;
> + return 0;
> +}
> +
> +static int camif_s_std(struct file *file, void *fh, v4l2_std_id std)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> + int ret;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + if (vb2_is_busy(&priv->buffer_queue))
> + return -EBUSY;
> +
> + ret = v4l2_subdev_call(sensor->sd, video, s_std, std);
> + if (ret < 0)
> + return ret;
> +
> + priv->current_std = std;
> + return 0;
> +}
> +
> +static int camif_enum_input(struct file *file, void *fh,
> + struct v4l2_input *input)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> + int index = input->index;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + if (index >= sensor->input.num)
> + return -EINVAL;
> +
> + input->type = V4L2_INPUT_TYPE_CAMERA;
> + strncpy(input->name, sensor->input.name[index], sizeof(input->name));
> +
> + if (index == priv->current_input) {
> + v4l2_subdev_call(sensor->sd, video, g_input_status,
> + &input->status);
> + v4l2_subdev_call(sensor->sd, video, querystd, &input->std);
Wrong op, use g_tvnorms instead.
> + } else {
> + input->status = V4L2_IN_ST_NO_SIGNAL;
> + input->std = V4L2_STD_UNKNOWN;
> + }
> +
> + return 0;
> +}
> +
> +static int camif_g_input(struct file *file, void *fh, unsigned int *index)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> +
> + *index = priv->current_input;
> + return 0;
> +}
> +
> +static int camif_s_input(struct file *file, void *fh, unsigned int index)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> + int ret;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + if (index >= sensor->input.num)
> + return -EINVAL;
> +
> + if (index == priv->current_input)
> + return 0;
> +
> + /* select the sensor's input */
> + ret = v4l2_subdev_call(sensor->sd, video, s_routing,
> + sensor->input.value[index], 0, 0);
> + if (!ret)
> + priv->current_input = index;
> +
> + return ret;
> +}
> +
> +static int camif_g_parm(struct file *file, void *fh,
> + struct v4l2_streamparm *a)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + return -EINVAL;
> +
> + return v4l2_subdev_call(sensor->sd, video, g_parm, a);
> +}
> +
> +static int camif_s_parm(struct file *file, void *fh,
> + struct v4l2_streamparm *a)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct imx_media_subdev *sensor;
> +
> + sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
> + if (IS_ERR(sensor)) {
> + v4l2_err(&priv->sd, "no sensor attached\n");
> + return PTR_ERR(sensor);
> + }
> +
> + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + return -EINVAL;
> +
> + return v4l2_subdev_call(sensor->sd, video, s_parm, a);
> +}
> +
> +static const struct v4l2_ioctl_ops camif_ioctl_ops = {
> + .vidioc_querycap = vidioc_querycap,
> +
> + .vidioc_enum_fmt_vid_cap = camif_enum_fmt_vid_cap,
> + .vidioc_g_fmt_vid_cap = camif_g_fmt_vid_cap,
> + .vidioc_try_fmt_vid_cap = camif_try_fmt_vid_cap,
> + .vidioc_s_fmt_vid_cap = camif_s_fmt_vid_cap,
> +
> + .vidioc_querystd = camif_querystd,
> + .vidioc_g_std = camif_g_std,
> + .vidioc_s_std = camif_s_std,
> +
> + .vidioc_enum_input = camif_enum_input,
> + .vidioc_g_input = camif_g_input,
> + .vidioc_s_input = camif_s_input,
> +
> + .vidioc_g_parm = camif_g_parm,
> + .vidioc_s_parm = camif_s_parm,
> +
> + .vidioc_reqbufs = vb2_ioctl_reqbufs,
> + .vidioc_create_bufs = vb2_ioctl_create_bufs,
> + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
> + .vidioc_querybuf = vb2_ioctl_querybuf,
> + .vidioc_qbuf = vb2_ioctl_qbuf,
> + .vidioc_dqbuf = vb2_ioctl_dqbuf,
> + .vidioc_expbuf = vb2_ioctl_expbuf,
> + .vidioc_streamon = vb2_ioctl_streamon,
> + .vidioc_streamoff = vb2_ioctl_streamoff,
> +};
> +
> +/*
> + * Queue operations
> + */
> +
> +static u32 camif_get_sizeimage(struct camif_priv *priv)
> +{
> + struct v4l2_mbus_framefmt *outfmt;
> + const struct imx_media_pixfmt *outcc;
> +
> + outfmt = &priv->format_mbus[priv->output_pad];
> + outcc = priv->cc[priv->output_pad];
> + return (outfmt->width * outfmt->height * outcc->bpp) >> 3;
> +}
> +
> +static int camif_queue_setup(struct vb2_queue *vq,
> + unsigned int *nbuffers, unsigned int *nplanes,
> + unsigned int sizes[], struct device *alloc_devs[])
> +{
> + struct camif_priv *priv = vb2_get_drv_priv(vq);
> + unsigned int count = *nbuffers;
> + u32 sizeimage;
> +
> + if (!priv->src_sd)
> + return -EPIPE;
> +
> + if (vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> + return -EINVAL;
> +
> + sizeimage = camif_get_sizeimage(priv);
> +
> + count = min_t(unsigned int, count, IMX_MEDIA_MAX_RING_BUFS);
> + count = max_t(unsigned int, count, IMX_MEDIA_MIN_RING_BUFS);
> +
> + while (sizeimage * count > VID_MEM_LIMIT)
> + count--;
> +
> + if (count < IMX_MEDIA_MIN_RING_BUFS)
> + return -EINVAL;
> +
> + *nplanes = 1;
> + *nbuffers = count;
> + sizes[0] = sizeimage;
> +
> + return 0;
> +}
> +
> +static int camif_buf_init(struct vb2_buffer *vb)
> +{
> + struct vb2_queue *vq = vb->vb2_queue;
> + struct camif_priv *priv = vb2_get_drv_priv(vq);
> + struct imx_media_buffer *buf = to_imx_media_vb(vb);
> +
> + if (!priv->src_sd)
> + return -EPIPE;
> +
> + INIT_LIST_HEAD(&buf->list);
> +
> + return 0;
> +}
> +
> +static int camif_buf_prepare(struct vb2_buffer *vb)
> +{
> + struct vb2_queue *vq = vb->vb2_queue;
> + struct camif_priv *priv = vb2_get_drv_priv(vq);
> + u32 sizeimage = camif_get_sizeimage(priv);
> + int ret;
> +
> + if (!priv->src_sd)
> + return -EPIPE;
> +
> + if (vb2_plane_size(vb, 0) < sizeimage) {
> + v4l2_err(&priv->sd,
> + "data will not fit into plane (%lu < %lu)\n",
> + vb2_plane_size(vb, 0), (long)sizeimage);
> + return -EINVAL;
> + }
> +
> + vb2_set_plane_payload(vb, 0, sizeimage);
> +
> + if (!priv->in_ring) {
> + priv->in_ring = imx_media_alloc_dma_buf_ring(
> + priv->md, &priv->src_sd->entity, &priv->sd.entity,
> + sizeimage, vq->num_buffers, false);
> + if (IS_ERR(priv->in_ring)) {
> + v4l2_err(&priv->sd, "failed to alloc dma-buf ring\n");
> + ret = PTR_ERR(priv->in_ring);
> + priv->in_ring = NULL;
> + return ret;
> + }
> + }
> +
> + ret = imx_media_dma_buf_queue_from_vb(priv->in_ring, vb);
> + if (ret)
> + goto free_ring;
> +
> + return 0;
> +
> +free_ring:
> + imx_media_free_dma_buf_ring(priv->in_ring);
> + priv->in_ring = NULL;
> + return ret;
> +}
> +
> +static void camif_buf_queue(struct vb2_buffer *vb)
> +{
> + struct camif_priv *priv = vb2_get_drv_priv(vb->vb2_queue);
> + struct imx_media_buffer *buf = to_imx_media_vb(vb);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->q_lock, flags);
> +
> + list_add_tail(&buf->list, &priv->ready_q);
> +
> + spin_unlock_irqrestore(&priv->q_lock, flags);
> +}
> +
> +static int camif_start_streaming(struct vb2_queue *vq, unsigned int count)
> +{
> + struct camif_priv *priv = vb2_get_drv_priv(vq);
> + u32 sizeimage = camif_get_sizeimage(priv);
> + struct imx_media_buffer *buf, *tmp;
> + unsigned long flags;
> + int ret;
> +
> + if (vb2_is_streaming(vq))
> + return 0;
> +
> + if (!priv->src_sd)
> + return -EPIPE;
> +
> + if (!priv->in_ring) {
> + priv->in_ring = imx_media_alloc_dma_buf_ring(
> + priv->md, &priv->src_sd->entity, &priv->sd.entity,
> + sizeimage, vq->num_buffers, false);
> + if (IS_ERR(priv->in_ring)) {
> + v4l2_err(&priv->sd, "failed to alloc dma-buf ring\n");
> + ret = PTR_ERR(priv->in_ring);
> + priv->in_ring = NULL;
> + goto return_bufs;
> + }
> + }
> +
> + ret = imx_media_pipeline_set_stream(priv->md, &priv->sd.entity,
> + &priv->mp, true);
> + if (ret) {
> + v4l2_err(&priv->sd, "pipeline_set_stream failed with %d\n",
> + ret);
> + goto free_ring;
> + }
> +
> + priv->stop = false;
> +
> + return 0;
> +
> +free_ring:
> + imx_media_free_dma_buf_ring(priv->in_ring);
> + priv->in_ring = NULL;
> +return_bufs:
> + spin_lock_irqsave(&priv->q_lock, flags);
> + list_for_each_entry_safe(buf, tmp, &priv->ready_q, list) {
> + list_del(&buf->list);
> + vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
> + }
> + spin_unlock_irqrestore(&priv->q_lock, flags);
> + return ret;
> +}
> +
> +static void camif_stop_streaming(struct vb2_queue *vq)
> +{
> + struct camif_priv *priv = vb2_get_drv_priv(vq);
> + struct imx_media_buffer *frame;
> + unsigned long flags;
> + int ret;
> +
> + if (!vb2_is_streaming(vq))
> + return;
> +
> + spin_lock_irqsave(&priv->q_lock, flags);
> + priv->stop = true;
> + spin_unlock_irqrestore(&priv->q_lock, flags);
> +
> + ret = imx_media_pipeline_set_stream(priv->md, &priv->sd.entity,
> + &priv->mp, false);
> + if (ret)
> + v4l2_warn(&priv->sd, "pipeline_set_stream failed with %d\n",
> + ret);
> +
> + if (priv->in_ring) {
> + v4l2_warn(&priv->sd, "%s: in_ring was not freed\n",
> + __func__);
> + imx_media_free_dma_buf_ring(priv->in_ring);
> + priv->in_ring = NULL;
> + }
> +
> + /* release all active buffers */
> + spin_lock_irqsave(&priv->q_lock, flags);
> + while (!list_empty(&priv->ready_q)) {
> + frame = list_entry(priv->ready_q.next,
> + struct imx_media_buffer, list);
> + list_del(&frame->list);
> + vb2_buffer_done(&frame->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
> + }
> + spin_unlock_irqrestore(&priv->q_lock, flags);
> +}
> +
> +static struct vb2_ops camif_qops = {
> + .queue_setup = camif_queue_setup,
> + .buf_init = camif_buf_init,
> + .buf_prepare = camif_buf_prepare,
> + .buf_queue = camif_buf_queue,
> + .wait_prepare = vb2_ops_wait_prepare,
> + .wait_finish = vb2_ops_wait_finish,
> + .start_streaming = camif_start_streaming,
> + .stop_streaming = camif_stop_streaming,
> +};
> +
> +/*
> + * File operations
> + */
> +static int camif_open(struct file *file)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + int ret;
> +
> + if (mutex_lock_interruptible(&priv->mutex))
> + return -ERESTARTSYS;
> +
> + ret = v4l2_fh_open(file);
> + if (ret)
> + v4l2_err(&priv->sd, "v4l2_fh_open failed\n");
> +
> + mutex_unlock(&priv->mutex);
> + return ret;
> +}
> +
> +static int camif_release(struct file *file)
> +{
> + struct camif_priv *priv = video_drvdata(file);
> + struct vb2_queue *vq = &priv->buffer_queue;
> + int ret = 0;
> +
> + mutex_lock(&priv->mutex);
> +
> + if (file->private_data == vq->owner) {
> + vb2_queue_release(vq);
> + vq->owner = NULL;
> + }
> +
> + v4l2_fh_release(file);
> + mutex_unlock(&priv->mutex);
> + return ret;
> +}
> +
> +static const struct v4l2_file_operations camif_fops = {
> + .owner = THIS_MODULE,
> + .open = camif_open,
> + .release = camif_release,
> + .poll = vb2_fop_poll,
> + .unlocked_ioctl = video_ioctl2,
> + .mmap = vb2_fop_mmap,
> +};
> +
> +static struct video_device camif_videodev = {
> + .fops = &camif_fops,
> + .ioctl_ops = &camif_ioctl_ops,
> + .minor = -1,
> + .release = video_device_release,
> + .vfl_dir = VFL_DIR_RX,
> + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
> +};
> +
> +/*
> + * Subdev and media entity operations
> + */
> +
> +static void camif_new_dma_buf(struct camif_priv *priv)
> +{
> + struct imx_media_dma_buf *dmabuf;
> + struct imx_media_buffer *buf;
> + enum vb2_buffer_state state;
> + struct vb2_buffer *vb;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->q_lock, flags);
> +
> + if (priv->stop || list_empty(&priv->ready_q))
> + goto unlock;
> +
> + dmabuf = imx_media_dma_buf_dequeue(priv->in_ring);
> + if (!dmabuf)
> + goto unlock;
> +
> + vb = dmabuf->vb;
> + buf = to_imx_media_vb(vb);
> + if (list_empty(&buf->list)) {
> + dev_dbg(priv->dev, "%s: buf%d not queued\n", __func__,
> + vb->index);
> + goto unlock;
> + }
> +
> + dev_dbg(priv->dev, "%s: new buf%d\n", __func__, vb->index);
> + vb->timestamp = ktime_get_ns();
> + list_del_init(&buf->list);
> + state = dmabuf->status == IMX_MEDIA_BUF_STATUS_DONE ?
> + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
> + vb2_buffer_done(vb, state);
> +unlock:
> + spin_unlock_irqrestore(&priv->q_lock, flags);
> +}
> +
> +static long camif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
> +{
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> + struct imx_media_dma_buf_ring **ring;
> +
> + switch (cmd) {
> + case IMX_MEDIA_REQ_DMA_BUF_SINK_RING:
> + if (!priv->in_ring)
> + return -EINVAL;
> + ring = (struct imx_media_dma_buf_ring **)arg;
> + *ring = priv->in_ring;
> + break;
> + case IMX_MEDIA_NEW_DMA_BUF:
> + camif_new_dma_buf(priv);
> + break;
> + case IMX_MEDIA_REL_DMA_BUF_SINK_RING:
> + /* src indicates sink buffer ring can be freed */
> + if (!priv->in_ring)
> + return 0;
> + v4l2_info(sd, "%s: freeing sink ring\n", __func__);
> + imx_media_free_dma_buf_ring(priv->in_ring);
> + priv->in_ring = NULL;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int camif_link_setup(struct media_entity *entity,
> + const struct media_pad *local,
> + const struct media_pad *remote, u32 flags)
> +{
> + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> + struct video_device *vfd = &priv->vfd;
> + struct v4l2_subdev *remote_sd;
> + int ret = 0;
> +
> + dev_dbg(priv->dev, "link setup %s -> %s", remote->entity->name,
> + local->entity->name);
> +
> + if (is_media_entity_v4l2_video_device(remote->entity))
> + return 0;
> +
> + WARN_ON(local->flags & MEDIA_PAD_FL_SOURCE);
> +
> + remote_sd = media_entity_to_v4l2_subdev(remote->entity);
> +
> + /* reset controls to refresh with inherited from subdevs */
> + v4l2_ctrl_handler_free(vfd->ctrl_handler);
> + v4l2_ctrl_handler_init(vfd->ctrl_handler, 0);
> +
> + if (flags & MEDIA_LNK_FL_ENABLED) {
> + if (priv->src_sd)
> + return -EBUSY;
> + priv->src_sd = remote_sd;
> + ret = imx_media_inherit_controls(priv->md, vfd,
> + &priv->src_sd->entity);
> + } else {
> + priv->src_sd = NULL;
> + }
> +
> + return ret;
> +}
> +
> +static int camif_enum_mbus_code(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_mbus_code_enum *code)
> +{
> + if (code->pad >= CAMIF_NUM_PADS)
> + return -EINVAL;
> +
> + return imx_media_enum_format(&code->code, code->index, true, true);
> +}
> +
> +static int camif_get_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *sdformat)
> +{
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> +
> + if (sdformat->pad >= CAMIF_NUM_PADS)
> + return -EINVAL;
> +
> + sdformat->format = priv->format_mbus[sdformat->pad];
> +
> + return 0;
> +}
> +
> +static int camif_set_fmt(struct v4l2_subdev *sd,
> + struct v4l2_subdev_pad_config *cfg,
> + struct v4l2_subdev_format *sdformat)
> +{
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> + const struct imx_media_pixfmt *cc;
> + u32 code;
> +
> + if (sdformat->pad >= CAMIF_NUM_PADS)
> + return -EINVAL;
> +
> + if (vb2_is_busy(&priv->buffer_queue)) {
> + v4l2_err(&priv->sd, "%s queue busy\n", __func__);
> + return -EBUSY;
> + }
> +
> + cc = imx_media_find_format(0, sdformat->format.code, true, true);
> + if (!cc) {
> + imx_media_enum_format(&code, 0, true, true);
> + cc = imx_media_find_format(0, code, true, true);
> + sdformat->format.code = cc->codes[0];
> + }
> +
> + /* Output pad mirrors input pad, no limitations on input pads */
> + if (sdformat->pad == priv->output_pad)
> + sdformat->format = priv->format_mbus[priv->input_pad];
> +
> + if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
> + cfg->try_fmt = sdformat->format;
> + } else {
> + priv->format_mbus[sdformat->pad] = sdformat->format;
> + priv->cc[sdformat->pad] = cc;
> + }
> +
> + return 0;
> +}
> +
> +static int camif_init_pads(struct camif_priv *priv)
> +{
> + struct video_device *vfd = &priv->vfd;
> + struct imx_media_subdev *imxsd;
> + struct imx_media_pad *pad;
> + int i, ret;
> +
> + imxsd = imx_media_find_subdev_by_sd(priv->md, &priv->sd);
> + if (IS_ERR(imxsd))
> + return PTR_ERR(imxsd);
> +
> + if (imxsd->num_sink_pads != 1 || imxsd->num_src_pads != 1) {
> + v4l2_err(&priv->sd, "invalid num pads %d/%d\n",
> + imxsd->num_sink_pads, imxsd->num_src_pads);
> + return -EINVAL;
> + }
> +
> + priv->vd_pad.flags = MEDIA_PAD_FL_SINK;
> + ret = media_entity_pads_init(&vfd->entity, 1, &priv->vd_pad);
> + if (ret) {
> + v4l2_err(&priv->sd, "failed to init device node pad\n");
> + return ret;
> + }
> +
> + for (i = 0; i < CAMIF_NUM_PADS; i++) {
> + pad = &imxsd->pad[i];
> + priv->pad[i] = pad->pad;
> + if (priv->pad[i].flags & MEDIA_PAD_FL_SINK)
> + priv->input_pad = i;
> + else
> + priv->output_pad = i;
> +
> + /* set a default mbus format */
> + ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
> + 640, 480, 0, V4L2_FIELD_NONE,
> + &priv->cc[i]);
> + if (ret)
> + return ret;
> + }
> +
> + return media_entity_pads_init(&priv->sd.entity, CAMIF_NUM_PADS,
> + priv->pad);
> +}
> +
> +static int camif_registered(struct v4l2_subdev *sd)
> +{
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> + struct vb2_queue *vq = &priv->buffer_queue;
> + struct video_device *vfd = &priv->vfd;
> + struct v4l2_mbus_framefmt *infmt, *outfmt;
> + int ret;
> +
> + /* get media device */
> + priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
> +
> + vfd->v4l2_dev = sd->v4l2_dev;
> +
> + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> + if (ret) {
> + v4l2_err(sd, "Failed to register video device\n");
> + return ret;
> + }
> +
> + vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> + vq->io_modes = VB2_MMAP | VB2_DMABUF;
> + vq->drv_priv = priv;
> + vq->buf_struct_size = sizeof(struct imx_media_buffer);
> + vq->ops = &camif_qops;
> + vq->mem_ops = &vb2_dma_contig_memops;
> + vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
> + vq->lock = &priv->mutex;
> + vq->min_buffers_needed = 2;
> + vq->dev = priv->dev;
> +
> + ret = vb2_queue_init(vq);
> + if (ret) {
> + v4l2_err(sd, "vb2_queue_init failed\n");
> + goto unreg;
> + }
> +
> + INIT_LIST_HEAD(&priv->ready_q);
> +
> + ret = camif_init_pads(priv);
> + if (ret) {
> + v4l2_err(sd, "camif_init_pads failed\n");
> + goto unreg;
> + }
> +
> + /* create the link to our device node */
> + ret = media_create_pad_link(&sd->entity, priv->output_pad,
> + &vfd->entity, 0,
> + MEDIA_LNK_FL_IMMUTABLE |
> + MEDIA_LNK_FL_ENABLED);
> + if (ret) {
> + v4l2_err(sd, "failed to create link to device node\n");
> + goto unreg;
> + }
> +
> + /* setup default pad formats */
> + infmt = &priv->format_mbus[priv->input_pad];
> + outfmt = &priv->format_mbus[priv->output_pad];
> + ret = imx_media_init_mbus_fmt(outfmt, 640, 480, 0, V4L2_FIELD_NONE,
> + &priv->cc[priv->output_pad]);
> + if (ret)
> + goto unreg;
> +
> + *infmt = *outfmt;
> + priv->cc[priv->input_pad] = priv->cc[priv->output_pad];
> +
> + priv->current_std = V4L2_STD_UNKNOWN;
> +
> + v4l2_info(sd, "Registered %s as /dev/%s\n", vfd->name,
> + video_device_node_name(vfd));
> +
> + vfd->ctrl_handler = &priv->ctrl_hdlr;
> +
> + return 0;
> +unreg:
> + video_unregister_device(vfd);
> + return ret;
> +}
> +
> +static void camif_unregistered(struct v4l2_subdev *sd)
> +{
> + struct camif_priv *priv = v4l2_get_subdevdata(sd);
> + struct video_device *vfd = &priv->vfd;
> +
> + mutex_lock(&priv->mutex);
> +
> + if (video_is_registered(vfd)) {
> + video_unregister_device(vfd);
> + media_entity_cleanup(&vfd->entity);
> + }
> +
> + mutex_unlock(&priv->mutex);
> +}
> +
> +static const struct v4l2_subdev_internal_ops camif_internal_ops = {
> + .registered = camif_registered,
> + .unregistered = camif_unregistered,
> +};
> +
> +static struct v4l2_subdev_core_ops camif_core_ops = {
> + .ioctl = camif_ioctl,
> +};
> +
> +static struct media_entity_operations camif_entity_ops = {
> + .link_setup = camif_link_setup,
> + .link_validate = v4l2_subdev_link_validate,
> +};
> +
> +static struct v4l2_subdev_pad_ops camif_pad_ops = {
> + .enum_mbus_code = camif_enum_mbus_code,
> + .get_fmt = camif_get_fmt,
> + .set_fmt = camif_set_fmt,
> +};
> +
> +static struct v4l2_subdev_ops camif_subdev_ops = {
> + .pad = &camif_pad_ops,
> + .core = &camif_core_ops,
> +};
> +
> +static int camif_probe(struct platform_device *pdev)
> +{
> + struct imx_media_internal_sd_platformdata *pdata;
> + struct camif_priv *priv;
> + struct video_device *vfd;
> + int ret;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, priv);
> + priv->dev = &pdev->dev;
> +
> + pdata = priv->dev->platform_data;
> +
> + mutex_init(&priv->mutex);
> + spin_lock_init(&priv->q_lock);
> +
> + v4l2_subdev_init(&priv->sd, &camif_subdev_ops);
> + v4l2_set_subdevdata(&priv->sd, priv);
> + priv->sd.internal_ops = &camif_internal_ops;
> + priv->sd.entity.ops = &camif_entity_ops;
> + priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
> + priv->sd.dev = &pdev->dev;
> + priv->sd.owner = THIS_MODULE;
> + /* get our group id and camif id */
> + priv->sd.grp_id = pdata->grp_id;
> + priv->id = (pdata->grp_id >> IMX_MEDIA_GRP_ID_CAMIF_BIT) - 1;
> + strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
> + snprintf(camif_videodev.name, sizeof(camif_videodev.name),
> + "%s devnode", pdata->sd_name);
> +
> + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
> +
> + vfd = &priv->vfd;
> + *vfd = camif_videodev;
> + vfd->lock = &priv->mutex;
> + vfd->queue = &priv->buffer_queue;
> +
> + video_set_drvdata(vfd, priv);
> +
> + v4l2_ctrl_handler_init(&priv->ctrl_hdlr, 0);
> +
> + ret = v4l2_async_register_subdev(&priv->sd);
> + if (ret)
> + v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
> +
> + return ret;
> +}
> +
> +static int camif_remove(struct platform_device *pdev)
> +{
> + struct camif_priv *priv =
> + (struct camif_priv *)platform_get_drvdata(pdev);
> +
> + v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
> + v4l2_async_unregister_subdev(&priv->sd);
> + media_entity_cleanup(&priv->sd.entity);
> + v4l2_device_unregister_subdev(&priv->sd);
> +
> + return 0;
> +}
> +
> +static const struct platform_device_id camif_ids[] = {
> + { .name = "imx-media-camif" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(platform, camif_ids);
> +
> +static struct platform_driver imx_camif_driver = {
> + .probe = camif_probe,
> + .remove = camif_remove,
> + .driver = {
> + .name = "imx-media-camif",
> + },
> +};
> +
> +module_platform_driver(imx_camif_driver);
> +
> +MODULE_DESCRIPTION("i.MX camera interface subdev driver");
> +MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
> +MODULE_LICENSE("GPL");
>
Regards,
Hans
next prev parent reply other threads:[~2017-01-20 14:39 UTC|newest]
Thread overview: 190+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-07 2:11 [PATCH v3 00/24] i.MX Media Driver Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 01/24] [media] dt-bindings: Add bindings for i.MX media driver Steve Longerbeam
2017-01-13 11:55 ` Philipp Zabel
2017-01-13 19:03 ` Steve Longerbeam
2017-01-16 12:09 ` Philipp Zabel
2017-01-16 17:13 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 02/24] ARM: dts: imx6qdl: Add compatible, clocks, irqs to MIPI CSI-2 node Steve Longerbeam
2017-01-13 11:57 ` Philipp Zabel
2017-01-13 22:40 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 03/24] ARM: dts: imx6qdl: Add mipi_ipu1/2 multiplexers, mipi_csi, and their connections Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 04/24] ARM: dts: imx6qdl: add media device Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 05/24] ARM: dts: imx6qdl-sabrelite: remove erratum ERR006687 workaround Steve Longerbeam
2017-01-13 11:59 ` Philipp Zabel
2017-01-07 2:11 ` [PATCH v3 06/24] ARM: dts: imx6-sabrelite: add OV5642 and OV5640 camera sensors Steve Longerbeam
2017-01-13 12:03 ` Philipp Zabel
2017-01-13 23:04 ` Steve Longerbeam
2017-01-16 12:55 ` Philipp Zabel
2017-01-16 17:15 ` Steve Longerbeam
2017-02-05 15:17 ` Laurent Pinchart
2017-01-30 22:28 ` Russell King - ARM Linux
2017-01-30 22:51 ` Russell King - ARM Linux
2017-02-05 15:24 ` Laurent Pinchart
2017-02-05 15:37 ` Russell King - ARM Linux
2017-01-07 2:11 ` [PATCH v3 07/24] ARM: dts: imx6-sabresd: " Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 08/24] ARM: dts: imx6-sabreauto: create i2cmux for i2c3 Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 09/24] ARM: dts: imx6-sabreauto: add reset-gpios property for max7310_b Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 10/24] ARM: dts: imx6-sabreauto: add pinctrl for gpt input capture Steve Longerbeam
2017-01-12 19:37 ` Tim Harvey
2017-01-12 23:40 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 11/24] ARM: dts: imx6-sabreauto: add the ADV7180 video decoder Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 12/24] add mux and video interface bridge entity functions Steve Longerbeam
2017-01-20 13:56 ` Hans Verkuil
2017-02-05 15:36 ` Laurent Pinchart
2017-02-06 10:27 ` Philipp Zabel
2017-01-07 2:11 ` [PATCH v3 13/24] platform: add video-multiplexer subdevice driver Steve Longerbeam
2017-01-10 5:35 ` Rob Herring
2017-01-20 14:03 ` Hans Verkuil
2017-01-24 12:02 ` Philipp Zabel
2017-01-25 2:07 ` Steve Longerbeam
2017-02-05 15:48 ` Laurent Pinchart
2017-02-06 9:50 ` Hans Verkuil
2017-02-06 22:33 ` Laurent Pinchart
2017-02-06 23:10 ` Steve Longerbeam
2017-02-07 10:26 ` Laurent Pinchart
2017-02-07 10:41 ` Philipp Zabel
2017-02-07 14:11 ` Laurent Pinchart
2017-02-07 13:36 ` Benoit Parrot
2017-02-07 20:50 ` Sakari Ailus
2017-02-07 23:04 ` Laurent Pinchart
2017-01-24 12:44 ` Javier Martinez Canillas
2017-01-26 1:22 ` Steve Longerbeam
2017-02-07 20:46 ` Sakari Ailus
2017-02-08 9:47 ` Philipp Zabel
2017-02-08 10:05 ` Laurent Pinchart
2017-01-07 2:11 ` [PATCH v3 14/24] UAPI: Add media UAPI Kbuild file Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 15/24] media: Add userspace header file for i.MX Steve Longerbeam
2017-01-13 12:05 ` Philipp Zabel
2017-01-13 23:13 ` Steve Longerbeam
2017-02-05 15:50 ` Laurent Pinchart
2017-01-07 2:11 ` [PATCH v3 16/24] media: Add i.MX media core driver Steve Longerbeam
2017-01-13 15:20 ` Philipp Zabel
2017-01-14 22:46 ` Steve Longerbeam
2017-01-16 13:47 ` Philipp Zabel
2017-01-23 2:31 ` Steve Longerbeam
2017-01-23 11:13 ` Philipp Zabel
2017-01-24 1:38 ` Steve Longerbeam
2017-01-24 1:45 ` Steve Longerbeam
2017-01-24 11:37 ` Philipp Zabel
2017-01-30 15:28 ` Russell King - ARM Linux
[not found] ` <2b1d2418-1ad4-6373-cb07-c3aeab48187f@gmail.com>
2017-01-19 1:44 ` Steve Longerbeam
2017-01-24 11:39 ` Philipp Zabel
2017-01-30 22:29 ` Russell King - ARM Linux
2017-02-02 22:44 ` Russell King - ARM Linux
2017-02-02 22:50 ` Russell King - ARM Linux
2017-02-07 1:54 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 17/24] media: imx: Add CSI subdev driver Steve Longerbeam
2017-01-16 15:03 ` Philipp Zabel
2017-01-16 21:15 ` Steve Longerbeam
2017-01-30 22:29 ` Russell King - ARM Linux
2017-01-31 10:30 ` Russell King - ARM Linux
2017-01-31 11:20 ` Russell King - ARM Linux
2017-02-01 0:31 ` Steve Longerbeam
2017-02-01 0:58 ` Russell King - ARM Linux
2017-01-31 15:51 ` Philipp Zabel
2017-01-31 16:48 ` Philipp Zabel
2017-02-01 1:40 ` Steve Longerbeam
2017-02-07 16:18 ` [PATCH] media: imx: csi: fix crop rectangle reset in sink set_fmt Philipp Zabel
2017-01-07 2:11 ` [PATCH v3 18/24] media: imx: Add SMFC subdev driver Steve Longerbeam
2017-02-01 18:39 ` Russell King - ARM Linux
2017-02-01 18:52 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 19/24] media: imx: Add IC subdev drivers Steve Longerbeam
2017-01-20 14:29 ` Hans Verkuil
2017-01-25 2:39 ` Steve Longerbeam
2017-01-30 22:29 ` Russell King - ARM Linux
2017-01-07 2:11 ` [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver Steve Longerbeam
2017-01-20 14:38 ` Hans Verkuil [this message]
2017-01-24 2:15 ` Steve Longerbeam
2017-01-31 13:42 ` Russell King - ARM Linux
2017-01-31 18:21 ` Steve Longerbeam
2017-01-31 20:33 ` Russell King - ARM Linux
2017-01-31 21:55 ` Ian Arkver
2017-01-31 22:04 ` Russell King - ARM Linux
2017-01-31 22:33 ` Ian Arkver
2017-01-31 22:36 ` Steve Longerbeam
2017-01-31 23:30 ` Russell King - ARM Linux
2017-01-31 23:41 ` Steve Longerbeam
2017-02-02 22:35 ` Russell King - ARM Linux
2017-02-07 1:52 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 21/24] media: imx: Add MIPI CSI-2 Receiver " Steve Longerbeam
2017-01-30 22:30 ` Russell King - ARM Linux
2017-01-31 0:01 ` Russell King - ARM Linux
2017-01-31 9:49 ` Philipp Zabel
2017-02-01 1:02 ` Steve Longerbeam
2017-02-01 1:13 ` Russell King - ARM Linux
2017-01-31 0:31 ` Russell King - ARM Linux
2017-01-31 2:11 ` Steve Longerbeam
2017-02-01 23:44 ` Russell King - ARM Linux
2017-02-02 0:04 ` Steve Longerbeam
2017-02-02 11:50 ` Philipp Zabel
2017-02-08 23:23 ` Steve Longerbeam
2017-02-08 23:42 ` Russell King - ARM Linux
2017-02-09 23:49 ` Steve Longerbeam
2017-02-09 23:51 ` Steve Longerbeam
2017-02-13 9:20 ` Philipp Zabel
2017-02-13 23:20 ` Steve Longerbeam
2017-02-14 16:59 ` Philipp Zabel
2017-02-09 9:43 ` Philipp Zabel
2017-01-07 2:11 ` [PATCH v3 22/24] media: imx: Add MIPI CSI-2 OV5640 sensor " Steve Longerbeam
2017-01-20 14:48 ` Hans Verkuil
2017-01-25 19:10 ` Steve Longerbeam
2017-01-30 23:29 ` Russell King - ARM Linux
2017-01-31 3:31 ` Steve Longerbeam
2017-02-02 10:36 ` Laurent Pinchart
2017-02-12 22:53 ` Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 23/24] media: imx: Add Parallel OV5642 " Steve Longerbeam
2017-01-07 2:11 ` [PATCH v3 24/24] ARM: imx_v6_v7_defconfig: Enable staging video4linux drivers Steve Longerbeam
2017-01-11 23:14 ` [PATCH v3 00/24] i.MX Media Driver Tim Harvey
2017-01-12 3:22 ` Steve Longerbeam
2017-01-12 21:13 ` Tim Harvey
2017-01-12 22:32 ` Steve Longerbeam
2017-01-13 21:04 ` Tim Harvey
2017-01-20 13:52 ` Hans Verkuil
2017-01-20 16:31 ` Philipp Zabel
2017-01-20 18:40 ` Steve Longerbeam
2017-01-20 20:39 ` Hans Verkuil
2017-01-23 11:00 ` Philipp Zabel
2017-01-23 11:08 ` Hans Verkuil
2017-01-24 11:28 ` Philipp Zabel
2017-01-23 23:08 ` Steve Longerbeam
2017-01-24 11:27 ` Philipp Zabel
2017-01-28 19:27 ` Steve Longerbeam
2017-01-30 13:06 ` Russell King - ARM Linux
2017-01-31 10:09 ` Philipp Zabel
2017-01-31 13:14 ` Russell King - ARM Linux
2017-01-31 13:35 ` Philipp Zabel
2017-01-31 14:04 ` Russell King - ARM Linux
2017-01-31 0:45 ` Russell King - ARM Linux
2017-01-31 1:06 ` Russell King - ARM Linux
2017-01-31 2:06 ` Steve Longerbeam
2017-01-31 1:22 ` Steve Longerbeam
2017-01-31 9:49 ` Philipp Zabel
2017-01-31 10:21 ` Russell King - ARM Linux
2017-01-31 11:00 ` Russell King - ARM Linux
2017-01-31 23:43 ` Steve Longerbeam
2017-02-01 0:23 ` Russell King - ARM Linux
2017-02-01 1:54 ` Steve Longerbeam
2017-02-01 9:20 ` Russell King - ARM Linux
2017-01-31 13:54 ` Philipp Zabel
2017-01-31 14:25 ` Philipp Zabel
2017-01-31 15:03 ` Russell King - ARM Linux
2017-02-01 1:26 ` Steve Longerbeam
2017-02-01 9:30 ` Philipp Zabel
2017-02-01 10:11 ` Russell King - ARM Linux
2017-02-01 10:42 ` Philipp Zabel
2017-02-01 10:53 ` Russell King - ARM Linux
2017-02-02 0:19 ` Steve Longerbeam
2017-02-03 14:41 ` Laurent Pinchart
2017-02-03 17:56 ` Steve Longerbeam
2017-02-15 2:27 ` Steve Longerbeam
2017-02-15 9:33 ` Philipp Zabel
2017-02-02 17:22 ` Russell King - ARM Linux
2017-02-02 17:31 ` Steve Longerbeam
2017-02-02 17:56 ` Russell King - ARM Linux
2017-02-02 18:26 ` Steve Longerbeam
2017-02-02 18:58 ` Russell King - ARM Linux
2017-02-02 19:12 ` Steve Longerbeam
2017-02-02 22:29 ` Russell King - ARM Linux
2017-02-03 18:49 ` Steve Longerbeam
2017-02-03 14:21 ` vb2 queue_setup documentation clarification (was "Re: [PATCH v3 00/24] i.MX Media Driver") Laurent Pinchart
2017-02-03 14:31 ` Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b7456d40-040d-41b7-45bc-ef6709ab7933@xs4all.nl \
--to=hverkuil@xs4all.nl \
--cc=andrew-ct.chen@mediatek.com \
--cc=arnd@arndb.de \
--cc=bparrot@ti.com \
--cc=devel@driverdev.osuosl.org \
--cc=devicetree@vger.kernel.org \
--cc=fabio.estevam@nxp.com \
--cc=geert@linux-m68k.org \
--cc=gregkh@linuxfoundation.org \
--cc=horms+renesas@verge.net.au \
--cc=jean-christophe.trotin@st.com \
--cc=kernel@pengutronix.de \
--cc=laurent.pinchart+renesas@ideasonboard.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=mark.rutland@arm.com \
--cc=markus.heiser@darmarIT.de \
--cc=mchehab@kernel.org \
--cc=minghsiu.tsai@mediatek.com \
--cc=nick@shmanahar.org \
--cc=niklas.soderlund+renesas@ragnatech.se \
--cc=p.zabel@pengutronix.de \
--cc=robert.jarzmik@free.fr \
--cc=robh+dt@kernel.org \
--cc=shawnguo@kernel.org \
--cc=slongerbeam@gmail.com \
--cc=songjun.wu@microchip.com \
--cc=steve_longerbeam@mentor.com \
--cc=sudipm.mukherjee@gmail.com \
--cc=tiffany.lin@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).