From 333a6515344f5dc4ed0772b8fe252a2246f2e099 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 07:29:13 -0200 Subject: Revert "[media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY" Enable MEDIA_IOC_G_TOPOLOGY ioctl for Kernel 4.6. This reverts commit be0270ec89e6b9b49de7e533dd1f3a89ad34d205. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-ioc-g-topology.xml | 3 --- drivers/media/media-device.c | 7 +------ include/uapi/linux/media.h | 6 +----- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml index 63152ab9efba..e0d49fa329f0 100644 --- a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml +++ b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml @@ -48,9 +48,6 @@ Description - - NOTE: This new ioctl is programmed to be added on Kernel 4.6. Its definition/arguments may change until its final version. - The typical usage of this ioctl is to call it twice. On the first call, the structure defined at &media-v2-topology; should be zeroed. At return, if no errors happen, this ioctl will return the diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 7dae0ac0f3ae..4d1c13de494b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -234,7 +234,6 @@ static long media_device_setup_link(struct media_device *mdev, return ret; } -#if 0 /* Let's postpone it to Kernel 4.6 */ static long __media_device_get_topology(struct media_device *mdev, struct media_v2_topology *topo) { @@ -390,7 +389,6 @@ static long media_device_get_topology(struct media_device *mdev, return 0; } -#endif static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -424,14 +422,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, mutex_unlock(&dev->graph_mutex); break; -#if 0 /* Let's postpone it to Kernel 4.6 */ case MEDIA_IOC_G_TOPOLOGY: mutex_lock(&dev->graph_mutex); ret = media_device_get_topology(dev, (struct media_v2_topology __user *)arg); mutex_unlock(&dev->graph_mutex); break; -#endif + default: ret = -ENOIOCTLCMD; } @@ -480,9 +477,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd, case MEDIA_IOC_DEVICE_INFO: case MEDIA_IOC_ENUM_ENTITIES: case MEDIA_IOC_SETUP_LINK: -#if 0 /* Let's postpone it to Kernel 4.6 */ case MEDIA_IOC_G_TOPOLOGY: -#endif return media_device_ioctl(filp, cmd, arg); case MEDIA_IOC_ENUM_LINKS32: diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..5dbb208e5451 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -286,7 +286,7 @@ struct media_links_enum { * later, before the adding this API upstream. */ -#if 0 /* Let's postpone it to Kernel 4.6 */ + struct media_v2_entity { __u32 id; char name[64]; /* FIXME: move to a property? (RFC says so) */ @@ -351,7 +351,6 @@ static inline void __user *media_get_uptr(__u64 arg) { return (void __user *)(uintptr_t)arg; } -#endif /* ioctls */ @@ -359,9 +358,6 @@ static inline void __user *media_get_uptr(__u64 arg) #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) - -#if 0 /* Let's postpone it to Kernel 4.6 */ #define MEDIA_IOC_G_TOPOLOGY _IOWR('|', 0x04, struct media_v2_topology) -#endif #endif /* __LINUX_MEDIA_H */ -- cgit v1.2.3 From 8163ec29c4c2911291d6fb2e9d5b171e17ce4f43 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 16 Sep 2015 20:31:38 -0300 Subject: [media] v4l: omap3isp: Fix module autoloading Platform drivers needs to export the OF id table and this be built into the module or udev will not have the necessary information to autoload the driver module when the device is registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 0bcfa553c1aa..79a0b953bba3 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2599,6 +2599,7 @@ static const struct of_device_id omap3isp_of_table[] = { { .compatible = "ti,omap3-isp" }, { }, }; +MODULE_DEVICE_TABLE(of, omap3isp_of_table); static struct platform_driver omap3isp_driver = { .probe = isp_probe, -- cgit v1.2.3 From 35c5f63773f77a4bfcc3010f6bcc84bdb74c8954 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:48 -0300 Subject: [media] v4l: omap3isp: Move starting the sensor from streamon IOCTL handler to VB2 QOP Move the starting of the sensor from the VIDIOC_STREAMON handler to the videobuf2 queue op start_streaming. This avoids failing starting the stream after vb2_streamon() has already finished. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 49 ++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 994dfc0813f6..bc37467e2fe5 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,10 +434,40 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +static int isp_video_start_streaming(struct vb2_queue *queue, + unsigned int count) +{ + struct isp_video_fh *vfh = vb2_get_drv_priv(queue); + struct isp_video *video = vfh->video; + struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); + unsigned long flags; + int ret; + + /* In sensor-to-memory mode, the stream can be started synchronously + * to the stream on command. In memory-to-memory mode, it will be + * started when buffers are queued on both the input and output. + */ + if (pipe->input) + return 0; + + ret = omap3isp_pipeline_set_stream(pipe, + ISP_PIPELINE_STREAM_CONTINUOUS); + if (ret < 0) + return ret; + + spin_lock_irqsave(&video->irqlock, flags); + if (list_empty(&video->dmaqueue)) + video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; + spin_unlock_irqrestore(&video->irqlock, flags); + + return 0; +} + static const struct vb2_ops isp_video_queue_ops = { .queue_setup = isp_video_queue_setup, .buf_prepare = isp_video_buffer_prepare, .buf_queue = isp_video_buffer_queue, + .start_streaming = isp_video_start_streaming, }; /* @@ -1087,29 +1117,10 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_check_format; - /* In sensor-to-memory mode, the stream can be started synchronously - * to the stream on command. In memory-to-memory mode, it will be - * started when buffers are queued on both the input and output. - */ - if (pipe->input == NULL) { - ret = omap3isp_pipeline_set_stream(pipe, - ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) - goto err_set_stream; - spin_lock_irqsave(&video->irqlock, flags); - if (list_empty(&video->dmaqueue)) - video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; - spin_unlock_irqrestore(&video->irqlock, flags); - } - mutex_unlock(&video->stream_lock); return 0; -err_set_stream: - mutex_lock(&video->queue_lock); - vb2_streamoff(&vfh->queue, type); - mutex_unlock(&video->queue_lock); err_check_format: media_entity_pipeline_stop(&video->video.entity); err_pipeline_start: -- cgit v1.2.3 From 87e062d4a93f1d78bd765256c826c338f7a0e921 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:49 -0300 Subject: [media] v4l: omap3isp: Return buffers back to videobuf2 if pipeline streamon fails When the video buffer queue was stopped before the stream source was started in omap3isp_streamon(), the buffers were not returned back to videobuf2. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index bc37467e2fe5..f82b470c01f9 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,6 +434,30 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +/* + * omap3isp_video_return_buffers - Return all queued buffers to videobuf2 + * @video: ISP video object + * @state: new state for the returned buffers + * + * Return all buffers queued on the video node to videobuf2 in the given state. + * The buffer state should be VB2_BUF_STATE_QUEUED if called due to an error + * when starting the stream, or VB2_BUF_STATE_ERROR otherwise. + * + * The function must be called with the video irqlock held. + */ +static void omap3isp_video_return_buffers(struct isp_video *video, + enum vb2_buffer_state state) +{ + while (!list_empty(&video->dmaqueue)) { + struct isp_buffer *buf; + + buf = list_first_entry(&video->dmaqueue, + struct isp_buffer, irqlist); + list_del(&buf->irqlist); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } +} + static int isp_video_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -452,8 +476,12 @@ static int isp_video_start_streaming(struct vb2_queue *queue, ret = omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) + if (ret < 0) { + spin_lock_irqsave(&video->irqlock, flags); + omap3isp_video_return_buffers(video, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&video->irqlock, flags); return ret; + } spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) @@ -571,26 +599,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) * omap3isp_video_cancel_stream - Cancel stream on a video node * @video: ISP video object * - * Cancelling a stream mark all buffers on the video node as erroneous and makes - * sure no new buffer can be queued. + * Cancelling a stream returns all buffers queued on the video node to videobuf2 + * in the erroneous state and makes sure no new buffer can be queued. */ void omap3isp_video_cancel_stream(struct isp_video *video) { unsigned long flags; spin_lock_irqsave(&video->irqlock, flags); - - while (!list_empty(&video->dmaqueue)) { - struct isp_buffer *buf; - - buf = list_first_entry(&video->dmaqueue, - struct isp_buffer, irqlist); - list_del(&buf->irqlist); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - + omap3isp_video_return_buffers(video, VB2_BUF_STATE_ERROR); video->error = true; - spin_unlock_irqrestore(&video->irqlock, flags); } -- cgit v1.2.3 From 18ba53f532f2813cb2b278b662c0bb9b7f0295b5 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Wed, 25 Feb 2015 12:58:14 -0300 Subject: [media] v4l: omap3isp: use vb2_buffer_state enum for vb2 buffer state use the vb2_buffer_state enum for assigning the state of the vb2 buffer, along side making isp_pipeline_state state variable local to the block. This fixes the following sparse warning as well: drivers/media/platform/omap3isp/ispvideo.c:497:35: warning: mixing different enum types drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum isp_pipeline_state versus drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum vb2_buffer_state Signed-off-by: Lad, Prabhakar Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index f82b470c01f9..2aff755ff77c 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -517,7 +517,7 @@ static const struct vb2_ops isp_video_queue_ops = { struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) { struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); - enum isp_pipeline_state state; + enum vb2_buffer_state vb_state; struct isp_buffer *buf; unsigned long flags; @@ -553,17 +553,19 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) /* Report pipeline errors to userspace on the capture device side. */ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) { - state = VB2_BUF_STATE_ERROR; + vb_state = VB2_BUF_STATE_ERROR; pipe->error = false; } else { - state = VB2_BUF_STATE_DONE; + vb_state = VB2_BUF_STATE_DONE; } - vb2_buffer_done(&buf->vb.vb2_buf, state); + vb2_buffer_done(&buf->vb.vb2_buf, vb_state); spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) { + enum isp_pipeline_state state; + spin_unlock_irqrestore(&video->irqlock, flags); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) -- cgit v1.2.3 From 514580f99af8eae246820fe324a78087972a7d63 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 24 Sep 2015 11:00:12 -0300 Subject: [media] v4l: omap3isp: Fix handling platform_get_irq result The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/assign_signed_to_unsigned.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2046107 Signed-off-by: Andrzej Hajda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 79a0b953bba3..97f6b1824577 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2528,12 +2528,13 @@ static int isp_probe(struct platform_device *pdev) } /* Interrupt */ - isp->irq_num = platform_get_irq(pdev, 0); - if (isp->irq_num <= 0) { + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { dev_err(isp->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iommu; } + isp->irq_num = ret; if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { -- cgit v1.2.3 From 61d5b9d46d2ea4b3ae9534ed6da608a78ce29ac5 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 10 Nov 2015 21:34:18 -0200 Subject: [media] v4l: omap3isp: preview: Mark output buffer done first The sequence number counter is incremented on each output buffer, and that incremented value is used as the sequence number of that buffer. The input buffer sequence numbering is based just on reading the same counter. If the input buffer is marked done first, its sequence number ends up being that of the output buffer - 1. This is how the resizer works as well. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isppreview.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 84a96670e2e7..ac30a0f83780 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -1480,13 +1480,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev) struct isp_buffer *buffer; int restart = 0; - if (prev->input == PREVIEW_INPUT_MEMORY) { - buffer = omap3isp_video_buffer_next(&prev->video_in); - if (buffer != NULL) - preview_set_inaddr(prev, buffer->dma); - pipe->state |= ISP_PIPELINE_IDLE_INPUT; - } - if (prev->output & PREVIEW_OUTPUT_MEMORY) { buffer = omap3isp_video_buffer_next(&prev->video_out); if (buffer != NULL) { @@ -1496,6 +1489,13 @@ static void preview_isr_buffer(struct isp_prev_device *prev) pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; } + if (prev->input == PREVIEW_INPUT_MEMORY) { + buffer = omap3isp_video_buffer_next(&prev->video_in); + if (buffer != NULL) + preview_set_inaddr(prev, buffer->dma); + pipe->state |= ISP_PIPELINE_IDLE_INPUT; + } + switch (prev->state) { case ISP_PIPELINE_STREAM_SINGLESHOT: if (isp_pipeline_ready(pipe)) -- cgit v1.2.3 From 74d1e7c09caed943efce745061f52231bc4c174e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Dec 2015 12:03:19 -0200 Subject: [media] v4l: omap3isp: Fix data lane shift configuration The data-shift DT property speficies the number of bits to be shifted, but the driver still interprets the value as a multiple of two bits as used by now removed platform data support. Fix it. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 +- drivers/media/platform/omap3isp/ispccdc.c | 2 +- drivers/media/platform/omap3isp/omap3isp.h | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 97f6b1824577..67efa9ea551e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -449,7 +449,7 @@ void omap3isp_configure_bridge(struct isp_device *isp, case CCDC_INPUT_PARALLEL: ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL; ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; - shift += parcfg->data_lane_shift * 2; + shift += parcfg->data_lane_shift; break; case CCDC_INPUT_CSI2A: diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index bb3974c98e37..882310eb45cc 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -2421,7 +2421,7 @@ static int ccdc_link_validate(struct v4l2_subdev *sd, &((struct isp_bus_cfg *) media_entity_to_v4l2_subdev(link->source->entity) ->host_priv)->bus.parallel; - parallel_shift = parcfg->data_lane_shift * 2; + parallel_shift = parcfg->data_lane_shift; } else { parallel_shift = 0; } diff --git a/drivers/media/platform/omap3isp/omap3isp.h b/drivers/media/platform/omap3isp/omap3isp.h index 190e259a6a2d..443e8f7673e2 100644 --- a/drivers/media/platform/omap3isp/omap3isp.h +++ b/drivers/media/platform/omap3isp/omap3isp.h @@ -33,9 +33,9 @@ enum isp_interface_type { * struct isp_parallel_cfg - Parallel interface configuration * @data_lane_shift: Data lane shifter * 0 - CAMEXT[13:0] -> CAM[13:0] - * 1 - CAMEXT[13:2] -> CAM[11:0] - * 2 - CAMEXT[13:4] -> CAM[9:0] - * 3 - CAMEXT[13:6] -> CAM[7:0] + * 2 - CAMEXT[13:2] -> CAM[11:0] + * 4 - CAMEXT[13:4] -> CAM[9:0] + * 6 - CAMEXT[13:6] -> CAM[7:0] * @clk_pol: Pixel clock polarity * 0 - Sample on rising edge, 1 - Sample on falling edge * @hs_pol: Horizontal synchronization polarity @@ -48,7 +48,7 @@ enum isp_interface_type { * 0 - Normal, 1 - One's complement */ struct isp_parallel_cfg { - unsigned int data_lane_shift:2; + unsigned int data_lane_shift:3; unsigned int clk_pol:1; unsigned int hs_pol:1; unsigned int vs_pol:1; -- cgit v1.2.3 From 3c97430d22d58b9c47a9a4573e8ae6976a475e3e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Jan 2016 12:49:57 -0200 Subject: [media] sh_mobile_ceu_camera: use soc_camera_from_vb2q Use soc_camera_from_vb2q() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 90c87f2b4ec0..b9f369c0fb94 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -213,8 +213,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - struct soc_camera_device *icd = container_of(vq, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -361,8 +360,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); @@ -413,8 +411,7 @@ error: static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -444,8 +441,7 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -460,7 +456,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) static void sh_mobile_ceu_stop_streaming(struct vb2_queue *q) { - struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(q); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct list_head *buf_head, *tmp; -- cgit v1.2.3 From 1dff3338539e96b2710c34693a6484585dfd7a78 Mon Sep 17 00:00:00 2001 From: Yoshihiko Mori Date: Sun, 13 Dec 2015 13:27:16 -0200 Subject: [media] soc_camera: rcar_vin: Add R-Car Gen3 support Add chip identification for R-Car Gen3. Signed-off-by: Yoshihiko Mori Signed-off-by: Yoshihiro Kaneko Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + drivers/media/platform/soc_camera/rcar_vin.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 9dafe6b06cd2..619193ccf7ff 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -6,6 +6,7 @@ family of devices. The current blocks are always slaves and suppot one input channel which can be either RGB, YUYV or BT656. - compatible: Must be one of the following + - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device - "renesas,vin-r8a7791" for the R8A7791 device diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index b7fd695b9ed5..dc75a80794fb 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -143,6 +143,7 @@ #define RCAR_VIN_BT656 (1 << 3) enum chip_id { + RCAR_GEN3, RCAR_GEN2, RCAR_H1, RCAR_M1, @@ -1818,6 +1819,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { #ifdef CONFIG_OF static const struct of_device_id rcar_vin_of_table[] = { + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_GEN3 }, { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, -- cgit v1.2.3 From 368a53df02d61bb849e100219c2a758510062f88 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 22 Nov 2015 07:12:56 -0200 Subject: [media] soc_camera: constify v4l2_subdev_sensor_ops structures The v4l2_subdev_sensor_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/mt9m001.c | 2 +- drivers/media/i2c/soc_camera/mt9t031.c | 2 +- drivers/media/i2c/soc_camera/mt9v022.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 2e14e52ba2e0..69becc358659 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -632,7 +632,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_mbus_config = mt9m001_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { .g_skip_top_lines = mt9m001_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 3b6eeed2e2b9..5c8e3ffe3b27 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -728,7 +728,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_mbus_config = mt9t031_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { .g_skip_top_lines = mt9t031_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index c2ba1fb3694d..2721e583bfa0 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -860,7 +860,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_mbus_config = mt9v022_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { .g_skip_top_lines = mt9v022_g_skip_top_lines, }; -- cgit v1.2.3 From 7d3ccfe697bceec9fdf7b901da4073cc55fa56de Mon Sep 17 00:00:00 2001 From: Joseph Marrero Date: Wed, 25 Nov 2015 20:38:43 -0200 Subject: [media] davinci_vpfe: make checkpatch happy This WARNING was found using the checkpatch tool: Block comments use * on the subsequent lines Signed-off-by: Joseph Marrero Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h index 7b7e7b26c1e8..3cc9be776f8b 100644 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h @@ -538,7 +538,7 @@ struct vpfe_isif_raw_config { }; /********************************************************************** - IPIPE API Structures +* IPIPE API Structures **********************************************************************/ /* IPIPE module configurations */ -- cgit v1.2.3 From 7871597a73b7b8daa7beeba3c36d68f9047d38c2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:41 -0200 Subject: [media] tvp5150: Restructure version detection Move the version detection code to a separate function and restructure it to prepare for TVP5151 support. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 79 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6c3769d44b75..f80928156ad7 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1105,13 +1105,53 @@ static const struct v4l2_subdev_ops tvp5150_ops = { I2C Client & Driver ****************************************************************************/ +static int tvp5150_detect_version(struct tvp5150 *core) +{ + struct v4l2_subdev *sd = &core->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned int i; + u16 dev_id; + u16 rom_ver; + u8 regs[4]; + int res; + + /* + * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, + * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER + */ + for (i = 0; i < 4; i++) { + res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); + if (res < 0) + return res; + regs[i] = res; + } + + dev_id = (regs[0] << 8) | regs[1]; + rom_ver = (regs[2] << 8) | regs[3]; + + v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n", + dev_id, regs[2], regs[3], c->addr << 1, c->adapter->name); + + if (dev_id == 0x5150 && rom_ver == 0x0321) { /* TVP51510A */ + v4l2_info(sd, "tvp5150a detected.\n"); + } else if (dev_id == 0x5150 && rom_ver == 0x0400) { /* TVP5150AM1 */ + v4l2_info(sd, "tvp5150am1 detected.\n"); + + /* ITU-T BT.656.4 timing */ + tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else { + v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; - int tvp5150_id[4]; - int i, res; + int res; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -1124,38 +1164,9 @@ static int tvp5150_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); - /* - * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, - * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER - */ - for (i = 0; i < 4; i++) { - res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); - if (res < 0) - return res; - tvp5150_id[i] = res; - } - - v4l_info(c, "chip found @ 0x%02x (%s)\n", - c->addr << 1, c->adapter->name); - - if (tvp5150_id[2] == 4 && tvp5150_id[3] == 0) { /* Is TVP5150AM1 */ - v4l2_info(sd, "tvp%02x%02xam1 detected.\n", - tvp5150_id[0], tvp5150_id[1]); - - /* ITU-T BT.656.4 timing */ - tvp5150_write(sd, TVP5150_REV_SELECT, 0); - } else { - /* Is TVP5150A */ - if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) { - v4l2_info(sd, "tvp%02x%02xa detected.\n", - tvp5150_id[0], tvp5150_id[1]); - } else { - v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n", - tvp5150_id[0], tvp5150_id[1]); - v4l2_info(sd, "*** Rom ver is %d.%d\n", - tvp5150_id[2], tvp5150_id[3]); - } - } + res = tvp5150_detect_version(core); + if (res < 0) + return res; core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = TVP5150_COMPOSITE1; -- cgit v1.2.3 From 05676b3e33fe2fd693f2c0ff3d058db6ca5e7ed6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:42 -0200 Subject: [media] tvp5150: Add tvp5151 support Expand the version detection code to identity the tvp5151. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index f80928156ad7..2816ceb4874a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1139,6 +1139,8 @@ static int tvp5150_detect_version(struct tvp5150 *core) /* ITU-T BT.656.4 timing */ tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else if (dev_id == 0x5151 && rom_ver == 0x0100) { /* TVP5151 */ + v4l2_info(sd, "tvp5151 detected.\n"); } else { v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); } -- cgit v1.2.3 From b1950b8db9896cca59f61b6b7c6d3a14dc782b80 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:44 -0200 Subject: [media] tvp5150: Add pixel rate control support This patch adds support for the V4L2_CID_PIXEL_RATE control. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 2816ceb4874a..555718ebbf0e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1174,7 +1174,7 @@ static int tvp5150_probe(struct i2c_client *c, core->input = TVP5150_COMPOSITE1; core->enable = 1; - v4l2_ctrl_handler_init(&core->hdl, 4); + v4l2_ctrl_handler_init(&core->hdl, 5); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, @@ -1183,6 +1183,9 @@ static int tvp5150_probe(struct i2c_client *c, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_PIXEL_RATE, 27000000, + 27000000, 1, 27000000); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; -- cgit v1.2.3 From 460b6c0831cb52ef349156cfa27e889606b4cb75 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:45 -0200 Subject: [media] tvp5150: Add s_stream subdev operation support This patch adds the .s_stream subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 555718ebbf0e..08383a273e51 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -952,6 +952,21 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) I2C Command ****************************************************************************/ +static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) +{ + /* Initializes TVP5150 to its default values */ + /* # set PCLK (27MHz) */ + tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + if (enable) + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + else + tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); + + return 0; +} + static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -1073,6 +1088,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_std = tvp5150_s_std, + .s_stream = tvp5150_s_stream, .s_routing = tvp5150_s_routing, .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, -- cgit v1.2.3 From dd3a46bbbe1d49a70a66d95a435a729f7ecd7e8f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:46 -0200 Subject: [media] tvp5150: Add g_mbus_config subdev operation support This patch adds the .g_mbus_config subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 08383a273e51..e6ce197d8dbc 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -948,6 +948,16 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } +static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->type = V4L2_MBUS_BT656; + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING + | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1093,6 +1103,7 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, .cropcap = tvp5150_cropcap, + .g_mbus_config = tvp5150_g_mbus_config, }; static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { -- cgit v1.2.3 From 367298c6b9dbcf393527ab23aa2b4314ca01bf28 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:47 -0200 Subject: [media] tvp5150: Add device tree binding document Add a Device Tree binding document for the TVP5150 video decoder. Signed-off-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/tvp5150.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/tvp5150.txt diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt new file mode 100644 index 000000000000..8c0fc1a26bf0 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt @@ -0,0 +1,45 @@ +* Texas Instruments TVP5150 and TVP5151 video decoders + +The TVP5150 and TVP5151 are video decoders that convert baseband NTSC and PAL +(and also SECAM in the TVP5151 case) video signals to either 8-bit 4:2:2 YUV +with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output formats. + +Required Properties: +- compatible: value must be "ti,tvp5150" +- reg: I2C slave address + +Optional Properties: +- pdn-gpios: phandle for the GPIO connected to the PDN pin, if any. +- reset-gpios: phandle for the GPIO connected to the RESETB pin, if any. + +The device node must contain one 'port' child node for its digital output +video port, in accordance with the video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Required Endpoint Properties for parallel synchronization: + +- hsync-active: active state of the HSYNC signal. Must be <1> (HIGH). +- vsync-active: active state of the VSYNC signal. Must be <1> (HIGH). +- field-even-active: field signal level during the even field data + transmission. Must be <0>. + +If none of hsync-active, vsync-active and field-even-active is specified, +the endpoint is assumed to use embedded BT.656 synchronization. + +Example: + +&i2c2 { + ... + tvp5150@5c { + compatible = "ti,tvp5150"; + reg = <0x5c>; + pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>; + + port { + tvp5150_1: endpoint { + remote-endpoint = <&ccdc_ep>; + }; + }; + }; +}; -- cgit v1.2.3 From 09aa2609fe69fd4878e5c0f1319410b46afaab8f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:49 -0200 Subject: [media] tvp5150: Initialize the chip on probe After power-up, the tvp5150 decoder is in a unknown state until the RESETB pin is driven LOW which reset all the registers and restarts the chip's internal state machine. The init sequence has some timing constraints and the RESETB signal can only be used if the PDN (Power-down) pin is first released. So, the initialization sequence is as follows: 1- PDN (active-low) is driven HIGH so the chip is power-up 2- A 20 ms delay is needed before sending a RESETB (active-low) signal. 3- The RESETB pulse duration is 500 ns. 4- A 200 us delay is needed for the I2C client to be active after reset. This patch used as a reference the logic in the IGEPv2 board file from the ISEE 2.6.37 vendor tree. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index e6ce197d8dbc..6f4b0f83973e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1175,6 +1176,36 @@ static int tvp5150_detect_version(struct tvp5150 *core) return 0; } +static int tvp5150_init(struct i2c_client *c) +{ + struct gpio_desc *pdn_gpio; + struct gpio_desc *reset_gpio; + + pdn_gpio = devm_gpiod_get_optional(&c->dev, "pdn", GPIOD_OUT_HIGH); + if (IS_ERR(pdn_gpio)) + return PTR_ERR(pdn_gpio); + + if (pdn_gpio) { + gpiod_set_value_cansleep(pdn_gpio, 0); + /* Delay time between power supplies active and reset */ + msleep(20); + } + + reset_gpio = devm_gpiod_get_optional(&c->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); + + if (reset_gpio) { + /* RESETB pulse duration */ + ndelay(500); + gpiod_set_value_cansleep(reset_gpio, 0); + /* Delay time between end of reset to I2C active */ + usleep_range(200, 250); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { @@ -1187,6 +1218,10 @@ static int tvp5150_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; + res = tvp5150_init(c); + if (res) + return res; + core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; -- cgit v1.2.3 From a2e5f1b3a4f12c8c35313a9052a8928b5b85a391 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:50 -0200 Subject: [media] tvp5150: Configure data interface via DT The video decoder supports either 8-bit 4:2:2 YUV with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output format but currently BT.656 it's always reported. Allow to configure the format to use via either platform data or a device tree definition. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 66 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6f4b0f83973e..57901d613a12 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -43,6 +44,8 @@ struct tvp5150 { u32 input; u32 output; int enable; + + enum v4l2_mbus_type mbus_type; }; static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd) @@ -773,6 +776,10 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) v4l2_ctrl_handler_setup(&decoder->hdl); tvp5150_set_std(sd, decoder->norm); + + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40); + return 0; }; @@ -952,7 +959,9 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_BT656; + struct tvp5150 *decoder = to_tvp5150(sd); + + cfg->type = decoder->mbus_type; cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; @@ -965,13 +974,20 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { + struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; + + /* Output format: 8-bit 4:2:2 YUV with discrete sync */ + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; + /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); @@ -1206,11 +1222,42 @@ static int tvp5150_init(struct i2c_client *c) return 0; } +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) +{ + struct v4l2_of_endpoint bus_cfg; + struct device_node *ep; + unsigned int flags; + int ret = 0; + + ep = of_graph_get_next_endpoint(np, NULL); + if (!ep) + return -EINVAL; + + ret = v4l2_of_parse_endpoint(ep, &bus_cfg); + if (ret) + goto err; + + flags = bus_cfg.bus.parallel.flags; + + if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && + !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_FIELD_EVEN_LOW)) + return -EINVAL; + + decoder->mbus_type = bus_cfg.bus_type; + +err: + of_node_put(ep); + return ret; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; + struct device_node *np = c->dev.of_node; int res; /* Check if the adapter supports the needed features */ @@ -1225,7 +1272,20 @@ static int tvp5150_probe(struct i2c_client *c, core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; + sd = &core->sd; + + if (IS_ENABLED(CONFIG_OF) && np) { + res = tvp5150_parse_dt(core, np); + if (res) { + v4l2_err(sd, "DT parsing error: %d\n", res); + return res; + } + } else { + /* Default to BT.656 embedded sync */ + core->mbus_type = V4L2_MBUS_BT656; + } + v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); res = tvp5150_detect_version(core); -- cgit v1.2.3 From 7ef930a7b33677b8227d0a19dcc32d891d3cde8d Mon Sep 17 00:00:00 2001 From: Eduard Gavin Date: Thu, 7 Jan 2016 10:46:48 -0200 Subject: [media] tvp5150: Add OF match table The Documentation/devicetree/bindings/media/i2c/tvp5150.txt DT binding doc lists "ti,tvp5150" as the device compatible string but the driver does not have an OF match table. Add the table to the driver so the I2C core can do an OF style match. Signed-off-by: Eduard Gavin Signed-off-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 57901d613a12..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1359,8 +1359,17 @@ static const struct i2c_device_id tvp5150_id[] = { }; MODULE_DEVICE_TABLE(i2c, tvp5150_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp5150_of_match[] = { + { .compatible = "ti,tvp5150", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp5150_of_match); +#endif + static struct i2c_driver tvp5150_driver = { .driver = { + .of_match_table = of_match_ptr(tvp5150_of_match), .name = "tvp5150", }, .probe = tvp5150_probe, -- cgit v1.2.3 From 99e44da7928d4abb3028258ac3cd23a48495cd61 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 24 Jan 2016 12:56:58 -0200 Subject: [media] media: change email address Soon my dibcom.fr/parrot.com-address won't respond anymore. Thus I'm replacing it. And, while being at it, let's adapt some other (old) email-addresses as well. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/README.dvb-usb | 2 +- drivers/media/common/b2c2/flexcop.c | 4 ++-- drivers/media/common/cypress_firmware.c | 2 +- drivers/media/common/cypress_firmware.h | 2 +- drivers/media/dvb-core/dvb-usb-ids.h | 2 +- drivers/media/dvb-frontends/bcm3510.c | 4 ++-- drivers/media/dvb-frontends/bcm3510.h | 2 +- drivers/media/dvb-frontends/bcm3510_priv.h | 2 +- drivers/media/dvb-frontends/dib0070.c | 2 +- drivers/media/dvb-frontends/dib0090.c | 4 ++-- drivers/media/dvb-frontends/dib3000.h | 6 +++--- drivers/media/dvb-frontends/dib3000mb.c | 8 ++++---- drivers/media/dvb-frontends/dib3000mb_priv.h | 2 +- drivers/media/dvb-frontends/dib3000mc.c | 4 ++-- drivers/media/dvb-frontends/dib3000mc.h | 2 +- drivers/media/dvb-frontends/dib7000m.c | 2 +- drivers/media/dvb-frontends/dib7000p.c | 4 ++-- drivers/media/dvb-frontends/dib8000.c | 2 +- drivers/media/dvb-frontends/dib9000.c | 4 ++-- drivers/media/dvb-frontends/dibx000_common.c | 2 +- drivers/media/pci/b2c2/flexcop-pci.c | 2 +- drivers/media/usb/b2c2/flexcop-usb.c | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_common.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 4 ++-- drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c | 2 +- drivers/media/usb/dvb-usb-v2/usb_urb.c | 2 +- drivers/media/usb/dvb-usb/a800.c | 4 ++-- drivers/media/usb/dvb-usb/cxusb.c | 4 ++-- drivers/media/usb/dvb-usb/dib0700_core.c | 2 +- drivers/media/usb/dvb-usb/dibusb-common.c | 2 +- drivers/media/usb/dvb-usb/dibusb-mb.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb-mc.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb.h | 2 +- drivers/media/usb/dvb-usb/digitv.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u-fe.c | 2 +- drivers/media/usb/dvb-usb/dtt200u.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-common.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-i2c.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-init.c | 4 ++-- drivers/media/usb/dvb-usb/dvb-usb-remote.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-urb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb.h | 2 +- drivers/media/usb/dvb-usb/nova-t-usb2.c | 4 ++-- drivers/media/usb/dvb-usb/ttusb2.c | 2 +- drivers/media/usb/dvb-usb/umt-010.c | 4 ++-- drivers/media/usb/dvb-usb/usb-urb.c | 2 +- drivers/media/usb/dvb-usb/vp702x-fe.c | 2 +- drivers/media/usb/dvb-usb/vp702x.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045-fe.c | 2 +- drivers/media/usb/dvb-usb/vp7045.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045.h | 2 +- 55 files changed, 80 insertions(+), 80 deletions(-) diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb index 669dc6ce4330..6f4b12f7b844 100644 --- a/Documentation/dvb/README.dvb-usb +++ b/Documentation/dvb/README.dvb-usb @@ -190,7 +190,7 @@ and watch another one. Patches, comments and suggestions are very very welcome. 3. Acknowledgements - Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for + Amaury Demol (Amaury.Demol@parrot.com) and Francois Kanounnikoff from DiBcom for providing specs, code and help, on which the dvb-dibusb, dib3000mb and dib3000mc are based. diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index 412c5daf2b48..0f5114d406f8 100644 --- a/drivers/media/common/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -1,7 +1,7 @@ /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop.c - main module part - * Copyright (C) 2004-9 Patrick Boettcher + * Copyright (C) 2004-9 Patrick Boettcher * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc * * Acknowledgements: @@ -34,7 +34,7 @@ #include "flexcop.h" #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" -#define DRIVER_AUTHOR "Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * This driver is "hard-coded" to be used with the 1st generation of * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming @@ -865,5 +865,5 @@ static struct dvb_frontend_ops bcm3510_ops = { }; MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/bcm3510.h b/drivers/media/dvb-frontends/bcm3510.h index ff66492fb940..961c2eb87c68 100644 --- a/drivers/media/dvb-frontends/bcm3510.h +++ b/drivers/media/dvb-frontends/bcm3510.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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 diff --git a/drivers/media/dvb-frontends/bcm3510_priv.h b/drivers/media/dvb-frontends/bcm3510_priv.h index 3bb1bc2a04f0..67f24686c31b 100644 --- a/drivers/media/dvb-frontends/bcm3510_priv.h +++ b/drivers/media/dvb-frontends/bcm3510_priv.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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 diff --git a/drivers/media/dvb-frontends/dib0070.c b/drivers/media/dvb-frontends/dib0070.c index 0b8fb5dd1889..ee7d66997ccd 100644 --- a/drivers/media/dvb-frontends/dib0070.c +++ b/drivers/media/dvb-frontends/dib0070.c @@ -774,6 +774,6 @@ free_mem: } EXPORT_SYMBOL(dib0070_attach); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index 47cb72243b9d..976ee034a430 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -2669,7 +2669,7 @@ free_mem: } EXPORT_SYMBOL(dib0090_fw_register); -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h index 6ae9899b5b45..d5dfafb4ef13 100644 --- a/drivers/media/dvb-frontends/dib3000.h +++ b/drivers/media/dvb-frontends/dib3000.h @@ -2,11 +2,11 @@ * public header file of the frontend drivers for mobile DVB-T demodulators * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 7a61172d0d45..3ca300939f79 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -2,11 +2,11 @@ * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information @@ -36,7 +36,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator" -#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" +#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de" static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/dvb-frontends/dib3000mb_priv.h b/drivers/media/dvb-frontends/dib3000mb_priv.h index 9dc235aa44b7..0459d5c84314 100644 --- a/drivers/media/dvb-frontends/dib3000mb_priv.h +++ b/drivers/media/dvb-frontends/dib3000mb_priv.h @@ -1,7 +1,7 @@ /* * dib3000mb_priv.h * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@posteo.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index 583d6b7fabed..ac90ed3af37e 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * @@ -939,6 +939,6 @@ static struct dvb_frontend_ops dib3000mc_ops = { .read_ucblocks = dib3000mc_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h index 74816f793611..b37e69e6a58c 100644 --- a/drivers/media/dvb-frontends/dib3000mc.h +++ b/drivers/media/dvb-frontends/dib3000mc.h @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 35eb71fe3c2b..8b21cccf3c3a 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1465,6 +1465,6 @@ static struct dvb_frontend_ops dib7000m_ops = { .read_ucblocks = dib7000m_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 33be5d6b9e10..65ab79ed5e3e 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2834,7 +2834,7 @@ static struct dvb_frontend_ops dib7000p_ops = { .read_ucblocks = dib7000p_read_unc_blocks, }; -MODULE_AUTHOR("Olivier Grenie "); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 94c26270fff0..349d2f1f62ce 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4516,6 +4516,6 @@ void *dib8000_attach(struct dib8000_ops *ops) } EXPORT_SYMBOL(dib8000_attach); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 8f92aca0b073..91888a2f5301 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -2589,7 +2589,7 @@ static struct dvb_frontend_ops dib9000_ops = { .read_ucblocks = dib9000_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c index 43be7238311e..723358d7ca84 100644 --- a/drivers/media/dvb-frontends/dibx000_common.c +++ b/drivers/media/dvb-frontends/dibx000_common.c @@ -510,6 +510,6 @@ u32 systime(void) } EXPORT_SYMBOL(systime); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 8b5e0b3a92a0..4cac1fc233f2 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -39,7 +39,7 @@ MODULE_PARM_DESC(debug, #define DRIVER_VERSION "0.1" #define DRIVER_NAME "flexcop-pci" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " struct flexcop_pci { struct pci_dev *pdev; diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 0bd969063392..d4bdba60b0f7 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -10,7 +10,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " /* debug */ #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 023d91f7e654..35f27e2e4e28 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h index 45f07090d431..a1622bda2a5e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index f0565bf3673e..5ec159f22399 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify @@ -1129,7 +1129,7 @@ int dvb_usbv2_reset_resume(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usbv2_reset_resume); MODULE_VERSION("2.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("DVB USB common"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c index 22bdce15ecf3..5bafeb6486be 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c index ca8f3c2b1082..55136cde38f5 100644 --- a/drivers/media/usb/dvb-usb-v2/usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 83684ed023cd..7ba975bea96a 100644 --- a/drivers/media/usb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T * USB2.0 (A800) DVB-T receiver. * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to * - AVerMedia who kindly provided information and @@ -185,7 +185,7 @@ static struct usb_driver a800_driver = { module_usb_driver(a800_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index ab7151181728..907ac01ae297 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -13,7 +13,7 @@ * * TODO: Use the cx25840-driver for the analogue part * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au) * @@ -2314,7 +2314,7 @@ static struct usb_driver cxusb_driver = { module_usb_driver(cxusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Michael Krufky "); MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 0d248ce02a9b..c16f999b9d7c 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -881,7 +881,7 @@ static struct usb_driver dib0700_driver = { module_usb_driver(dib0700_driver); MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index ef3a8f75f82e..35de6095926d 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -1,6 +1,6 @@ /* Common methods for dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c index a4ac37e0e98b..a0057641cc86 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mb.c +++ b/drivers/media/usb/dvb-usb/dibusb-mb.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -465,7 +465,7 @@ static struct usb_driver dibusb_driver = { module_usb_driver(dibusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-mc.c b/drivers/media/usb/dvb-usb/dibusb-mc.c index 9d1a59d09c52..08fb8a3f6e0c 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mc.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -143,7 +143,7 @@ static struct usb_driver dibusb_mc_driver = { module_usb_driver(dibusb_mc_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index 32ab1392313f..3f82163d8ab8 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h @@ -1,6 +1,6 @@ /* Header file for all dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 772bde3c5020..63134335c994 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -1,7 +1,7 @@ /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 * receiver * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * partly based on the SDK published by Nebula Electronics * @@ -348,7 +348,7 @@ static struct usb_driver digitv_driver = { module_usb_driver(digitv_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); MODULE_VERSION("1.0-alpha"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 8637ad1be6be..7e72a1bef76a 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -1,7 +1,7 @@ /* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * 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 diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index c357fb3b0a88..ca3b69aa9688 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c @@ -1,7 +1,7 @@ /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Steve Chang from WideView for providing support for the WT-220U. * @@ -362,7 +362,7 @@ static struct usb_driver dtt200u_usb_driver = { module_usb_driver(dtt200u_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u.h b/drivers/media/usb/dvb-usb/dtt200u.h index 005b0a7df358..efccc399b1cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.h +++ b/drivers/media/usb/dvb-usb/dtt200u.h @@ -1,7 +1,7 @@ /* Common header file of Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dvb-usb-common.h b/drivers/media/usb/dvb-usb/dvb-usb-common.h index 6b7b2a89242e..7e619d638809 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/usb/dvb-usb/dvb-usb-common.h @@ -1,6 +1,6 @@ /* dvb-usb-common.h is part of the DVB USB library. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * a header file containing prototypes and types for internal use of the dvb-usb-lib diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 9ddfcab268be..71de19ba0e01 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -1,6 +1,6 @@ /* dvb-usb-dvb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c index 733a7ff7b207..dd048a7c461c 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c @@ -1,6 +1,6 @@ /* dvb-usb-firmware.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c index 88e4a62abc44..4f0b0adce7f5 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c @@ -1,6 +1,6 @@ /* dvb-usb-i2c.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for (de-)initializing an I2C adapter. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c index 1adf325012f7..3896ba9a4179 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c @@ -3,7 +3,7 @@ * * dvb-usb-init.c * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -299,6 +299,6 @@ void dvb_usb_device_exit(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usb_device_exit); MODULE_VERSION("1.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 7b5dae3077f6..c259f9e43542 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -1,6 +1,6 @@ /* dvb-usb-remote.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing the input-device and for handling remote-control-queries. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-urb.c b/drivers/media/usb/dvb-usb/dvb-usb-urb.c index 5c8f651344fc..95f9097498cb 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-urb.c @@ -1,6 +1,6 @@ /* dvb-usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index ce4c4e3b58bb..639c4678c65b 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -1,6 +1,6 @@ /* dvb-usb.h is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * the headerfile, all dvb-usb-drivers have to include. diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index 6c55384e2fca..fc7569e2728d 100644 --- a/drivers/media/usb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -227,7 +227,7 @@ static struct usb_driver nova_t_driver = { module_usb_driver(nova_t_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index f10717311e05..ecc207fbaf3c 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -820,7 +820,7 @@ static struct usb_driver ttusb2_driver = { module_usb_driver(ttusb2_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/umt-010.c b/drivers/media/usb/dvb-usb/umt-010.c index 9b042292e788..58ad5b4f856c 100644 --- a/drivers/media/usb/dvb-usb/umt-010.c +++ b/drivers/media/usb/dvb-usb/umt-010.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -145,7 +145,7 @@ static struct usb_driver umt_driver = { module_usb_driver(umt_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/usb-urb.c b/drivers/media/usb/dvb-usb/usb-urb.c index d62ee0f5a165..89173603be67 100644 --- a/drivers/media/usb/dvb-usb/usb-urb.c +++ b/drivers/media/usb/dvb-usb/usb-urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/vp702x-fe.c b/drivers/media/usb/dvb-usb/vp702x-fe.c index d361a72ca0fa..27398c08c69d 100644 --- a/drivers/media/usb/dvb-usb/vp702x-fe.c +++ b/drivers/media/usb/dvb-usb/vp702x-fe.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c index ee1e19e36445..40de33de90a7 100644 --- a/drivers/media/usb/dvb-usb/vp702x.c +++ b/drivers/media/usb/dvb-usb/vp702x.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * @@ -439,7 +439,7 @@ static struct usb_driver vp702x_usb_driver = { module_usb_driver(vp702x_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045-fe.c b/drivers/media/usb/dvb-usb/vp7045-fe.c index e708afc6a57f..7765602ea658 100644 --- a/drivers/media/usb/dvb-usb/vp7045-fe.c +++ b/drivers/media/usb/dvb-usb/vp7045-fe.c @@ -1,7 +1,7 @@ /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index d750724132ee..13340af0d39c 100644 --- a/drivers/media/usb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c @@ -2,7 +2,7 @@ * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver * - DigitalNow TinyUSB2 DVB-t receiver * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * @@ -296,7 +296,7 @@ static struct usb_driver vp7045_usb_driver = { module_usb_driver(vp7045_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045.h b/drivers/media/usb/dvb-usb/vp7045.h index cf5ec46f8bb1..66499932ca76 100644 --- a/drivers/media/usb/dvb-usb/vp7045.h +++ b/drivers/media/usb/dvb-usb/vp7045.h @@ -1,7 +1,7 @@ /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII * USB2.0 DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * -- cgit v1.2.3 From 91be260faaf8561dc51e72033c346f6ab28d40d8 Mon Sep 17 00:00:00 2001 From: Nicolas Sugino Date: Thu, 26 Nov 2015 19:00:28 -0200 Subject: [media] dib8000: Add support for Mygica/Geniatech S2870 MyGica/Geniatech S2870 is very similar to the S870 but with dual tuner. The card is recognised as Geniatech STK8096-PVR. [mchehab@osg.samsung.com: Fix some checkpatch.pl issues] Signed-off-by: Nicolas Sugino Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb/dib0700_devices.c | 77 ++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 474582231b5d..7f5d0865acfd 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -118,6 +118,7 @@ #define USB_PID_DIBCOM_STK807XP 0x1f90 #define USB_PID_DIBCOM_STK807XPVR 0x1f98 #define USB_PID_DIBCOM_STK8096GP 0x1fa0 +#define USB_PID_DIBCOM_STK8096PVR 0x1faa #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 #define USB_PID_DIBCOM_TFE8096P 0x1f9C #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 7ed49646a699..ea0391e32d23 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -1736,8 +1736,13 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) struct dib0700_adapter_state *st = adap->priv; struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); - if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) - return -ENODEV; + if (adap->id == 0) { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } else { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override; @@ -1773,6 +1778,20 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } +static int stk809x_frontend1_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *state = adap->priv; + + if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) + return -ENODEV; + + state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x82, 0); + + adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; @@ -3794,6 +3813,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, + { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4959,6 +4979,59 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_BIT_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 2, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, { + .num_frontends = 1, + .fe = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend1_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x03), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + .num_device_descs = 1, + .devices = { + { "DiBcom STK8096-PVR reference design", + { &dib0700_usb_id_table[83], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_BIT_RC5 | + RC_BIT_RC6_MCE | + RC_BIT_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; -- cgit v1.2.3 From 33cb54015f5eebceb360443498430bdfab79778c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 19:38:44 -0200 Subject: [media] media: rc: nuvoton: mark wakeup-related resources When requesting resources use different names for the normal and the wakeup part. This makes it easier to interpret the output of e.g. /proc/interrupts and /proc/ioports. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 18adf580f502..081435cda30c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1079,12 +1079,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) goto exit_unregister_device; if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, - CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) + CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake")) goto exit_unregister_device; if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) + NVT_DRIVER_NAME "-wake", (void *)nvt)) goto exit_unregister_device; device_init_wakeup(&pdev->dev, true); -- cgit v1.2.3 From 464254e5dbd60124936d47be6679a23b42840b51 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 20:02:38 -0200 Subject: [media] media: rc: raw: improve FIFO handling The FIFO is used for ir_raw_event records, however for some historic reason the FIFO is used on a per byte basis. IMHO this adds unneeded complexity. Therefore set up the FIFO for ir_raw_event records. This also allows to define the FIFO statically as part of ir_raw_event_ctrl instead of having to allocate the FIFO dynamically. In addition: - When writing into the FIFO and it's full return ENOSPC instead of ENOMEM thus making it easier to tell between "FIFO full" and "Dynamic memory allocation failed" when the error is propagated to a higher level. Also add an error message. - When reading from the FIFO check whether it's empty. This is not strictly needed here but kfifo_out is annotated "must check" anyway. Successfully tested it with the nuvoton-cir driver. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-core-priv.h | 6 +++++- drivers/media/rc/rc-ir-raw.c | 23 ++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7359f3d03b64..585d5e52118d 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -16,6 +16,9 @@ #ifndef _RC_CORE_PRIV #define _RC_CORE_PRIV +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + #include #include #include @@ -35,7 +38,8 @@ struct ir_raw_event_ctrl { struct list_head list; /* to keep track of raw clients */ struct task_struct *thread; spinlock_t lock; - struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */ + /* fifo for the pulse/space durations */ + DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE); ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ struct rc_dev *dev; /* pointer to the parent rc_dev */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index c69807fe2fef..144304c94606 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -20,9 +20,6 @@ #include #include "rc-core-priv.h" -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ static LIST_HEAD(ir_raw_client_list); @@ -36,14 +33,12 @@ static int ir_raw_event_thread(void *data) struct ir_raw_event ev; struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; while (!kthread_should_stop()) { spin_lock_irq(&raw->lock); - retval = kfifo_len(&raw->kfifo); - if (retval < sizeof(ev)) { + if (!kfifo_len(&raw->kfifo)) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) @@ -54,7 +49,8 @@ static int ir_raw_event_thread(void *data) continue; } - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + if(!kfifo_out(&raw->kfifo, &ev, 1)) + dev_err(&raw->dev->dev, "IR event FIFO is empty!\n"); spin_unlock_irq(&raw->lock); mutex_lock(&ir_raw_handler_lock); @@ -87,8 +83,10 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) IR_dprintk(2, "sample: (%05dus %s)\n", TO_US(ev->duration), TO_STR(ev->pulse)); - if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; + if (!kfifo_put(&dev->raw->kfifo, *ev)) { + dev_err(&dev->dev, "IR event FIFO is full!\n"); + return -ENOSPC; + } return 0; } @@ -273,11 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; - rc = kfifo_alloc(&dev->raw->kfifo, - sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) - goto out; + INIT_KFIFO(dev->raw->kfifo); spin_lock_init(&dev->raw->lock); dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, @@ -319,7 +313,6 @@ void ir_raw_event_unregister(struct rc_dev *dev) handler->raw_unregister(dev); mutex_unlock(&ir_raw_handler_lock); - kfifo_free(&dev->raw->kfifo); kfree(dev->raw); dev->raw = NULL; } -- cgit v1.2.3 From c5d89a49fcb47e27a9ef96b63bdbe7fbf0504bd8 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Sat, 28 Nov 2015 23:53:31 -0200 Subject: [media] Add support for Terratec Cinergy S2 Rev.4 Also Add Terratec Cinergy S2 usb id's Signed-off-by: Benjamin Larsson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 4 ++++ drivers/media/usb/dvb-usb-v2/dvbsky.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 7f5d0865acfd..750d23f9928d 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -256,6 +256,10 @@ #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab +#define USB_PID_TERRATEC_CINERGY_S2_R1 0x00a8 +#define USB_PID_TERRATEC_CINERGY_S2_R2 0x00b0 +#define USB_PID_TERRATEC_CINERGY_S2_R3 0x0102 +#define USB_PID_TERRATEC_CINERGY_S2_R4 0x0105 #define USB_PID_TERRATEC_H7 0x10b4 #define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_H7_3 0x10a5 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 1dd962535f97..2d922b96ed83 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -851,6 +851,9 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, + &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", + RC_MAP_DVBSKY) }, { } }; MODULE_DEVICE_TABLE(usb, dvbsky_id_table); -- cgit v1.2.3 From a561d768c13287ef156863c4ff149306844101fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 12:47:44 -0200 Subject: [media] dw2102: use the new USB ID Terratec Cinergy S2 macros Now that this was defined at usb-id.h, update the values for USB_PID_TERRATEC_CINERGY_S2_R1 and USB_PID_TERRATEC_CINERGY_S2_R2. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 14ef25dc6cd3..bc19da5ad3b7 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1702,13 +1702,13 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, - [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)}, + [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)}, [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, + [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, -- cgit v1.2.3 From 7655a3aea2ca14b9d34af929304f3c08140cc91c Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Thu, 3 Dec 2015 18:12:50 -0200 Subject: [media] si2165: Reject DVB-T bandwidth auto mode The si2165 does not support bandwidth auto-detection. Reject the request. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 2b93241d4bc1..659976612392 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -825,19 +825,19 @@ static int si2165_set_frontend_dvbt(struct dvb_frontend *fe) struct si2165_state *state = fe->demodulator_priv; u32 dvb_rate = 0; u16 bw10k; + u32 bw_hz = p->bandwidth_hz; dprintk("%s: called\n", __func__); if (!state->has_dvbt) return -EINVAL; - if (p->bandwidth_hz > 0) { - dvb_rate = p->bandwidth_hz * 8 / 7; - bw10k = p->bandwidth_hz / 10000; - } else { - dvb_rate = 8 * 8 / 7; - bw10k = 800; - } + /* no bandwidth auto-detection */ + if (bw_hz == 0) + return -EINVAL; + + dvb_rate = bw_hz * 8 / 7; + bw10k = bw_hz / 10000; ret = si2165_adjust_pll_divl(state, 12); if (ret < 0) -- cgit v1.2.3 From 27524ff8cd6c28ea3735f80f0374e0fc5494768f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 9 Dec 2015 11:46:55 -0200 Subject: [media] : cxd2830r: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Antti Palosaari Signed-off-by: Linus Walleij Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cxd2820r_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 24a457d9d803..ba4cb7557aa5 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -606,8 +606,7 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -620,8 +619,7 @@ static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -636,8 +634,7 @@ static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr); @@ -731,7 +728,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, priv->gpio_chip.base = -1; /* dynamic allocation */ priv->gpio_chip.ngpio = GPIO_COUNT; priv->gpio_chip.can_sleep = 1; - ret = gpiochip_add(&priv->gpio_chip); + ret = gpiochip_add_data(&priv->gpio_chip, priv); if (ret) goto error; -- cgit v1.2.3 From 47de9bf8931e6bf9c92fdba9867925d1ce482ab1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 14:39:34 -0200 Subject: [media] tvp5150: Fix breakage for serial usage changeset 460b6c0831cb ("tvp5150: Add s_stream subdev operation support") broke for em28xx-based devices with uses tvp5150. On those devices, touching the TVP5150_MISC_CTL register causes em28xx to stop streaming. I suspect that it uses the 27 MHz clock provided by tvp5150 to feed em28xx. So, change the logic to do nothing on s_stream if the tvp5150 is not set up to work with V4L2_MBUS_PARALLEL. Tested with Hauppauge WinTV USB 2 model 42012 Rev. C186 (USB ID: 2040:4200). Cc: Javier Martinez Canillas Cc: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..779c6f453cc9 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,19 +975,18 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ - int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type == V4L2_MBUS_PARALLEL) - val = 0x0d; + if (decoder->mbus_type != V4L2_MBUS_PARALLEL) + return 0; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, val); + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit v1.2.3 From c1ae8f3ad8758b588b4ba02edcb8d413185a10d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 12 Dec 2015 22:32:01 -0200 Subject: [media] davinci: ccdc_update_raw_params() frees the wrong thing Passing a physical address to free_pages() is a bad idea. config_params->fault_pxl.fpc_table_addr is set to virt_to_phys() of __get_free_pages() return value; what we should pass to free_pages() is its phys_to_virt(). ccdc_close() does that properly, but ccdc_update_raw_params() doesn't. Signed-off-by: Al Viro Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/dm644x_ccdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index ffbefdff6b5e..6fba32bec974 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -261,7 +261,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) */ if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { if (fpc_physaddr != NULL) { - free_pages((unsigned long)fpc_physaddr, + free_pages((unsigned long)fpc_virtaddr, get_order (config_params->fault_pxl.fp_num * FP_NUM_BYTES)); -- cgit v1.2.3 From 28d5bdbe5c0adcc11b7b63e65cf002a1ebaf3ca4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 12:41:51 -0200 Subject: [media] mt9v032: Add reset and standby gpios Add optional reset and standby gpios. The reset gpio is used to reset the chip in power_on(). The standby gpio is not used currently. It is just unset, so the chip is not in standby. Signed-off-by: Markus Pargmann Reviewed-by: Philipp Zabel Acked-by: Rob Herring Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/mt9v032.txt | 2 ++ drivers/media/i2c/mt9v032.c | 28 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt index 202565313e82..100f0ae43269 100644 --- a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt +++ b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt @@ -20,6 +20,8 @@ Optional Properties: - link-frequencies: List of allowed link frequencies in Hz. Each frequency is expressed as a 64-bit big-endian integer. +- reset-gpios: GPIO handle which is connected to the reset pin of the chip. +- standby-gpios: GPIO handle which is connected to the standby pin of the chip. For further reading on port node refer to Documentation/devicetree/bindings/media/video-interfaces.txt. diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2e1d116a64e7..501b37039449 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -251,6 +252,8 @@ struct mt9v032 { struct regmap *regmap; struct clk *clk; + struct gpio_desc *reset_gpio; + struct gpio_desc *standby_gpio; struct mt9v032_platform_data *pdata; const struct mt9v032_model_info *model; @@ -312,16 +315,31 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) struct regmap *map = mt9v032->regmap; int ret; + if (mt9v032->reset_gpio) + gpiod_set_value_cansleep(mt9v032->reset_gpio, 1); + ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk); if (ret < 0) return ret; + /* System clock has to be enabled before releasing the reset */ ret = clk_prepare_enable(mt9v032->clk); if (ret) return ret; udelay(1); + if (mt9v032->reset_gpio) { + gpiod_set_value_cansleep(mt9v032->reset_gpio, 0); + + /* After releasing reset we need to wait 10 clock cycles + * before accessing the sensor over I2C. As the minimum SYSCLK + * frequency is 13MHz, waiting 1µs will be enough in the worst + * case. + */ + udelay(1); + } + /* Reset the chip and stop data read out */ ret = regmap_write(map, MT9V032_RESET, 1); if (ret < 0) @@ -954,6 +972,16 @@ static int mt9v032_probe(struct i2c_client *client, if (IS_ERR(mt9v032->clk)) return PTR_ERR(mt9v032->clk); + mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(mt9v032->reset_gpio)) + return PTR_ERR(mt9v032->reset_gpio); + + mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", + GPIOD_OUT_LOW); + if (IS_ERR(mt9v032->standby_gpio)) + return PTR_ERR(mt9v032->standby_gpio); + mutex_init(&mt9v032->power_lock); mt9v032->pdata = pdata; mt9v032->model = (const void *)did->driver_data; -- cgit v1.2.3 From 23c7d7134147f276a09d0e55011cf682a0051093 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:25 -0200 Subject: [media] staging: media: lirc: replace NULL comparisons with !var A NULL comparison can be written as if (var) or if (!var). Reported by checkpatch. Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index d009bcb439f0..7df827856de6 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -647,7 +647,7 @@ static int __init lirc_parallel_init(void) goto exit_device_put; pport = parport_find_base(io); - if (pport == NULL) { + if (!pport) { pr_notice("no port at %x found\n", io); result = -ENXIO; goto exit_device_put; @@ -656,7 +656,7 @@ static int __init lirc_parallel_init(void) pf, kf, lirc_lirc_irq_handler, 0, NULL); parport_put_port(pport); - if (ppdevice == NULL) { + if (!ppdevice) { pr_notice("parport_register_device() failed\n"); result = -ENXIO; goto exit_device_put; -- cgit v1.2.3 From b790aea57ecd31786ec2b00f8551261c57db4bd4 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:26 -0200 Subject: [media] staging: media: lirc: no space after cast checkpatch complains about space after type cast. [mchehab@osg.samsung.com: removed an obsolete hunk] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 7df827856de6..eed6ffac7c90 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -286,9 +286,9 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64) signal)*1000000; + helper = ((__u64)signal)*1000000; do_div(helper, timer); - signal = (long) helper; + signal = (long)helper; if (signal > LIRC_SFH506_DELAY) data = signal - LIRC_SFH506_DELAY; @@ -393,9 +393,9 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64) wbuf[i])*timer; + helper = ((__u64)wbuf[i])*timer; do_div(helper, 1000000); - wbuf[i] = (int) helper; + wbuf[i] = (int)helper; } local_irq_save(flags); -- cgit v1.2.3 From 0d2f79c2bb34d9a9631a43b8d5ea7f2968564a6a Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:27 -0200 Subject: [media] staging: media: lirc: space around operator checkpatch complains about missing space around operators. [mchehab@osg.samsung.com: removed obsolete hunks] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index eed6ffac7c90..6e2edb24d9d5 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -193,7 +193,7 @@ static int lirc_claim(void) return 0; } } - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); is_claimed = 1; return 1; } @@ -264,7 +264,7 @@ static void lirc_lirc_irq_handler(void *blah) init = 1; } - timeout = timer/10; /* timeout after 1/10 sec. */ + timeout = timer / 10; /* timeout after 1/10 sec. */ signal = 1; level = lirc_get_timer(); do { @@ -286,7 +286,7 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64)signal)*1000000; + helper = ((__u64)signal) * 1000000; do_div(helper, timer); signal = (long)helper; @@ -294,7 +294,7 @@ static void lirc_lirc_irq_handler(void *blah) data = signal - LIRC_SFH506_DELAY; else data = 1; - rbuf_write(PULSE_BIT|data); /* pulse */ + rbuf_write(PULSE_BIT | data); /* pulse */ } lastkt = ktime_get(); #else @@ -331,7 +331,7 @@ static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n, set_current_state(TASK_INTERRUPTIBLE); while (count < n) { if (rptr != wptr) { - if (copy_to_user(buf+count, &rbuf[rptr], + if (copy_to_user(buf + count, &rbuf[rptr], sizeof(int))) { result = -EFAULT; break; @@ -393,7 +393,7 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64)wbuf[i])*timer; + helper = ((__u64)wbuf[i]) * timer; do_div(helper, 1000000); wbuf[i] = (int)helper; } @@ -664,7 +664,7 @@ static int __init lirc_parallel_init(void) if (parport_claim(ppdevice) != 0) goto skip_init; is_claimed = 1; - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); #ifdef LIRC_TIMER if (debug) -- cgit v1.2.3 From d5441ea58ccc70637b75b035dee61685b516a5ca Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Dec 2015 12:28:37 -0200 Subject: [media] gsc-m2m: Use an unsigned data type for a variable The data type "int" was used by the variable "ret" in the gsc_m2m_poll() function despite of the aspect that the type "unsigned int" will usually be needed for the return value from a call of the v4l2_m2m_poll() function. Improve this implementation detail by addition of the type modifier then. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 93782f15b825..a600e32e2543 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -700,7 +700,7 @@ static unsigned int gsc_m2m_poll(struct file *file, { struct gsc_ctx *ctx = fh_to_ctx(file->private_data); struct gsc_dev *gsc = ctx->gsc_dev; - int ret; + unsigned int ret; if (mutex_lock_interruptible(&gsc->lock)) return -ERESTARTSYS; -- cgit v1.2.3 From 2e490139b137bbac3250d594cef3dcbc461ad4cc Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 21 Dec 2015 11:54:46 -0200 Subject: [media] media: i2c: ov2659: speedup probe if no device connected The ov2659 driver performs device detection and initialization in the following way: - send reset command REG_SOFTWARE_RESET - load array of predefined register's setting (~150 values) - read device version REG_SC_CHIP_ID_H/REG_SC_CHIP_ID_L - check version and exit if invalid. As result, for not connected device there will be >~150 i2c transactions executed before device version checking and exit (there are no failures detected because ov2659 declared as I2C_CLIENT_SCCB and NACKs are ignored in this case). Let's fix that by checking the chip version first and start initialization only if it's supported. Cc: Benoit Parrot Signed-off-by: Grygorii Strashko Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2659.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 02b9a3440557..1f999e9c0118 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1321,10 +1321,6 @@ static int ov2659_detect(struct v4l2_subdev *sd) } usleep_range(1000, 2000); - ret = ov2659_init(sd, 0); - if (ret < 0) - return ret; - /* Check sensor revision */ ret = ov2659_read(client, REG_SC_CHIP_ID_H, &pid); if (!ret) @@ -1338,8 +1334,10 @@ static int ov2659_detect(struct v4l2_subdev *sd) dev_err(&client->dev, "Sensor detection failed (%04X, %d)\n", id, ret); - else + else { dev_info(&client->dev, "Found OV%04X sensor\n", id); + ret = ov2659_init(sd, 0); + } } return ret; -- cgit v1.2.3 From c2e5c951c2d10536a9f17647f3440e5f9f639d8b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 15:23:57 -0200 Subject: [media] si2165: Refactoring for si2165_writereg_mask8() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the si2165_readreg8() function failed. 2. Reduce the scope for the local variables "ret" and "tmp" to one branch of an if statement. 3. Delete the jump label "err" then. 4. Return the value from a call of the si2165_writereg8() function without using an extra assignment for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 659976612392..8bf716a8ea58 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -225,22 +225,18 @@ static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg, u8 val, u8 mask) { - int ret; - u8 tmp; - if (mask != 0xff) { - ret = si2165_readreg8(state, reg, &tmp); + u8 tmp; + int ret = si2165_readreg8(state, reg, &tmp); + if (ret < 0) - goto err; + return ret; val &= mask; tmp &= ~mask; val |= tmp; } - - ret = si2165_writereg8(state, reg, val); -err: - return ret; + return si2165_writereg8(state, reg, val); } #define REG16(reg, val) { (reg), (val) & 0xff }, { (reg)+1, (val)>>8 & 0xff } -- cgit v1.2.3 From 2050d14c6ea23ea7b50b5cc7d05dbf645705cf70 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 12:20:45 -0200 Subject: [media] tuners: Refactoring for m88rs6000t_sleep() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the regmap_write() function failed. 2. Delete the jump label "err" then. 3. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/m88rs6000t.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c index 504bfbc4027a..9f3e0fd4cad9 100644 --- a/drivers/media/tuners/m88rs6000t.c +++ b/drivers/media/tuners/m88rs6000t.c @@ -461,13 +461,12 @@ static int m88rs6000t_sleep(struct dvb_frontend *fe) dev_dbg(&dev->client->dev, "%s:\n", __func__); ret = regmap_write(dev->regmap, 0x07, 0x6d); - if (ret) - goto err; - usleep_range(5000, 10000); -err: - if (ret) + if (ret) { dev_dbg(&dev->client->dev, "failed=%d\n", ret); - return ret; + return ret; + } + usleep_range(5000, 10000); + return 0; } static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency) -- cgit v1.2.3 From 61f8e1a73296d065abc959e0c0861ffbdfa2d0b3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 13:36:44 -0200 Subject: [media] r820t: Delete an unnecessary variable initialisation in generic_set_freq() The variable "rc" will be set to an appropriate value from a call of the r820t_set_tv_standard() function. Thus let us omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index a7a8452e99d2..6ab35e315fe7 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -1295,7 +1295,7 @@ static int generic_set_freq(struct dvb_frontend *fe, v4l2_std_id std, u32 delsys) { struct r820t_priv *priv = fe->tuner_priv; - int rc = -EINVAL; + int rc; u32 lo_freq; tuner_dbg("should set frequency to %d kHz, bw %d MHz\n", -- cgit v1.2.3 From a73cfe527c10bb023f0e22dd8cf37dd418c093e7 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 09:32:41 -0200 Subject: [media] msi2500: Delete an unnecessary check in msi2500_set_usb_adc() This issue was detected by using the Coccinelle software. Return the value from a call of the msi2500_ctrl_msg() function without using an extra check for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/msi2500/msi2500.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index c104315fdc17..2d33033682af 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -839,8 +839,6 @@ static int msi2500_set_usb_adc(struct msi2500_dev *dev) goto err; ret = msi2500_ctrl_msg(dev, CMD_WREG, reg3); - if (ret) - goto err; err: return ret; } -- cgit v1.2.3 From 3def9ad6d3066e597d0ce86801a81eedb130b04a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:22 -0200 Subject: [media] nuvoton-cir: use request_muxed_region for accessing EFM registers The two EFM ioports are accessed by drivers for other parts of the Nuvoton Super-IO chips too. Therefore access to these ioports needs to be protected by using request_muxed_region (like it's implemented e.g. in hwmon/nct6775 already). Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 081435cda30c..62c82c54ec82 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -80,17 +80,24 @@ static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) } /* enter extended function mode */ -static inline void nvt_efm_enable(struct nvt_dev *nvt) +static inline int nvt_efm_enable(struct nvt_dev *nvt) { + if (!request_muxed_region(nvt->cr_efir, 2, NVT_DRIVER_NAME)) + return -EBUSY; + /* Enabling Extended Function Mode explicitly requires writing 2x */ outb(EFER_EFM_ENABLE, nvt->cr_efir); outb(EFER_EFM_ENABLE, nvt->cr_efir); + + return 0; } /* exit extended function mode */ static inline void nvt_efm_disable(struct nvt_dev *nvt) { outb(EFER_EFM_DISABLE, nvt->cr_efir); + + release_region(nvt->cr_efir, 2); } /* -- cgit v1.2.3 From 7a89836e994eaad7a17ae293ea1cd2b5597d2b4e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:34 -0200 Subject: [media] nuvoton-cir: simplify nvt_select_logical_ dev Use nvt_cr_write to simplify nvt_select_logical_ dev. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 62c82c54ec82..2539d4f10a0c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -107,8 +107,7 @@ static inline void nvt_efm_disable(struct nvt_dev *nvt) */ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) { - outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); - outb(ldev, nvt->cr_efdr); + nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } /* write val to cir config register */ -- cgit v1.2.3 From 1feac493b08a87b912a09b62666ad6d49bd6b87b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:41 -0200 Subject: [media] nuvoton-cir: simplify nvt_cir_tx_inactive Simplify nvt_cir_tx_inactive. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 2539d4f10a0c..f661effac82e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -742,16 +742,13 @@ static void nvt_cir_log_irqs(u8 status, u8 iren) static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) { unsigned long flags; - bool tx_inactive; u8 tx_state; spin_lock_irqsave(&nvt->tx.lock, flags); tx_state = nvt->tx.tx_state; spin_unlock_irqrestore(&nvt->tx.lock, flags); - tx_inactive = (tx_state == ST_TX_NONE); - - return tx_inactive; + return tx_state == ST_TX_NONE; } /* interrupt service routine for incoming and outgoing CIR data */ -- cgit v1.2.3 From a17ede9ac1d8164e4d0b0b58e21bfa40890818d2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:05 -0200 Subject: [media] nuvoton-cir: factor out logical device disabling Factor out disabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f661effac82e..ceb6b95b13fa 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and disable logical device with setting EFM mode*/ +static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* write val to cir config register */ static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) { @@ -937,13 +946,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); - nvt_efm_enable(nvt); - /* disable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } static int nvt_open(struct rc_dev *dev) @@ -1145,13 +1149,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); - nvt_efm_enable(nvt); - /* disable cir logical dev */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); -- cgit v1.2.3 From e1a7d981cfefbf8e0261083a10ccad7dd0af6394 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:47 -0200 Subject: [media] nuvoton-cir: fix clearing wake fifo At least on NVT6779D clearing the wake fifo works in learning mode only (although this condition is not mentioned in the chip spec). Setting the clear fifo bit has no effect in wake up mode. Even if clearing the wake fifo should work in wake up mode on other chips this workaround doesn't hurt. If needed the caller of nvt_clear_cir_wake_fifo has to take care of locking. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ceb6b95b13fa..5f36227a9059 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -370,11 +370,19 @@ static void nvt_clear_cir_fifo(struct nvt_dev *nvt) /* clear out the hardware's cir wake rx fifo */ static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) { - u8 val; + u8 val, config; + + config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON); + + /* clearing wake fifo works in learning mode only */ + nvt_cir_wake_reg_write(nvt, config & ~CIR_WAKE_IRCON_MODE0, + CIR_WAKE_IRCON); val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, CIR_WAKE_FIFOCON); + + nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); } /* clear out the hardware's cir tx fifo */ -- cgit v1.2.3 From f2c2ba0e251d0b5211ce0397081b087ac623136f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:18 -0200 Subject: [media] nuvoton-cir: use IR_DEFAULT_TIMEOUT and consider SAMPLE_PERIOD Switch to using the recently introduced IR default timeout value (IR_DEFAULT_TIMEOUT) and consider the value of SAMPLE_PERIOD when calculating the limit count register value. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 0ad15d34e9c9..6a3de08a17c0 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -157,8 +157,8 @@ struct nvt_dev { /* total length of CIR and CIR WAKE */ #define CIR_IOREG_LENGTH 0x0f -/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ -#define CIR_RX_LIMIT_COUNT 0x7d0 +/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL */ +#define CIR_RX_LIMIT_COUNT (IR_DEFAULT_TIMEOUT / US_TO_NS(SAMPLE_PERIOD)) /* CIR Regs */ #define CIR_IRCON 0x00 -- cgit v1.2.3 From 0890655c29a88765924c46460f38f33f7e34b5fc Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:12 -0200 Subject: [media] nuvoton-cir: factor out logical device enabling Factor out enabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5f36227a9059..f6248519b31e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and enable logical device with setting EFM mode*/ +static inline void nvt_enable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* select and disable logical device with setting EFM mode*/ static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) { @@ -924,13 +933,8 @@ static void nvt_enable_cir(struct nvt_dev *nvt) CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); - nvt_efm_enable(nvt); - /* enable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); /* clear all pending interrupts */ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); @@ -1176,11 +1180,7 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_set_cir_iren(nvt); /* Enable CIR logical device */ - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From ccca00d6d7c2d6cec282ac3e3942032268d50fe4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:59 -0200 Subject: [media] nuvoton-cir: improve logical device handling Only enable the logical devices after the registers have been initialized. The call to nvt_enable_logical_dev in nvt_resume is not needed as this is done implicitely by nvt_cir_regs_init now. [mchehab@osg.samsung.com: fixed multiline comment to kernel CodingStyle] Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f6248519b31e..5593a2f5b6c4 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -329,9 +329,8 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) val |= psval; nvt_cr_write(nvt, val, psreg); - /* Select CIR logical device and enable */ + /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -344,7 +343,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) { - /* Select ACPI logical device, enable it and CIR Wake */ + /* Select ACPI logical device and anable it */ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); @@ -354,9 +353,8 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* enable pme interrupt of cir wakeup event */ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); - /* Select CIR Wake logical device and enable */ + /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -440,6 +438,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) /* and finally, enable interrupts */ nvt_set_cir_iren(nvt); + + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); } static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) @@ -474,6 +475,9 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) /* clear any and all stray interrupts */ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); + + /* enable the CIR WAKE logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); } static void nvt_enable_wake(struct nvt_dev *nvt) @@ -1051,7 +1055,10 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) nvt_cir_wake_ldev_init(nvt); nvt_efm_disable(nvt); - /* Initialize CIR & CIR Wake Config Registers */ + /* + * Initialize CIR & CIR Wake Config Registers + * and enable logical devices + */ nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); @@ -1179,9 +1186,6 @@ static int nvt_resume(struct pnp_dev *pdev) /* open interrupt */ nvt_set_cir_iren(nvt); - /* Enable CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From 0c6fbfdf8663e26a7e29f6142bd7ac2ac35310af Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:56 -0200 Subject: [media] nuvoton-cir: remove unneeded EFM operation in nvt_cir_isr Selecting the logical device in the interrupt handler is not needed as no configuration register is accessed. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5593a2f5b6c4..ec14b63a280d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -790,10 +790,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_efm_disable(nvt); - /* * Get IR Status register contents. Write 1 to ack/clear * -- cgit v1.2.3 From d790c9b93b0c37a23680c88b63be0e34744f764e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:13 -0200 Subject: [media] nuvoton-cir: remove unneeded call to nvt_set_cir_iren Calling nvt_set_cir_iren separately is not needed as this is done by nvt_cir_regs_init. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ec14b63a280d..d396dcc11be5 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1179,9 +1179,6 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_dbg("%s called", __func__); - /* open interrupt */ - nvt_set_cir_iren(nvt); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From fb16aaf58cbe902585fc3a2ce40d74a2de384ac2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:05 -0200 Subject: [media] nuvoton-cir: fix setting ioport base address At least on Zotac CI321 ACPI provides an ioport range for the wake up part but accessing these ioports has no effect. Instead the ioport base address is set to another value already (0xa20 in my case) and accessing this ioport range works. Therefore set a new ioport base address only if the current ioport base address is 0 (register reset default). The need to use the existing base address instead of trying to set an own one doesn't seem to be limited to this specific device as other drivers like hwmon/nct6775 do it the same way. This change was successfully tested on the mentioned device. And the change should be generic enough to not break the driver for other chips (however due to lack of appropriate hardware I wasn't able to test this). [mchehab@osg.samsung.com: Tested on Intel NUC NUC5i7RYB with BIOS version RYBDWi35.86A.0350.2015.0812.1722] Signed-off-by: Heiner Kallweit Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d396dcc11be5..5790ee46a38d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -161,6 +161,22 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) return val; } +/* don't override io address if one is set already */ +static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned long *ioaddr) +{ + unsigned long old_addr; + + old_addr = nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8; + old_addr |= nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO); + + if (old_addr) + *ioaddr = old_addr; + else { + nvt_cr_write(nvt, *ioaddr >> 8, CR_CIR_BASE_ADDR_HI); + nvt_cr_write(nvt, *ioaddr & 0xff, CR_CIR_BASE_ADDR_LO); + } +} + /* dump current cir register contents */ static void cir_dump_regs(struct nvt_dev *nvt) { @@ -332,8 +348,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_addr); nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); @@ -356,8 +371,7 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_wake_addr); nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); -- cgit v1.2.3 From 13d52fe40f1f7bbad49128e8ee6a2fe5e13dd18d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 06:59:39 -0200 Subject: [media] em28xx: fix implementation of s_stream On em28xx driver, s_stream subdev ops was not implemented properly. It was used only to disable stream, never enabling it. That was the root cause of the regression when we added support for s_stream on tvp5150 driver. With that, we can get rid of the changes on tvp5150 side, e. g. changeset 47de9bf8931e ('[media] tvp5150: Fix breakage for serial usage'). Tested video output on em2820+tvp5150 on WinTV USB2 and video and/or vbi output on em288x+tvp5150 on HVR 950. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 0e86ff423c49..6a015e8e8655 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -196,7 +196,6 @@ static void em28xx_wake_i2c(struct em28xx *dev) v4l2_device_call_all(v4l2_dev, 0, core, reset, 0); v4l2_device_call_all(v4l2_dev, 0, video, s_routing, INPUT(dev->ctl_input)->vmux, 0, 0); - v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0); } static int em28xx_colorlevels_set_default(struct em28xx *dev) @@ -962,6 +961,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) f.type = V4L2_TUNER_ANALOG_TV; v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, &f); + + /* Enable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1); } v4l2->streaming_users++; @@ -981,6 +983,9 @@ static void em28xx_stop_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } @@ -1013,6 +1018,9 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } -- cgit v1.2.3 From 841502d731f1708aae907d5bdf1659e8a372fc9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 07:13:30 -0200 Subject: Revert "[media] tvp5150: Fix breakage for serial usage" This patch were a workaround for a regression at tvp5150, but it causes troubles on devices with omap3+tvp5151 when working in non-parallel bus mode. Now that em28xx was fixed, we can get rid of that. This reverts commit 47de9bf8931e6bf9c92fdba9867925d1ce482ab1. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 779c6f453cc9..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,18 +975,19 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type != V4L2_MBUS_PARALLEL) - return 0; + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit v1.2.3 From 4f57d27be2a5a10ad042fcfd97c5ea9f4d5215f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:23 -0200 Subject: [media] tvp5150: fix tvp5150_fill_fmt() The tvp5150 output video is interlaced so mark the format field as alternate and reduce the height to the half. [javier: split patch and write commit message] Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..c277caaad8be 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -852,10 +852,10 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, tvp5150_reset(sd, 0); f->width = decoder->rect.width; - f->height = decoder->rect.height; + f->height = decoder->rect.height / 2; f->code = MEDIA_BUS_FMT_UYVY8_2X8; - f->field = V4L2_FIELD_SEQ_TB; + f->field = V4L2_FIELD_ALTERNATE; f->colorspace = V4L2_COLORSPACE_SMPTE170M; v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, -- cgit v1.2.3 From e545ac872ff884801a48beb7e6e0fc7513555fd9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:24 -0200 Subject: [media] tvp5150: Add pad-level subdev operations This patch enables the tvp5150 decoder driver to be used with the media controller framework by adding pad-level subdev operations and init the media entity pad. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index c277caaad8be..0ad122fcd632 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -37,6 +37,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -826,17 +827,6 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) } } -static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad || code->index) - return -EINVAL; - - code->code = MEDIA_BUS_FMT_UYVY8_2X8; - return 0; -} - static int tvp5150_fill_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -968,6 +958,38 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + V4L2 subdev pad ops + ****************************************************************************/ +static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->pad || code->index) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_UYVY8_2X8; + return 0; +} + +static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fse->code = MEDIA_BUS_FMT_UYVY8_2X8; + fse->min_width = decoder->rect.width; + fse->max_width = decoder->rect.width; + fse->min_height = decoder->rect.height / 2; + fse->max_height = decoder->rect.height / 2; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1132,6 +1154,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { .enum_mbus_code = tvp5150_enum_mbus_code, + .enum_frame_size = tvp5150_enum_frame_size, .set_fmt = tvp5150_fill_fmt, .get_fmt = tvp5150_fill_fmt, }; @@ -1287,6 +1310,14 @@ static int tvp5150_probe(struct i2c_client *c, } v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + +#if defined(CONFIG_MEDIA_CONTROLLER) + core->pad.flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (res < 0) + return res; +#endif res = tvp5150_detect_version(core); if (res < 0) -- cgit v1.2.3 From d83a96a53dd2c36948be37b64a85a761b942ddfd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 09:24:29 -0200 Subject: [media] em28xx: remove unused input types The em28xx driver have lots of different input types but only 4 of such types are actually used. The others are bogus. Remove them, in order to cleanup the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 134 ++++++++++++++++---------------- drivers/media/usb/em28xx/em28xx-video.c | 16 ++-- drivers/media/usb/em28xx/em28xx.h | 8 +- 3 files changed, 73 insertions(+), 85 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a1b6ef5894a6..ab0fe0319991 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -570,7 +570,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -583,7 +583,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -605,7 +605,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -616,7 +616,7 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -635,7 +635,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -655,7 +655,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -675,7 +675,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -715,7 +715,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -735,7 +735,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -755,7 +755,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -775,7 +775,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -800,7 +800,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_AUX, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE5, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -819,7 +819,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -829,7 +829,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -848,7 +848,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { @@ -863,7 +863,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -879,7 +879,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -889,7 +889,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -909,7 +909,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -930,7 +930,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -952,7 +952,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -974,7 +974,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -992,7 +992,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1006,7 +1006,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1029,7 +1029,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1100,7 +1100,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = terratec_cinergy_USB_XS_FR_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = terratec_cinergy_USB_XS_FR_analog, @@ -1186,7 +1186,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1213,7 +1213,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1239,7 +1239,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1265,7 +1265,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1291,7 +1291,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1317,7 +1317,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1343,7 +1343,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1368,7 +1368,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1392,7 +1392,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1413,7 +1413,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1428,7 +1428,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* capture only board */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1443,7 +1443,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture-only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = vc211a_enable, @@ -1465,7 +1465,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1485,7 +1485,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1500,7 +1500,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1520,7 +1520,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1541,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1563,7 +1563,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1581,7 +1581,7 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, } }, }, @@ -1610,7 +1610,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1633,7 +1633,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1654,7 +1654,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1677,7 +1677,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1708,7 +1708,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = em2882_kworld_315u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2882_kworld_315u_analog1, @@ -1735,7 +1735,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1758,7 +1758,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1782,7 +1782,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1808,7 +1808,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1834,7 +1834,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1859,7 +1859,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1904,7 +1904,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = kworld_330u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = kworld_330u_analog, @@ -1951,7 +1951,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1970,7 +1970,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1990,7 +1990,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { /* Composite has not been tested yet */ - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_VIDEO, }, { /* S-video has not been tested yet */ @@ -2006,7 +2006,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2023,7 +2023,7 @@ struct em28xx_board em28xx_boards[] = { .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .mute_gpio = terratec_av350_mute_gpio, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AUDIO_SRC_LINE, .gpio = terratec_av350_unmute_gpio, @@ -2041,7 +2041,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2067,7 +2067,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = evga_indtube_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = evga_indtube_analog, @@ -2125,7 +2125,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2238,7 +2238,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .amux = EM28XX_AMUX_VIDEO, .gpio = speedlink_vad_laplace_reg_seq, } }, @@ -2272,7 +2272,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 6a015e8e8655..52428b4cce5f 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1442,16 +1442,11 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", + [EM28XX_RADIO] = "Radio", }; static int vidioc_enum_input(struct file *file, void *priv, @@ -1471,8 +1466,7 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(i->name, iname[INPUT(n)->type]); - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) + if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; i->std = dev->v4l2->vdev.tvnorms; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 8ff066c977d9..b23bf6a64011 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -291,15 +291,9 @@ struct em28xx_dmaqueue { #define MAX_EM28XX_INPUT 4 enum enum28xx_itype { - EM28XX_VMUX_COMPOSITE1 = 1, - EM28XX_VMUX_COMPOSITE2, - EM28XX_VMUX_COMPOSITE3, - EM28XX_VMUX_COMPOSITE4, + EM28XX_VMUX_COMPOSITE = 1, EM28XX_VMUX_SVIDEO, EM28XX_VMUX_TELEVISION, - EM28XX_VMUX_CABLE, - EM28XX_VMUX_DVB, - EM28XX_VMUX_DEBUG, EM28XX_RADIO, }; -- cgit v1.2.3 From 8dfbcc4351a0b6d2f2d77f367552f48ffefafe18 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 09:22:44 -0200 Subject: [media] xc2028: avoid use after free If struct xc2028_config is passed without a firmware name, the following trouble may happen: [11009.907205] xc2028 5-0061: type set to XCeive xc2028/xc3028 tuner [11009.907491] ================================================================== [11009.907750] BUG: KASAN: use-after-free in strcmp+0x96/0xb0 at addr ffff8803bd78ab40 [11009.907992] Read of size 1 by task modprobe/28992 [11009.907994] ============================================================================= [11009.907997] BUG kmalloc-16 (Tainted: G W ): kasan: bad access detected [11009.907999] ----------------------------------------------------------------------------- [11009.908008] INFO: Allocated in xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] age=0 cpu=3 pid=28992 [11009.908012] ___slab_alloc+0x581/0x5b0 [11009.908014] __slab_alloc+0x51/0x90 [11009.908017] __kmalloc+0x27b/0x350 [11009.908022] xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] [11009.908026] usb_hcd_submit_urb+0x1e8/0x1c60 [11009.908029] usb_submit_urb+0xb0e/0x1200 [11009.908032] usb_serial_generic_write_start+0xb6/0x4c0 [11009.908035] usb_serial_generic_write+0x92/0xc0 [11009.908039] usb_console_write+0x38a/0x560 [11009.908045] call_console_drivers.constprop.14+0x1ee/0x2c0 [11009.908051] console_unlock+0x40d/0x900 [11009.908056] vprintk_emit+0x4b4/0x830 [11009.908061] vprintk_default+0x1f/0x30 [11009.908064] printk+0x99/0xb5 [11009.908067] kasan_report_error+0x10a/0x550 [11009.908070] __asan_report_load1_noabort+0x43/0x50 [11009.908074] INFO: Freed in xc2028_set_config+0x90/0x630 [tuner_xc2028] age=1 cpu=3 pid=28992 [11009.908077] __slab_free+0x2ec/0x460 [11009.908080] kfree+0x266/0x280 [11009.908083] xc2028_set_config+0x90/0x630 [tuner_xc2028] [11009.908086] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908090] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908094] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908098] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908101] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908105] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908108] do_one_initcall+0x141/0x300 [11009.908111] do_init_module+0x1d0/0x5ad [11009.908114] load_module+0x6666/0x9ba0 [11009.908117] SyS_finit_module+0x108/0x130 [11009.908120] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908123] INFO: Slab 0xffffea000ef5e280 objects=25 used=25 fp=0x (null) flags=0x2ffff8000004080 [11009.908126] INFO: Object 0xffff8803bd78ab40 @offset=2880 fp=0x0000000000000001 [11009.908130] Bytes b4 ffff8803bd78ab30: 01 00 00 00 2a 07 00 00 9d 28 00 00 01 00 00 00 ....*....(...... [11009.908133] Object ffff8803bd78ab40: 01 00 00 00 00 00 00 00 b0 1d c3 6a 00 88 ff ff ...........j.... [11009.908137] CPU: 3 PID: 28992 Comm: modprobe Tainted: G B W 4.5.0-rc1+ #43 [11009.908140] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [11009.908142] ffff8803bd78a000 ffff8802c273f1b8 ffffffff81932007 ffff8803c6407a80 [11009.908148] ffff8802c273f1e8 ffffffff81556759 ffff8803c6407a80 ffffea000ef5e280 [11009.908153] ffff8803bd78ab40 dffffc0000000000 ffff8802c273f210 ffffffff8155ccb4 [11009.908158] Call Trace: [11009.908162] [] dump_stack+0x4b/0x64 [11009.908165] [] print_trailer+0xf9/0x150 [11009.908168] [] object_err+0x34/0x40 [11009.908171] [] kasan_report_error+0x230/0x550 [11009.908175] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908179] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908182] [] __asan_report_load1_noabort+0x43/0x50 [11009.908185] [] ? __asan_register_globals+0x50/0xa0 [11009.908189] [] ? strcmp+0x96/0xb0 [11009.908192] [] strcmp+0x96/0xb0 [11009.908196] [] xc2028_set_config+0x15c/0x630 [tuner_xc2028] [11009.908200] [] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908203] [] ? memset+0x28/0x30 [11009.908206] [] ? xc2028_set_config+0x630/0x630 [tuner_xc2028] [11009.908211] [] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908215] [] ? em28xx_dvb_init.part.3+0x37c/0x5cf4 [em28xx_dvb] [11009.908219] [] ? hauppauge_hvr930c_init+0x487/0x487 [em28xx_dvb] [11009.908222] [] ? lgdt330x_attach+0x1cc/0x370 [lgdt330x] [11009.908226] [] ? i2c_read_demod_bytes.isra.2+0x210/0x210 [lgdt330x] [11009.908230] [] ? ref_module.part.15+0x10/0x10 [11009.908233] [] ? module_assert_mutex_or_preempt+0x80/0x80 [11009.908238] [] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908242] [] ? em28xx_attach_xc3028.constprop.7+0x30d/0x30d [em28xx_dvb] [11009.908245] [] ? string+0x14d/0x1f0 [11009.908249] [] ? symbol_string+0xff/0x1a0 [11009.908253] [] ? uuid_string+0x6f0/0x6f0 [11009.908257] [] ? __kernel_text_address+0x7e/0xa0 [11009.908260] [] ? print_context_stack+0x7f/0xf0 [11009.908264] [] ? __module_address+0xb6/0x360 [11009.908268] [] ? is_ftrace_trampoline+0x99/0xe0 [11009.908271] [] ? __kernel_text_address+0x7e/0xa0 [11009.908275] [] ? debug_check_no_locks_freed+0x290/0x290 [11009.908278] [] ? dump_trace+0x11b/0x300 [11009.908282] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908285] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908289] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908292] [] ? trace_hardirqs_on+0xd/0x10 [11009.908296] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908299] [] ? mutex_trylock+0x400/0x400 [11009.908302] [] ? do_one_initcall+0x131/0x300 [11009.908306] [] ? call_rcu_sched+0x17/0x20 [11009.908309] [] ? put_object+0x48/0x70 [11009.908314] [] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908317] [] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908320] [] ? 0xffffffffa0150000 [11009.908324] [] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908327] [] do_one_initcall+0x141/0x300 [11009.908330] [] ? try_to_run_init_process+0x40/0x40 [11009.908333] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908337] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908340] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908343] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908346] [] ? __asan_register_globals+0x87/0xa0 [11009.908350] [] do_init_module+0x1d0/0x5ad [11009.908353] [] load_module+0x6666/0x9ba0 [11009.908356] [] ? symbol_put_addr+0x50/0x50 [11009.908361] [] ? em28xx_dvb_init.part.3+0x5989/0x5cf4 [em28xx_dvb] [11009.908366] [] ? module_frob_arch_sections+0x20/0x20 [11009.908369] [] ? open_exec+0x50/0x50 [11009.908374] [] ? ns_capable+0x5b/0xd0 [11009.908377] [] SyS_finit_module+0x108/0x130 [11009.908379] [] ? SyS_init_module+0x1f0/0x1f0 [11009.908383] [] ? lockdep_sys_exit_thunk+0x12/0x14 [11009.908394] [] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908396] Memory state around the buggy address: [11009.908398] ffff8803bd78aa00: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908401] ffff8803bd78aa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908403] >ffff8803bd78ab00: fc fc fc fc fc fc fc fc 00 00 fc fc fc fc fc fc [11009.908405] ^ [11009.908407] ffff8803bd78ab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908409] ffff8803bd78ac00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908411] ================================================================== In order to avoid it, let's set the cached value of the firmware name to NULL after freeing it. While here, return an error if the memory allocation fails. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 4e941f00b600..082ff5608455 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1403,11 +1403,12 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) * in order to avoid troubles during device release. */ kfree(priv->ctrl.fname); + priv->ctrl.fname = NULL; memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); if (priv->ctrl.fname == NULL) - rc = -ENOMEM; + return -ENOMEM; } /* -- cgit v1.2.3 From 163c9bca101caf000691b56fb3834905e62cbba3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 08:39:33 -0200 Subject: [media] tuner.h: rename TUNER_PAD_IF_OUTPUT to TUNER_PAD_OUTPUT The output of a tuner is not only IF frequencies. They may also output audio on some of its pins, and may even be a zero-IF tuner, with outputs a baseband. So, rename the PAD name to make it clearer and add a proper documentation about that at tuner.h. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- drivers/media/v4l2-core/tuner-core.c | 2 +- include/media/tuner.h | 21 ++++++++++++++++++--- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 560450a0b32a..a7de62ebc415 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -661,7 +661,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { ret = media_create_pad_links(mdev, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_IF_OUTPUT, + tuner, TUNER_PAD_OUTPUT, MEDIA_ENT_F_DTV_DEMOD, demod, 0, MEDIA_LNK_FL_ENABLED, false); diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 9e29e70a78d7..df2bc3f732b6 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -276,7 +276,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev) return -EINVAL; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 620b83d03f75..54e43fe13e6d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1259,7 +1259,7 @@ static int cx231xx_create_media_graph(struct cx231xx *dev) return 0; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index b669deccc34c..e7978e4e40ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -888,7 +888,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) state->tuner.function = MEDIA_ENT_F_TUNER; state->tuner.name = "mxl111sf tuner"; state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->tuner_pads[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&state->tuner, TUNER_NUM_PADS, state->tuner_pads); diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 76496fd282aa..a1f858b34187 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -697,7 +697,7 @@ static int tuner_probe(struct i2c_client *client, register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/tuner.h b/include/media/tuner.h index e5321fda5489..c5994fe865a0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -21,11 +21,26 @@ #include -/* Tuner PADs */ -/* FIXME: is this the right place for it? */ +/** + * enum tuner_pad_index - tuner pad index + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, - TUNER_PAD_IF_OUTPUT, + TUNER_PAD_OUTPUT, TUNER_NUM_PADS }; -- cgit v1.2.3 From 6aad127d37b609ca40ee3b93454a58ee6ed5a1ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 06:11:30 -0200 Subject: [media] v4l2-mc.h: move tuner PAD definitions to this new header The customer PC hardware can be shipped with lots of different configurations, as vendors use to replace some of the chips on their hardware along the time. All drivers that support such devices are prepared to handle the hardware differences, using their own auto-probing logic. They do it in a way that number of inputs and outputs for a given hardware type doesn't change. Now that we're adding media controller capabilities to those drivers, we need to standardize the number of inputs and outputs for each hardware type, as we want to have a generic function at the V4L2 core that would create the links for the entities that are expected on such hardware. Such standard is already there for tuners, but tuner.h is not the best place to store such data, as we'll need to add definitions also for analog TV demodulators. Also, we'll need a place to put a set of MC handling functions. So, let's create a v4l2-mc.h to store such kind of definitions. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/device-drivers.tmpl | 1 + include/media/tuner.h | 24 +------------------ include/media/v4l2-mc.h | 38 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 include/media/v4l2-mc.h diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index cdd8b24db68d..cc303a2f641c 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -229,6 +229,7 @@ X!Isound/sound_firmware.c !Iinclude/media/v4l2-dv-timings.h !Iinclude/media/v4l2-event.h !Iinclude/media/v4l2-flash-led-class.h +!Iinclude/media/v4l2-mc.h !Iinclude/media/v4l2-mediabus.h !Iinclude/media/v4l2-mem2mem.h !Iinclude/media/v4l2-of.h diff --git a/include/media/tuner.h b/include/media/tuner.h index c5994fe865a0..b3edc14e763f 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -20,29 +20,7 @@ #ifdef __KERNEL__ #include - -/** - * enum tuner_pad_index - tuner pad index - * - * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a - * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. - * @TUNER_NUM_PADS: Number of pads of the tuner. - */ -enum tuner_pad_index { - TUNER_PAD_RF_INPUT, - TUNER_PAD_OUTPUT, - TUNER_NUM_PADS -}; +#include #define ADDR_UNSET (255) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h new file mode 100644 index 000000000000..f6fcd70f3548 --- /dev/null +++ b/include/media/v4l2-mc.h @@ -0,0 +1,38 @@ +/* + * v4l2-mc.h - Media Controller V4L2 types and prototypes + * + * Copyright (C) 2016 Mauro Carvalho Chehab + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/** + * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ +enum tuner_pad_index { + TUNER_PAD_RF_INPUT, + TUNER_PAD_OUTPUT, + TUNER_NUM_PADS +}; \ No newline at end of file -- cgit v1.2.3 From 5c9077eabc9a0ffbd4c8b0724ddcd69ef2b1a7ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:08 -0200 Subject: [media] v4l2-mc.h: Split audio from baseband output Analog TV tuners have a separate output pad for the audio IF or audio sampled data. This pad is connected to a different chipset. Add an extra pad for it and improve the documentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 1 + include/media/v4l2-mc.h | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index a1f858b34187..d6bd9ce1101d 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -698,6 +698,7 @@ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index f6fcd70f3548..c174e5b4f188 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -19,20 +19,26 @@ * * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. + * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video + * chrominance and luminance or the hole bandwidth + * of the signal converted to an Intermediate Frequency + * (IF) or to baseband (on zero-IF tuners). + * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode + * analog TV signals have an extra pad for audio output. + * Old tuners use an analog stage with a saw filter for + * the audio IF frequency. The output of the pad is, in + * this case, the audio IF, with should be decoded either + * by the bridge chipset (that's the case of cx2388x + * chipsets) or may require an external IF sound + * processor, like msp34xx. On modern silicon tuners, + * the audio IF decoder is usually incorporated at the + * tuner. On such case, the output of this pad is an + * audio sampled data. * @TUNER_NUM_PADS: Number of pads of the tuner. */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, TUNER_PAD_OUTPUT, + TUNER_PAD_AUD_OUT, TUNER_NUM_PADS -}; \ No newline at end of file +}; -- cgit v1.2.3 From 06131932c1d5f1bd09832f42be658906a27749fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 07:28:08 -0200 Subject: [media] media.h: add support for IF-PLL video/sound decoder Very old hardware may have an analog stage tuner. Those hardware consists of a PLL that converts a RF signal into IF signals. Depending on the hardware, those video IF signal can be decoded directly by the bridge chipset. Most Conexant chips (bt8x8, cx2388x, etc) have internally the decoders for that. Yet, even on such hardware, the tuner may have internally its own TV multi-standard decoder like tda9887. The same happens with the audio IF signal, where some bridges are capable of receiving it, while others require an external IF-PLL sound decoder, like msp3400. Those external IF-PLL audio and video decoders have their own I2C address, and use different drivers to handle them. So, they're mapped as different subdevices on Linux. Thankfully, all modern hardware comes with an IC chip that has both the RF and the IF stages on it, being capable of decoding audio and video IF signals internally. Yet, as we need to support drivers that can work with either analog or silicon tuners, we need to add two entity types for those old hardware. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 29 ++++++++++++++++++++++++- include/uapi/linux/media.h | 17 +++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 1af384250910..751c3d027103 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -84,7 +84,34 @@ MEDIA_ENT_F_TUNER - Digital TV, analog TV, radio and/or software radio tuner. + Digital TV, analog TV, radio and/or software radio tuner, + with consists on a PLL tuning stage that converts radio + frequency (RF) signal into an Intermediate Frequency (IF). + Modern tuners have internally IF-PLL decoders for audio + and video, but older models have those stages implemented + on separate entities. + + + + MEDIA_ENT_F_IF_VID_DECODER + IF-PLL video decoder. It receives the IF from a PLL + and decodes the analog TV video signal. This is commonly + found on some very old analog tuners, like Philips MK3 + designs. They all contain a tda9887 (or some software + compatible similar chip, like tda9885). Those devices + use a different I2C address than the tuner PLL. + + + + MEDIA_ENT_F_IF_AUD_DECODER + IF-PLL sound decoder. It receives the IF from a PLL + and decodes the analog TV audio signal. This is commonly + found on some very old analog hardware, like Micronas + msp3400, Philips tda9840, tda985x, etc. Those devices + use a different I2C address than the tuner PLL and + should be controlled together with the IF-PLL video + decoder. + diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 5dbb208e5451..c9eb42a6c021 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -88,6 +88,15 @@ struct media_device_info { #define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) #define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) +/* + * Analog TV IF-PLL decoders + * + * It is a responsibility of the master/bridge drivers to create links + * for MEDIA_ENT_F_IF_VID_DECODER and MEDIA_ENT_F_IF_AUD_DECODER. + */ +#define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 41) +#define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 42) + /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility @@ -107,8 +116,12 @@ struct media_device_info { #define MEDIA_ENT_F_LENS (MEDIA_ENT_F_OLD_SUBDEV_BASE + 3) #define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4) /* - * It is a responsibility of the entity drivers to add connectors and links - * for the tuner entities. + * It is a responsibility of the master/bridge drivers to add connectors + * and links for MEDIA_ENT_F_TUNER. Please notice that some old tuners + * may require the usage of separate I2C chips to decode analog TV signals, + * when the master/bridge chipset doesn't have its own TV standard decoder. + * On such cases, the IF-PLL staging is mapped via one or two entities: + * MEDIA_ENT_F_IF_VID_DECODER and/or MEDIA_ENT_F_IF_AUD_DECODER. */ #define MEDIA_ENT_F_TUNER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 5) -- cgit v1.2.3 From 953a457e50958494cfa90b41a13c26e9fb04195c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:37 -0200 Subject: [media] v4l2-mc.h Add pads for audio and video IF-PLL decoders The audio and video IF-PLL decoders have one sink and one source PAD. Add macro names for those pads and describe what kind of signals are represented at such pads. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 27 +++++++++++++++++++++------ include/media/v4l2-mc.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index d6bd9ce1101d..731487be5baa 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -696,17 +696,32 @@ static int tuner_probe(struct i2c_client *client, /* Should be just before return */ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) - t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; - t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; - t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; + /* + * Handle the special case where the tuner has actually + * two stages: the PLL to tune into a frequency and the + * IF-PLL demodulator (tda988x). + */ + if (t->type == TUNER_TDA9887) { + t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, + IF_VID_DEC_PAD_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER; + } else { + t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_TUNER; + } - ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); if (ret < 0) { tuner_err("failed to initialize media entity!\n"); kfree(t); - return -ENODEV; + return ret; } #endif /* Sets a default mode */ diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index c174e5b4f188..6a6ef5bc767e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -42,3 +42,35 @@ enum tuner_pad_index { TUNER_PAD_AUD_OUT, TUNER_NUM_PADS }; + +/** + * enum if_vid_dec_index - video IF-PLL pad index for + * MEDIA_ENT_F_IF_VID_DECODER + * + * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad + * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the + * video chrominance and luminance IF signals. + * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL. + */ +enum if_vid_dec_pad_index { + IF_VID_DEC_PAD_IF_INPUT, + IF_VID_DEC_PAD_OUT, + IF_VID_DEC_PAD_NUM_PADS +}; + +/** + * enum if_aud_dec_index - audio/sound IF-PLL pad index for + * MEDIA_ENT_F_IF_AUD_DECODER + * + * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad + * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the + * audio sampled stream data, usually connected + * to the bridge bus via an Inter-IC Sound (I2S) + * bus. + * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL. + */ +enum if_aud_dec_pad_index { + IF_AUD_DEC_PAD_IF_INPUT, + IF_AUD_DEC_PAD_OUT, + IF_AUD_DEC_PAD_NUM_PADS +}; -- cgit v1.2.3 From e4001e955bec5566848624635cfb2d353ebac507 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:57 -0200 Subject: [media] v4l2-mc: add analog TV demodulator pad index macros We also need to standardize the PAD index macros for demods, as they all should look the same in a media graph. Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 6a6ef5bc767e..df115195690e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -74,3 +74,18 @@ enum if_aud_dec_pad_index { IF_AUD_DEC_PAD_OUT, IF_AUD_DEC_PAD_NUM_PADS }; + +/** + * enum demod_pad_index - analog TV pad index for MEDIA_ENT_F_ATV_DECODER + * + * @DEMOD_PAD_IF_INPUT: IF input sink pad. + * @DEMOD_PAD_VID_OUT: Video output source pad. + * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad. + * @DEMOD_NUM_PADS: Maximum number of output pads. + */ +enum demod_pad_index { + DEMOD_PAD_IF_INPUT, + DEMOD_PAD_VID_OUT, + DEMOD_PAD_VBI_OUT, + DEMOD_NUM_PADS +}; -- cgit v1.2.3 From 55606310e77f5099d01b59ea9a25401f521c5713 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 12:08:13 -0200 Subject: [media] tvp5150: create the expected number of pads The tvp5150 doesn't have just one pad. It has 3 ones: - IF input - Video output - VBI output Fix it and use the macros for the pad indexes. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 0ad122fcd632..20428f052506 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -37,7 +38,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; - struct media_pad pad; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -1313,8 +1316,10 @@ static int tvp5150_probe(struct i2c_client *c, sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #if defined(CONFIG_MEDIA_CONTROLLER) - core->pad.flags = MEDIA_PAD_FL_SOURCE; - res = media_entity_pads_init(&sd->entity, 1, &core->pad); + core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; #endif -- cgit v1.2.3 From fb4932821731f58353d23f6673b55a9612a1cb57 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 08:51:01 -0200 Subject: [media] msp3400: initialize MC data Add pads and set the device type when used with the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.c | 14 ++++++++++++++ drivers/media/i2c/msp3400-driver.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index a84561d0d4a8..e016626ebf89 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -688,6 +688,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) int msp_revision; int msp_product, msp_prod_hi, msp_prod_lo; int msp_rom; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif if (!id) strlcpy(client->name, "msp3400", sizeof(client->name)); @@ -704,6 +707,17 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &msp_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER; + + ret = media_entity_pads_init(&sd->entity, 2, state->pads); + if (ret < 0) + return ret; +#endif + state->v4l2_std = V4L2_STD_NTSC; state->detected_std = V4L2_STD_ALL; state->audmode = V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index 6cae21366ed5..f0bb37dc9013 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -7,6 +7,7 @@ #include #include #include +#include /* ---------------------------------------------------------------------- */ @@ -102,6 +103,10 @@ struct msp_state { wait_queue_head_t wq; unsigned int restart:1; unsigned int watch_stereo:1; + +#if CONFIG_MEDIA_CONTROLLER + struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; +#endif }; static inline struct msp_state *to_state(struct v4l2_subdev *sd) -- cgit v1.2.3 From f92c70ad28341b6430c64332521428768058dd17 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 15:09:15 -0200 Subject: [media] tvp5150: identify it as a MEDIA_ENT_F_ATV_DECODER The tvp5150 is an analog TV decoder. Identify as such at the media graph, or otherwise devices using it would fail. That avoids the following warning: [ 1546.669139] usb 2-3.3: Entity type for entity tvp5150 5-005c was not initialized! Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 20428f052506..19b52736b24e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1319,6 +1319,9 @@ static int tvp5150_probe(struct i2c_client *c, core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; -- cgit v1.2.3 From af7d374a4cf715d7b7f535bcc30d814faf6a5cf6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 08:44:28 -0200 Subject: [media] saa7115: initialize demod type and add the needed pads The saa7115 driver is used on several em28xx-based devices. Now that we're about to add MC support to em28xx, we need to be sure that the saa711x demod will be properly mapped at MC. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 24d2b76dbe97..d2a1ce2bc7f5 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,9 @@ enum saa711x_model { struct saa711x_state { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct { @@ -1809,6 +1813,9 @@ static int saa711x_probe(struct i2c_client *client, struct saa7115_platform_data *pdata; int ident; char name[CHIP_VER_SIZE + 1]; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1832,6 +1839,18 @@ static int saa711x_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa711x_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + + ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads); + if (ret < 0) + return ret; +#endif + v4l_info(client, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); hdl = &state->hdl; -- cgit v1.2.3 From 56a7f51554b22729cee87042ea697a0d59b13d6b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 13:08:19 -0200 Subject: [media] em28xx: unregister devices in case of failure If something bad happens during device registration, unregister the already registered devices. Without that, it will have lots of KASAN errors when udev would try to open the devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 52428b4cce5f..8c87f3fbd0cf 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2579,6 +2579,22 @@ static int em28xx_v4l2_init(struct em28xx *dev) return 0; unregister_dev: + if (video_is_registered(&v4l2->radio_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->radio_dev)); + video_unregister_device(&v4l2->radio_dev); + } + if (video_is_registered(&v4l2->vbi_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vbi_dev)); + video_unregister_device(&v4l2->vbi_dev); + } + if (video_is_registered(&v4l2->vdev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vdev)); + video_unregister_device(&v4l2->vdev); + } + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); v4l2_device_unregister(&v4l2->v4l2_dev); err: -- cgit v1.2.3 From 41a5e7ea7d25f207e5d1c71c9cfe5c07aa5fd055 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 10:11:57 -0200 Subject: [media] em28xx: fix tuner detection for Pixelview Prolink PlayTV USB 2.0 The tuner is at address 0x60. This address is not probed by default by tuner anymore, so we need to explicitly add it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ab0fe0319991..2001c9c14784 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -1555,6 +1555,7 @@ struct em28xx_board em28xx_boards[] = { .buttons = std_snapshot_button, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, + .tuner_addr = 0x60, .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, -- cgit v1.2.3 From 22580f7cb9dfc11db233f48a5e257566f508f5c3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 12:53:56 -0200 Subject: [media] em28xx: make sure that the device has video There are some devices, like Terratec Cinergy HTC, where while the device supports analog TV, the driver is not capable yet of handling it, because the analog TV driver was not written. So, don't bind the em28xx-v4l drivers on such devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 2001c9c14784..ec4e95119877 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3468,7 +3468,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); - /* allocate device struct */ + /* allocate device struct and check if the device is a webcam */ mutex_init(&dev->lock); retval = em28xx_init_dev(dev, udev, interface, nr); if (retval) { @@ -3484,6 +3484,15 @@ static int em28xx_usb_probe(struct usb_interface *interface, try_bulk = usb_xfer_mode > 0; } + /* Disable V4L2 if the device doesn't have a decoder */ + if (has_video && + dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) { + printk(DRIVER_NAME + ": Currently, V4L2 is not supported on this model\n"); + has_video = false; + dev->has_video = false; + } + /* Select USB transfer types to use */ if (has_video) { if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) -- cgit v1.2.3 From 0962a763327bd33fd18c3a4d0a613cad0976a930 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:05:11 -0200 Subject: [media] em28xx: avoid divide by zero error [ 1841.243670] divide error: 0000 [#1] SMP KASAN [ 1841.243994] Modules linked in: em28xx_rc rc_core tda18271 drxk em28xx_dvb dvb_core em28xx_alsa mt9v011 em28xx_v4l videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core em28xx tveeprom v4l2_common videodev media cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats parport_pc ppdev lp parport snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm iTCO_wdt iTCO_vendor_support irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel sha256_ssse3 sha256_generic hmac drbg i915 snd_hda_codec_realtek snd_hda_codec_generic aesni_intel aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd btusb i2c_algo_bit snd_hda_intel btrtl drm_kms_helper btbcm evdev snd_hda_codec btintel psmouse bluetooth pcspkr snd_hwdep sg drm serio_raw [ 1841.244845] snd_hda_core snd_pcm mei_me rfkill snd_timer mei snd lpc_ich soundcore shpchp i2c_i801 mfd_core battery dw_dmac i2c_designware_platform i2c_designware_core dw_dmac_core video acpi_pad button tpm_tis tpm ext4 crc16 mbcache jbd2 dm_mod hid_generic usbhid sd_mod ahci libahci libata ehci_pci e1000e xhci_pci ptp scsi_mod ehci_hcd xhci_hcd pps_core fan thermal sdhci_acpi sdhci mmc_core i2c_hid hid [last unloaded: tveeprom] [ 1841.245342] CPU: 2 PID: 38 Comm: kworker/2:1 Tainted: G W 4.5.0-rc1+ #43 [ 1841.245413] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [ 1841.245503] Workqueue: events request_module_async [em28xx] [ 1841.245557] task: ffff88009df10000 ti: ffff88009df18000 task.ti: ffff88009df18000 [ 1841.245626] RIP: 0010:[] [] size_to_scale+0xed/0x2c0 [em28xx_v4l] [ 1841.245714] RSP: 0018:ffff88009df1faa8 EFLAGS: 00010246 [ 1841.245756] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff8803bb933b38 [ 1841.245815] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8803bb933b00 [ 1841.245879] RBP: ffff88009df1fad8 R08: ffff8803bb933b3c R09: 1ffff10077726760 [ 1841.245944] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 1841.246006] R13: 0000000000000000 R14: dffffc0000000000 R15: ffff8803b391a130 [ 1841.246071] FS: 0000000000000000(0000) GS:ffff8803c6900000(0000) knlGS:0000000000000000 [ 1841.246141] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1841.246194] CR2: 0000000001d97008 CR3: 00000003bdd85000 CR4: 00000000003406e0 [ 1841.246256] Stack: [ 1841.246278] 0000000000000246 ffff8803bb9321f0 ffff8803bb932270 ffffffffa136f7a0 [ 1841.246359] 0000000000000000 ffff8803bb932130 ffff88009df1fb20 ffffffffa13646a0 [ 1841.246439] ffffffffa127f206 ffff8803bb932130 ffff8803bb932130 ffff8803b391a130 [ 1841.246517] Call Trace: [ 1841.246548] [] em28xx_set_video_format+0x140/0x1e0 [em28xx_v4l] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 8c87f3fbd0cf..86db1e1f8ab5 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1232,6 +1232,12 @@ static void scale_to_size(struct em28xx *dev, *width = (((unsigned long)maxw) << 12) / (hscale + 4096L); *height = (((unsigned long)maxh) << 12) / (vscale + 4096L); + + /* Don't let width or height to be zero */ + if (*width < 1) + *width = 1; + if (*height < 1) + *height = 1; } /* ------------------------------------------------------------------ @@ -1307,6 +1313,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); } + /* Avoid division by zero at size_to_scale */ + if (width < 1) + width = 1; + if (height < 1) + height = 1; size_to_scale(dev, width, height, &hscale, &vscale); scale_to_size(dev, hscale, vscale, &width, &height); -- cgit v1.2.3 From ac88fce987bd3433706b1082e8a85408de63512c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:33:12 -0200 Subject: [media] mt9v011: add media controller support Create a source pad and set the media controller type to the sensor. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v011.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index b9fea11d6b0b..9ed1b26b6549 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -50,6 +50,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct mt9v011 { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pad; +#endif struct v4l2_ctrl_handler ctrls; unsigned width, height; unsigned xtal; @@ -493,6 +496,9 @@ static int mt9v011_probe(struct i2c_client *c, u16 version; struct mt9v011 *core; struct v4l2_subdev *sd; +#ifdef CONFIG_MEDIA_CONTROLLER + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -506,6 +512,15 @@ static int mt9v011_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); +#ifdef CONFIG_MEDIA_CONTROLLER + core->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + + ret = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (ret < 0) + return ret; +#endif + /* Check if the sensor is really a MT9V011 */ version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); if ((version != MT9V011_VERSION) && -- cgit v1.2.3 From 37ecc7b1278f4184a6869504f7074b4a54f112c5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 07:07:24 -0200 Subject: [media] em28xx: add media controller support Add the needed bits to make em28xx to create a media controller graph. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-camera.c | 4 + drivers/media/usb/em28xx/em28xx-cards.c | 55 +++++- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ++ drivers/media/usb/em28xx/em28xx-video.c | 294 ++++++++++++++++++++++++++++++- drivers/media/usb/em28xx/em28xx.h | 13 +- 5 files changed, 366 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index b58acd3fcd99..72f3f4d50253 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -64,6 +64,8 @@ static int em28xx_initialize_mt9m111(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } @@ -91,6 +93,8 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ec4e95119877..ba442c967415 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3013,6 +3013,48 @@ static void flush_request_modules(struct em28xx *dev) flush_work(&dev->request_module_wk); } +static int em28xx_media_device_init(struct em28xx *dev, + struct usb_device *udev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mdev->dev = &udev->dev; + + if (!dev->name) + strlcpy(mdev->model, "unknown em28xx", sizeof(mdev->model)); + else + strlcpy(mdev->model, dev->name, sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + strcpy(mdev->bus_info, udev->devpath); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + dev->media_dev = mdev; +#endif + return 0; +} + +static void em28xx_unregister_media_device(struct em28xx *dev) +{ + +#ifdef CONFIG_MEDIA_CONTROLLER + if (dev->media_dev) { + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; + } +#endif +} + /* * em28xx_release_resources() * unregisters the v4l2,i2c and usb devices @@ -3024,6 +3066,8 @@ static void em28xx_release_resources(struct em28xx *dev) mutex_lock(&dev->lock); + em28xx_unregister_media_device(dev); + if (dev->def_i2c_bus) em28xx_i2c_unregister(dev, 1); em28xx_i2c_unregister(dev, 0); @@ -3168,6 +3212,8 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, */ snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno); + em28xx_media_device_init(dev, udev); + if (dev->is_audio_only) { retval = em28xx_audio_setup(dev); if (retval) @@ -3511,9 +3557,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, request_modules(dev); - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it + /* + * Do it at the end, to reduce dynamic configuration changes during + * the device init. Yet, as request_modules() can be async, the + * topology will likely change after the load of the em28xx subdrivers. */ +#ifdef CONFIG_MEDIA_CONTROLLER + retval = media_device_register(dev->media_dev); +#endif return 0; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index bf5c24467c65..ea80541d58f0 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -916,6 +916,9 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, dev->name, result); goto fail_adapter; } +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + dvb->adapter.mdev = dev->media_dev; +#endif /* Ensure all frontends negotiate bus access */ dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; @@ -994,8 +997,15 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + + result = dvb_create_media_graph(&dvb->adapter, false); + if (result < 0) + goto fail_create_graph; + return 0; +fail_create_graph: + dvb_net_release(&dvb->net); fail_fe_conn: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); fail_fe_mem: diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 86db1e1f8ab5..16a2d4039330 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -866,6 +866,275 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type) em28xx_videodbg("res: put %d\n", res_type); } +static void em28xx_v4l2_media_release(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + if (!INPUT(i)->type) + return; + media_device_unregister_entity(&dev->input_ent[i]); + } +#endif +} + +/* + * Media Controller helper functions + */ + +static int em28xx_v4l2_create_media_graph(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + int i, ret; + + if (!mdev) + return 0; + + /* Webcams are really simple */ + if (dev->board.is_webcam) { + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + return 0; + } + + /* Non-webcams have analog TV decoder and other complexities */ + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + /* Something bad happened! */ + if (!decoder) + return -EINVAL; + + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + if (em28xx_vbi_supported(dev)) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + &v4l2->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + case EM28XX_VMUX_SVIDEO: + ret = media_create_pad_link(ent, 0, decoder, + DEMOD_PAD_IF_INPUT, 0); + if (ret) + return ret; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + if (!tuner) + break; + + ret = media_create_pad_link(ent, 0, tuner, + TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + break; + } + } +#endif + return 0; +} + +static int em28xx_enable_analog_tuner(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_entity *source; + struct media_link *link, *found_link = NULL; + int ret, active_links = 0; + + if (!mdev || !v4l2->decoder) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + list_for_each_entry(link, &v4l2->decoder->links, list) { + if (link->sink->entity == v4l2->decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + list_for_each_entry(link, &source->links, list) { + struct media_entity *sink; + int flags = 0; + + sink = link->sink->entity; + + if (sink == v4l2->decoder) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + pr_err("Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } else + em28xx_videodbg("link %s->%s was %s\n", + source->name, sink->name, + flags ? "ENABLED" : "disabled"); + } +#endif + return 0; +} + +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", + [EM28XX_VMUX_TELEVISION] = "Television", + [EM28XX_RADIO] = "Radio", +}; + +static void em28xx_v4l2_create_entities(struct em28xx *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + struct em28xx_v4l2 *v4l2 = dev->v4l2; + int ret, i; + + /* Initialize Video, VBI and Radio pads */ + v4l2->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad); + if (ret < 0) + pr_err("failed to initialize video media entity!\n"); + + if (em28xx_vbi_supported(dev)) { + v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1, + &v4l2->vbi_pad); + if (ret < 0) + pr_err("failed to initialize vbi media entity!\n"); + } + + /* Webcams don't have input connectors */ + if (dev->board.is_webcam) + return; + + /* Create entities for each input connector */ + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + ent->name = iname[INPUT(i)->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case EM28XX_VMUX_SVIDEO: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + + /* ------------------------------------------------------------------ Videobuf2 operations ------------------------------------------------------------------*/ @@ -883,6 +1152,9 @@ static int queue_setup(struct vb2_queue *vq, return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; + + em28xx_enable_analog_tuner(dev); + return 0; } @@ -1453,13 +1725,6 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char * const iname[] = { - [EM28XX_VMUX_COMPOSITE] = "Composite", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_RADIO] = "Radio", -}; - static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1974,6 +2239,8 @@ static int em28xx_v4l2_fini(struct em28xx *dev) em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); + em28xx_v4l2_media_release(dev); + if (video_is_registered(&v4l2->radio_dev)) { em28xx_info("V4L2 device %s deregistered\n", video_device_node_name(&v4l2->radio_dev)); @@ -2297,6 +2564,9 @@ static int em28xx_v4l2_init(struct em28xx *dev) v4l2->dev = dev; dev->v4l2 = v4l2; +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2->v4l2_dev.mdev = dev->media_dev; +#endif ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev); if (ret < 0) { em28xx_errdev("Call to v4l2_device_register() failed!\n"); @@ -2569,6 +2839,16 @@ static int em28xx_v4l2_init(struct em28xx *dev) video_device_node_name(&v4l2->radio_dev)); } + /* Init entities at the Media Controller */ + em28xx_v4l2_create_entities(dev); + + ret = em28xx_v4l2_create_media_graph(dev); + if (ret) { + em28xx_errdev("failed to create media graph\n"); + em28xx_v4l2_media_release(dev); + goto unregister_dev; + } + em28xx_info("V4L2 video device registered as %s\n", video_device_node_name(&v4l2->vdev)); diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index b23bf6a64011..267444961775 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -26,7 +26,7 @@ #ifndef _EM28XX_H #define _EM28XX_H -#define EM28XX_VERSION "0.2.1" +#define EM28XX_VERSION "0.2.2" #define DRIVER_DESC "Empia em28xx device driver" #include @@ -552,6 +552,11 @@ struct em28xx_v4l2 { bool top_field; int vbi_read; unsigned int field_count; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad video_pad, vbi_pad; + struct media_entity *decoder; +#endif }; struct em28xx_audio { @@ -712,6 +717,12 @@ struct em28xx { /* Snapshot button input device */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *media_dev; + struct media_entity input_ent[MAX_EM28XX_INPUT]; + struct media_pad input_pad[MAX_EM28XX_INPUT]; +#endif }; #define kref_to_dev(d) container_of(d, struct em28xx, ref) -- cgit v1.2.3 From 242c5033508991221d787043b734740770c850be Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:34:26 -0200 Subject: [media] constify stv6110x_devctl structure The stv6110x_devctl structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stv6110x.c | 4 ++-- drivers/media/dvb-frontends/stv6110x.h | 4 ++-- drivers/media/dvb-frontends/stv6110x_priv.h | 2 +- drivers/media/pci/ddbridge/ddbridge-core.c | 2 +- drivers/media/pci/ngene/ngene-cards.c | 2 +- drivers/media/pci/ttpci/budget.c | 4 ++-- drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c | 2 +- drivers/media/usb/dvb-usb/technisat-usb2.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index e66154e5c1d7..a62c01e454f5 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -355,7 +355,7 @@ static struct dvb_tuner_ops stv6110x_ops = { .release = stv6110x_release }; -static struct stv6110x_devctl stv6110x_ctl = { +static const struct stv6110x_devctl stv6110x_ctl = { .tuner_init = stv6110x_init, .tuner_sleep = stv6110x_sleep, .tuner_set_mode = stv6110x_set_mode, @@ -369,7 +369,7 @@ static struct stv6110x_devctl stv6110x_ctl = { .tuner_get_status = stv6110x_get_status, }; -struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x.h b/drivers/media/dvb-frontends/stv6110x.h index 9f7eb251aec3..696b6e5b9e7b 100644 --- a/drivers/media/dvb-frontends/stv6110x.h +++ b/drivers/media/dvb-frontends/stv6110x.h @@ -55,12 +55,12 @@ struct stv6110x_devctl { #if IS_REACHABLE(CONFIG_DVB_STV6110x) -extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +extern const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c); #else -static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +static inline const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x_priv.h b/drivers/media/dvb-frontends/stv6110x_priv.h index 0ec936a660a7..a993aba27b7e 100644 --- a/drivers/media/dvb-frontends/stv6110x_priv.h +++ b/drivers/media/dvb-frontends/stv6110x_priv.h @@ -70,7 +70,7 @@ struct stv6110x_state { const struct stv6110x_config *config; u8 regs[8]; - struct stv6110x_devctl *devctl; + const struct stv6110x_devctl *devctl; }; #endif /* __STV6110x_PRIV_H */ diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 9d5b314142f1..6e995ef8c37e 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -690,7 +690,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; struct stv6110x_config *tunerconf = (input->nr & 1) ? &stv6110b : &stv6110a; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); if (!ctl) { diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index 039bed3cc919..4e783a68bf4a 100644 --- a/drivers/media/pci/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -57,7 +57,7 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) chan->dev->card_info->fe_config[chan->number]; struct stv6110x_config *tunerconf = (struct stv6110x_config *) chan->dev->card_info->tuner_config[chan->number]; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ if (chan->number < 2) diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index de54310a2660..9f48100227f1 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -644,7 +644,7 @@ static void frontend_init(struct budget *budget) } case 0x101c: { /* TT S2-1600 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); @@ -697,7 +697,7 @@ static void frontend_init(struct budget *budget) break; case 0x1020: { /* Omicom S2 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c index 69d7fe4471c2..2c0015b1264d 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c @@ -118,7 +118,7 @@ int c8sectpfe_frontend_attach(struct dvb_frontend **fe, struct channel_info *tsin, int chan_num) { struct tda18212_config *tda18212; - struct stv6110x_devctl *fe2; + const struct stv6110x_devctl *fe2; struct i2c_client *client; struct i2c_board_info tda18212_info = { .type = "tda18212", diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 6c3c47722955..51487d2f7764 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -512,7 +512,7 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) &a->dev->i2c_adap, STV090x_DEMODULATOR_0); if (a->fe_adap[0].fe) { - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, a->fe_adap[0].fe, -- cgit v1.2.3 From f691ba9864ad0ed1bd67ad27ed95ed2dce6e15e2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:51:38 -0200 Subject: [media] drivers/media/usb/as102: constify as102_priv_ops_t structure The as102_priv_ops_t structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/as102/as102_drv.h | 2 +- drivers/media/usb/as102/as102_usb_drv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/as102/as102_drv.h b/drivers/media/usb/as102/as102_drv.h index aee2d76e8dfc..8def19d9ab92 100644 --- a/drivers/media/usb/as102/as102_drv.h +++ b/drivers/media/usb/as102/as102_drv.h @@ -52,7 +52,7 @@ struct as10x_bus_adapter_t { struct as10x_cmd_t *cmd, *rsp; /* bus adapter private ops callback */ - struct as102_priv_ops_t *ops; + const struct as102_priv_ops_t *ops; }; struct as102_dev_t { diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c index 3f669066ccf6..0e8030c071b8 100644 --- a/drivers/media/usb/as102/as102_usb_drv.c +++ b/drivers/media/usb/as102/as102_usb_drv.c @@ -189,7 +189,7 @@ static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap, return actual_len; } -static struct as102_priv_ops_t as102_priv_ops = { +static const struct as102_priv_ops_t as102_priv_ops = { .upload_fw_pkt = as102_send_ep1, .xfer_cmd = as102_usb_xfer_cmd, .as102_read_ep2 = as102_read_ep2, -- cgit v1.2.3 From 9637b03251dea31d99c0742932b9fcbfa015e5f0 Mon Sep 17 00:00:00 2001 From: "Wu, Xia" Date: Wed, 9 Dec 2015 05:26:26 -0200 Subject: [media] media: videobuf2-core: Fix one __qbuf_dmabuf() error path Add dma_buf_put() to decrease refcount of the dmabuf in error path if DMABUF size is smaller than the requirement. Signed-off-by: wu xia Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c5d49d7a0d76..ec5b78ee6e72 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1220,6 +1220,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) if (planes[plane].length < vb->planes[plane].min_length) { dprintk(1, "invalid dmabuf length for plane %d\n", plane); + dma_buf_put(dbuf); ret = -EINVAL; goto err; } -- cgit v1.2.3 From 2874bf3ec453f50cfe1f7bf000efdadeb6f30db6 Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 12:00:31 -0200 Subject: [media] tc358743: Print timings only when debug level is set Prevent unnecessary kernel log spamming. Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 3397eb99c67b..0325f7ed45d9 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -859,15 +859,16 @@ static void tc358743_format_change(struct v4l2_subdev *sd) if (tc358743_get_detected_timings(sd, &timings)) { enable_stream(sd, false); - v4l2_dbg(1, debug, sd, "%s: Format changed. No signal\n", + v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); } else { if (!v4l2_match_dv_timings(&state->timings, &timings, 0, false)) enable_stream(sd, false); - v4l2_print_dv_timings(sd->name, - "tc358743_format_change: Format changed. New format: ", - &timings, false); + if (debug) + v4l2_print_dv_timings(sd->name, + "tc358743_format_change: New format: ", + &timings, false); } if (sd->devnode) -- cgit v1.2.3 From ff880348e74e0fd1196ab39ec765f5fd330ed3c6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 11 Dec 2015 14:16:48 -0200 Subject: [media] go7007: constify go7007_hpi_ops structures The go7007_hpi_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-go7007.c | 2 +- drivers/media/usb/go7007/go7007-priv.h | 2 +- drivers/media/usb/go7007/go7007-usb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index 8a2abb34186b..2799538e2d7e 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -378,7 +378,7 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len) return 0; } -static struct go7007_hpi_ops saa7134_go7007_hpi_ops = { +static const struct go7007_hpi_ops saa7134_go7007_hpi_ops = { .interface_reset = saa7134_go7007_interface_reset, .write_interrupt = saa7134_go7007_write_interrupt, .read_interrupt = saa7134_go7007_read_interrupt, diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h index 745185eb060b..bebee8ca9981 100644 --- a/drivers/media/usb/go7007/go7007-priv.h +++ b/drivers/media/usb/go7007/go7007-priv.h @@ -250,7 +250,7 @@ struct go7007 { struct i2c_adapter i2c_adapter; /* HPI driver */ - struct go7007_hpi_ops *hpi_ops; + const struct go7007_hpi_ops *hpi_ops; void *hpi_context; int interrupt_available; wait_queue_head_t interrupt_waitq; diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index 3dbf14c85c5c..14d3f8c1ce4a 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -932,7 +932,7 @@ static void go7007_usb_release(struct go7007 *go) kfree(go->hpi_context); } -static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_ezusb_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, @@ -942,7 +942,7 @@ static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .release = go7007_usb_release, }; -static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_onboard_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, -- cgit v1.2.3 From 9f1830206d5e2c6fc85185de4d22c5188ff00232 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 14 Dec 2015 08:17:00 -0200 Subject: [media] saa7134: add DMABUF support Since saa7134 is now using vb2, there is no reason why we can't support dmabuf for this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-empress.c | 3 ++- drivers/media/pci/saa7134/saa7134-video.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 56b932c97196..ca417a454d67 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -189,6 +189,7 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .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, .vidioc_g_frequency = saa7134_g_frequency, @@ -286,7 +287,7 @@ static int empress_init(struct saa7134_dev *dev) * transfers that do not start at the beginning of a page. A USERPTR * can start anywhere in a page, so USERPTR support is a no-go. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; q->drv_priv = &dev->ts_q; q->ops = &saa7134_empress_qops; q->gfp_flags = GFP_DMA32; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index a63c1366a64e..7a42d3ae3ac9 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1906,6 +1906,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_s_std = saa7134_s_std, .vidioc_g_std = saa7134_g_std, .vidioc_querystd = saa7134_querystd, @@ -2089,7 +2090,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) * USERPTR support is a no-go unless the application knows about these * limitations and has special support for this. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; if (saa7134_userptr) q->io_modes |= VB2_USERPTR; q->drv_priv = &dev->video_q; -- cgit v1.2.3 From 80fa4f07fd6d33500b26275a5405d5b49cf2ff6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Sun, 20 Dec 2015 09:57:17 -0200 Subject: [media] usbtv: discard redundant video fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many dropped fields with some sources, leading to many redundant fields without counterparts. When this redundant field is odd, a new frame is pushed containing this odd field interleaved with whatever was left in the buffer, causing video artifacts. Do not push a new frame after processing every odd field, but do it only after those which come after an even field. Signed-off-by: Nikola Forró Acked-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 33 +++++++++++++++++++-------------- drivers/media/usb/usbtv/usbtv.h | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ebb33943f9a..4ecb27b2d619 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -312,20 +312,24 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); usbtv->chunks_done++; - /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == usbtv->n_chunks-1) { - int size = vb2_plane_size(&buf->vb.vb2_buf, 0); - enum vb2_buffer_state state = usbtv->chunks_done == - usbtv->n_chunks ? - VB2_BUF_STATE_DONE : - VB2_BUF_STATE_ERROR; - - buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.sequence = usbtv->sequence++; - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); - vb2_buffer_done(&buf->vb.vb2_buf, state); - list_del(&buf->list); + /* Last chunk in a field */ + if (chunk_no == usbtv->n_chunks-1) { + /* Last chunk in a frame, signalling an end */ + if (odd && !usbtv->last_odd) { + int size = vb2_plane_size(&buf->vb.vb2_buf, 0); + enum vb2_buffer_state state = usbtv->chunks_done == + usbtv->n_chunks ? + VB2_BUF_STATE_DONE : + VB2_BUF_STATE_ERROR; + + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.sequence = usbtv->sequence++; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); + } + usbtv->last_odd = odd; } spin_unlock_irqrestore(&usbtv->buflock, flags); @@ -639,6 +643,7 @@ static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) if (usbtv->udev == NULL) return -ENODEV; + usbtv->last_odd = 1; usbtv->sequence = 0; return usbtv_start(usbtv); } diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 19cb8bf7c4e9..161b38d5cfa0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -95,6 +95,7 @@ struct usbtv { int width, height; int n_chunks; int iso_size; + int last_odd; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; -- cgit v1.2.3 From 03c6bdfc65f157f2de4cc98926fc26778b28b0d1 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 22 Dec 2015 13:38:04 -0200 Subject: [media] bttv-driver, usbvision-video: use to_video_device() Use to_video_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 2 +- drivers/media/usb/usbvision/usbvision-video.c | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 9400e996087b..a04329adc0e5 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -186,7 +186,7 @@ MODULE_VERSION(BTTV_VERSION); static ssize_t show_card(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vfd = to_video_device(cd); struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index de9ff3bb8edd..7f5d6f15a49f 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -162,8 +162,7 @@ MODULE_ALIAS(DRIVER_ALIAS); static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); return video_get_drvdata(vdev); } @@ -177,8 +176,7 @@ static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t show_model(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", usbvision_device_data[usbvision->dev_model].model_string); @@ -188,8 +186,7 @@ static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_hue(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; @@ -203,8 +200,7 @@ static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_contrast(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; @@ -218,8 +214,7 @@ static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_brightness(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; @@ -233,8 +228,7 @@ static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; @@ -248,8 +242,7 @@ static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_streaming(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->streaming == stream_on ? 1 : 0)); @@ -259,8 +252,7 @@ static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); static ssize_t show_compression(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); @@ -270,8 +262,7 @@ static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); static ssize_t show_device_bridge(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%d\n", usbvision->bridge_type); } -- cgit v1.2.3 From faccb05ca8fb56c140fdeb70ae599e559c01c815 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 24 Dec 2015 18:06:45 -0200 Subject: [media] stk1160: Remove redundant vb2_buf payload set Calling vb2_set_plane_payload is enough, there's no need to set the planes[] bytesused field. Remove it. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/stk1160/stk1160-video.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 46191d5262eb..6ecb0b48423f 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -98,7 +98,6 @@ void stk1160_buffer_done(struct stk1160 *dev) buf->vb.sequence = dev->sequence++; buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused; buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); -- cgit v1.2.3 From b20b51f090f81418b4f74232a0f414b886e8ba8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Fri, 25 Dec 2015 15:25:16 -0200 Subject: [media] vim2m: return error if driver registration fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't hide the error code. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 418113c99801..c4b5fab83666 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1074,7 +1074,7 @@ static int __init vim2m_init(void) if (ret) platform_device_unregister(&vim2m_pdev); - return 0; + return ret; } module_init(vim2m_init); -- cgit v1.2.3 From 490ba9c29d5b82df2bed59d6007314c03d597716 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 19:02:21 -0200 Subject: [media] bttv: Returning only value constants in two functions Return constant integer values without storing them in the local variable "err" or "rc". Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index a04329adc0e5..2c412377507b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1726,22 +1726,15 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id) struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; unsigned int i; - int err = 0; for (i = 0; i < BTTV_TVNORMS; i++) if (id & bttv_tvnorms[i].v4l2_id) break; - if (i == BTTV_TVNORMS) { - err = -EINVAL; - goto err; - } - + if (i == BTTV_TVNORMS) + return -EINVAL; btv->std = id; set_tvnorm(btv, i); - -err: - - return err; + return 0; } static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) @@ -1770,12 +1763,9 @@ static int bttv_enum_input(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - int rc = 0; - if (i->index >= bttv_tvcards[btv->c.type].video_inputs) { - rc = -EINVAL; - goto err; - } + if (i->index >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 0; @@ -1799,10 +1789,7 @@ static int bttv_enum_input(struct file *file, void *priv, } i->std = BTTV_NORMS; - -err: - - return rc; + return 0; } static int bttv_g_input(struct file *file, void *priv, unsigned int *i) -- cgit v1.2.3 From 80c1bce9aa315ac70738f79afb4f7c93ae27d9fa Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 19:52:48 -0200 Subject: [media] au0828: Refactoring for start_urb_transfer() This issue was detected by using the Coccinelle software. 1. Let us return directly if a buffer allocation failed. 2. Delete the jump label "err" then. 3. Drop the explicit initialisation for the variable "ret" at the beginning. 4. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-dvb.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 94363a3ba400..0e174e860614 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -181,7 +181,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) static int start_urb_transfer(struct au0828_dev *dev) { struct urb *purb; - int i, ret = -ENOMEM; + int i, ret; dprintk(2, "%s()\n", __func__); @@ -194,7 +194,7 @@ static int start_urb_transfer(struct au0828_dev *dev) dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urbs[i]) - goto err; + return -ENOMEM; purb = dev->urbs[i]; @@ -207,9 +207,10 @@ static int start_urb_transfer(struct au0828_dev *dev) if (!purb->transfer_buffer) { usb_free_urb(purb); dev->urbs[i] = NULL; + ret = -ENOMEM; pr_err("%s: failed big buffer allocation, err = %d\n", __func__, ret); - goto err; + return ret; } purb->status = -EINPROGRESS; @@ -235,10 +236,7 @@ static int start_urb_transfer(struct au0828_dev *dev) } dev->urb_streaming = true; - ret = 0; - -err: - return ret; + return 0; } static void au0828_start_transport(struct au0828_dev *dev) -- cgit v1.2.3 From b68554cd76bfed57a3aac2fc4ac4c60478d90050 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 08:02:43 -0200 Subject: [media] hdpvr: Refactoring for hdpvr_read() Let us return directly if the element "status" of the variable "buf" indicates "BUFSTAT_READY". A check repetition can be excluded for the variable "ret" at the end then. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 7dee22deebf3..ba7f02270c83 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -462,10 +462,8 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, } if (wait_event_interruptible(dev->wait_data, - buf->status == BUFSTAT_READY)) { - ret = -ERESTARTSYS; - goto err; - } + buf->status == BUFSTAT_READY)) + return -ERESTARTSYS; } if (buf->status != BUFSTAT_READY) -- cgit v1.2.3 From f8433226d1b3eb035693724dca786c4445221368 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 16:53:35 -0200 Subject: [media] cx231xx: correctly handling failed allocation Since kmalloc can be failed in memory pressure, if not properly handled, NULL dereference can be happend Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 48643b94e694..c9320d6c6131 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1382,6 +1382,8 @@ static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) buffer_size = urb->actual_length; buffer = kmalloc(buffer_size, GFP_ATOMIC); + if (!buffer) + return -ENOMEM; memcpy(buffer, dma_q->ps_head, 3); memcpy(buffer+3, p_buffer, buffer_size-3); -- cgit v1.2.3 From e22a3b34a1f2ee53f89aef86b15d6f677de6bdc5 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 19:48:29 -0200 Subject: [media] usbtv: correctly handling failed allocation Since kzalloc can be failed, if not properly handled, NULL dereference could be happened. Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ecb27b2d619..f6cfad46547e 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -393,6 +393,10 @@ static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) ip->transfer_flags = URB_ISO_ASAP; ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, GFP_KERNEL); + if (!ip->transfer_buffer) { + usb_free_urb(ip); + return NULL; + } ip->complete = usbtv_iso_cb; ip->number_of_packets = USBTV_ISOC_PACKETS; ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS; -- cgit v1.2.3 From 3defe84a76d5055b24e2e04b5171892fa9455566 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 09:58:14 -0200 Subject: [media] av7110: constify sp8870_config structure This sp8870_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/av7110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index a69dc6a0752b..18d229fa65cf 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -1739,7 +1739,7 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir #endif } -static struct sp8870_config alps_tdlb7_config = { +static const struct sp8870_config alps_tdlb7_config = { .demod_address = 0x71, .request_firmware = alps_tdlb7_request_firmware, -- cgit v1.2.3 From 40205163ff84277747347ad0e522a7e2152a7677 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:11:06 -0200 Subject: [media] drivers/media/usb/dvb-usb-v2: constify mxl111sf_tuner_config structure This mxl111sf_tuner_config structure is never modified, so declare it as const. There are some indentation changes to remain within 80 columns. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Reviewed-by: Michael Ira Krufky Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | 6 +++--- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h | 8 ++++---- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index 444579be0b77..7d16252dbb71 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -36,7 +36,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); struct mxl111sf_tuner_state { struct mxl111sf_state *mxl_state; - struct mxl111sf_tuner_config *cfg; + const struct mxl111sf_tuner_config *cfg; enum mxl_if_freq if_freq; @@ -489,8 +489,8 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { }; struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { struct mxl111sf_tuner_state *state = NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index e6caab21a197..509b55071218 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -63,13 +63,13 @@ struct mxl111sf_tuner_config { #if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg); + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg); #else static inline struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index e7978e4e40ea..5d676b533a3a 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -856,7 +856,7 @@ static int mxl111sf_ant_hunt(struct dvb_frontend *fe) return 0; } -static struct mxl111sf_tuner_config mxl_tuner_config = { +static const struct mxl111sf_tuner_config mxl_tuner_config = { .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ .invert_spectrum = 0, .read_reg = mxl111sf_read_reg, -- cgit v1.2.3 From 4a40c73e5b27910edafe000fcc50a905de13447f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:19:52 -0200 Subject: [media] media: bt8xx: constify or51211_config structure The or51211_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index d407244fd1bc..8aeb14cfb89c 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -458,7 +458,7 @@ static void or51211_sleep(struct dvb_frontend * fe) bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000); } -static struct or51211_config or51211_config = { +static const struct or51211_config or51211_config = { .demod_address = 0x15, .request_firmware = or51211_request_firmware, .setmode = or51211_setmode, -- cgit v1.2.3 From 64e423d4fb7d561131a2dcc91930c401ab6bc217 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:27:53 -0200 Subject: [media] media: bt8xx: constify sp887x_config structure This sp887x_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 8aeb14cfb89c..e69d338ab9be 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -318,7 +318,7 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s return request_firmware(fw, name, &bt->bt->dev->dev); } -static struct sp887x_config microtune_mt7202dtf_config = { +static const struct sp887x_config microtune_mt7202dtf_config = { .demod_address = 0x70, .request_firmware = microtune_mt7202dtf_request_firmware, }; -- cgit v1.2.3 From 74dc385cb450089b28c28be2c8a0baca296b95f9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:30:09 -0200 Subject: [media] coda: fix first encoded frame payload During the recent vb2_buffer restructuring, the calculation of the buffer payload reported to userspace was accidentally broken for the first encoded frame, counting only the length of the headers. This patch re-adds the length of the actual frame data. Fixes: 2d7007153f0c ("[media] media: videobuf2: Restructure vb2_buffer") Reported-by: Michael Olbrich Signed-off-by: Philipp Zabel Tested-by: Jan Luebbe Cc: # for v4.4 and up Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 7d28899f89ce..6efe9d002961 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct coda_ctx *ctx) /* Calculate bytesused field */ if (dst_buf->sequence == 0) { - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]); -- cgit v1.2.3 From 39de7d95f88d95a07f64b047c985fff31c006b5c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Jan 2016 08:05:52 -0200 Subject: [media] vpx3220: signedness bug in vpx3220_fp_read() The intent was to return -1 on error and that's what the callers expect but the current code returns USHRT_MAX instead. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/vpx3220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 4b564f17f618..90b693f4e2ab 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -124,7 +124,7 @@ static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data) return 0; } -static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) +static int vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) { struct i2c_client *client = v4l2_get_subdevdata(sd); s16 data; -- cgit v1.2.3 From 199964b1d080d82cc8d39a7df1ece8671ef07753 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 08:57:58 -0200 Subject: [media] staging: media: lirc: fix MODULE_PARM_DESC typo It "tx_mask" was intended instead of "tx_maxk". Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 6e2edb24d9d5..68ede6c56e6d 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -730,7 +730,7 @@ module_param(irq, int, S_IRUGO); MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); module_param(tx_mask, int, S_IRUGO); -MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); +MODULE_PARM_DESC(tx_mask, "Transmitter mask (default: 0x01)"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging messages"); -- cgit v1.2.3 From aeae69daa312246e8f03ed2f6bc792d25a531118 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 09:02:56 -0200 Subject: [media] wl128x: fix typo in MODULE_PARM_DESC The module_param() is "default_rds_buf" and the MODULE_PARM_DESC() should match. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index ebc73b034249..3f9e6df7d837 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -68,7 +68,7 @@ MODULE_PARM_DESC(default_radio_region, "Region: 0=Europe/US, 1=Japan"); /* RDS buffer blocks */ static u32 default_rds_buf = 300; module_param(default_rds_buf, uint, 0444); -MODULE_PARM_DESC(rds_buf, "RDS buffer entries"); +MODULE_PARM_DESC(default_rds_buf, "RDS buffer entries"); /* Radio Nr */ static u32 radio_nr = -1; -- cgit v1.2.3 From 9dd73448c6a98b1971e626627e4b020b8898a3f6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Theou Date: Fri, 8 Jan 2016 20:02:03 -0200 Subject: [media] cx231xx: Fix memory leak dma_area needs to be freed when the device is closed. Based on em23xx-audio.c Signed-off-by: Jean-Baptiste Theou Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-audio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index de4ae5eb4830..a6a9508418f8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -499,6 +499,11 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) } dev->adev.users--; + if (substream->runtime->dma_area) { + dev_dbg(dev->dev, "freeing\n"); + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + } mutex_unlock(&dev->lock); if (dev->adev.users == 0 && dev->adev.shutdown == 1) { -- cgit v1.2.3 From 949cf70636bfe12c160c36608d18c5f8d89d2940 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 11 Jan 2016 05:13:35 -0200 Subject: [media] radio-si476x: add return value check to avoid dead code Dead code found on below code: si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) ====> Dead code !!! goto exit; The piece of code miss return value check after calling .si476x_radio_add_new_custom(), the patch fix it. Signed-off-by: Fugang Duan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si476x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 859f0c08ee05..271f725b17e8 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1530,11 +1530,11 @@ static int si476x_radio_probe(struct platform_device *pdev) if (si476x_core_has_diversity(radio->core)) { si476x_ctrls[SI476X_IDX_DIVERSITY_MODE].def = si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode); - si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; - si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) goto exit; } -- cgit v1.2.3 From 8e20b80344148dd8b7ec23d546e931d54810a1b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Jan 2016 11:44:41 -0200 Subject: [media] v4l2-dv-timings: skip standards check for V4L2_DV_BT_CAP_CUSTOM Skip validating the standards field in v4l2_valid_dv_timings() if the V4L2_DV_BT_CAP_CUSTOM capability is set, since that implies that non-standard timings are allowed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dv-timings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index ec258b73001a..889de0a32152 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -165,7 +165,8 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, bt->width > cap->max_width || bt->pixelclock < cap->min_pixelclock || bt->pixelclock > cap->max_pixelclock || - (cap->standards && bt->standards && + (!(caps & V4L2_DV_BT_CAP_CUSTOM) && + cap->standards && bt->standards && !(bt->standards & cap->standards)) || (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) -- cgit v1.2.3 From fcae73fac1b45053766c92f08fb3afee6d30dbbc Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 11:38:07 -0200 Subject: [media] tc358743: Use local array with fixed size in i2c write i2c_wr() is called from ops and the interrupt service routine, while state->wr_data is shared and unprotected, and could be overwritten. This shared buffer is therefore replaced with a local array with fixed size. The array has the size of one EDID block (128 bytes) + 2 bytes i2c address, and the EDID is written block by block (up to 8 blocks). Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 0325f7ed45d9..da7469bc6e56 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -59,8 +59,7 @@ MODULE_LICENSE("GPL"); #define EDID_NUM_BLOCKS_MAX 8 #define EDID_BLOCK_SIZE 128 -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE (EDID_NUM_BLOCKS_MAX * EDID_BLOCK_SIZE + 2) +#define I2C_MAX_XFER_SIZE (EDID_BLOCK_SIZE + 2) static const struct v4l2_dv_timings_cap tc358743_timings_cap = { .type = V4L2_DV_BT_656_1120, @@ -97,9 +96,6 @@ struct tc358743_state { /* edid */ u8 edid_blocks_written; - /* used by i2c_wr() */ - u8 wr_data[MAX_XFER_SIZE]; - struct v4l2_dv_timings timings; u32 mbus_fmt_code; @@ -149,13 +145,15 @@ static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) { struct tc358743_state *state = to_state(sd); struct i2c_client *client = state->i2c_client; - u8 *data = state->wr_data; int err, i; struct i2c_msg msg; + u8 data[I2C_MAX_XFER_SIZE]; - if ((2 + n) > sizeof(state->wr_data)) + if ((2 + n) > I2C_MAX_XFER_SIZE) { + n = I2C_MAX_XFER_SIZE - 2; v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", reg, 2 + n); + } msg.addr = client->addr; msg.buf = data; @@ -1582,6 +1580,7 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); u16 edid_len = edid->blocks * EDID_BLOCK_SIZE; + int i; v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", __func__, edid->pad, edid->start_block, edid->blocks); @@ -1607,7 +1606,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, return 0; } - i2c_wr(sd, EDID_RAM, edid->edid, edid_len); + for (i = 0; i < edid_len; i += EDID_BLOCK_SIZE) + i2c_wr(sd, EDID_RAM + i, edid->edid + i, EDID_BLOCK_SIZE); state->edid_blocks_written = edid->blocks; -- cgit v1.2.3 From b7d4d2f8d8517e1b3759568ef20a88d1022598ff Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 22 Dec 2015 12:22:01 -0200 Subject: [media] media: adv7604: implement get_selection The rcar_vin driver relies on this. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f8dd7505b529..5d4dbd05f9d6 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1884,6 +1884,26 @@ static int adv76xx_get_format(struct v4l2_subdev *sd, return 0; } +static int adv76xx_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct adv76xx_state *state = to_state(sd); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */ + if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS) + return -EINVAL; + + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = state->timings.bt.width; + sel->r.height = state->timings.bt.height; + + return 0; +} + static int adv76xx_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -2404,6 +2424,7 @@ static const struct v4l2_subdev_video_ops adv76xx_video_ops = { static const struct v4l2_subdev_pad_ops adv76xx_pad_ops = { .enum_mbus_code = adv76xx_enum_mbus_code, + .get_selection = adv76xx_get_selection, .get_fmt = adv76xx_get_format, .set_fmt = adv76xx_set_format, .get_edid = adv76xx_get_edid, -- cgit v1.2.3 From 49fe73400d94027c9402d8fc11d1f8ed1a5aeb61 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Dec 2015 11:18:10 -0200 Subject: [media] DocBook media: make explicit that standard/timings never change automatically A driver might detect a new standard or DV timings, but it will never change to those new timings automatically. Instead it will send an event and let the application take care of it. Make this explicit in the documentation. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-query-dv-timings.xml | 14 ++++++++++++-- Documentation/DocBook/media/v4l/vidioc-querystd.xml | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml index e9c70a8f3476..0c93677d16b4 100644 --- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml @@ -60,9 +60,19 @@ input automatically, similar to sensing the video standard. To do so, applications call VIDIOC_QUERY_DV_TIMINGS with a pointer to a &v4l2-dv-timings;. Once the hardware detects the timings, it will fill in the -timings structure. +timings structure. -If the timings could not be detected because there was no signal, then +Please note that drivers shall not switch timings automatically +if new timings are detected. Instead, drivers should send the +V4L2_EVENT_SOURCE_CHANGE event (if they support this) and expect +that userspace will take action by calling VIDIOC_QUERY_DV_TIMINGS. +The reason is that new timings usually mean different buffer sizes as well, and you +cannot change buffer sizes on the fly. In general, applications that receive the +Source Change event will have to call VIDIOC_QUERY_DV_TIMINGS, +and if the detected timings are valid they will have to stop streaming, set the new +timings, allocate new buffers and start streaming again. + +If the timings could not be detected because there was no signal, then ENOLINK is returned. If a signal was detected, but it was unstable and the receiver could not lock to the signal, then ENOLCK is returned. If the receiver could lock to the signal, diff --git a/Documentation/DocBook/media/v4l/vidioc-querystd.xml b/Documentation/DocBook/media/v4l/vidioc-querystd.xml index 222348542182..3ceae35fab03 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querystd.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querystd.xml @@ -59,6 +59,16 @@ then the driver will return V4L2_STD_UNKNOWN. When detection is not possible or fails, the set must contain all standards supported by the current video input or output. +Please note that drivers shall not switch the video standard +automatically if a new video standard is detected. Instead, drivers should send the +V4L2_EVENT_SOURCE_CHANGE event (if they support this) and expect +that userspace will take action by calling VIDIOC_QUERYSTD. +The reason is that a new video standard can mean different buffer sizes as well, and you +cannot change buffer sizes on the fly. In general, applications that receive the +Source Change event will have to call VIDIOC_QUERYSTD, +and if the detected video standard is valid they will have to stop streaming, set the new +standard, allocate new buffers and start streaming again. + -- cgit v1.2.3 From 7df5ab8774aa383c6d2bff00688d004585d96dfd Mon Sep 17 00:00:00 2001 From: Tiffany Lin Date: Tue, 19 Jan 2016 05:56:50 -0200 Subject: [media] media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32 In v4l2-compliance utility, test QUERYBUF required correct length value to go through each planar to check planar's length in multi-planar buffer type Signed-off-by: Tiffany Lin Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Cc: # for v3.7 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8fd84a67478a..019644ff627d 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory)) + get_user(kp->memory, &up->memory) || + get_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - if (get_user(kp->length, &up->length)) - return -EFAULT; - num_planes = kp->length; if (num_planes == 0) { kp->m.planes = NULL; @@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + if (get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: { compat_long_t tmp; - if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) + if (get_user(tmp, &up->m.userptr)) return -EFAULT; kp->m.userptr = (unsigned long)compat_ptr(tmp); @@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved2, &up->reserved2) || - put_user(kp->reserved, &up->reserved)) + put_user(kp->reserved, &up->reserved) || + put_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) + if (put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: -- cgit v1.2.3 From 3541e349e18eeacbe8e5e97ed984f018be4cfdaf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jan 2016 13:13:25 -0200 Subject: [media] vivid: fix broken Bayer text rendering Sometimes when a Bayer pixelformat is selected the rendering of the OSD text by vivid was all wrong: every other line of the text was shifted by half the width or more. It turned out that to render Bayer formats the interleaved boolean is set to true in the tpg. This mode indicates a semi-biplanar mode where two interleaved planes are used to render the frame. From outside the tpg it looks like a single plane, but internally it is two planes. However, in the tpg_s_bytesperline() function the interleaved bool wasn't checked and only the bytesperline value for plane 0 was updated. But for the interleaved mode the same value has to be copied to bytesperline[1] as well. The effect was that whatever old value was left in bytesperline[1] was used, which caused all sorts of weird and seemingly unpredictable shifts. Reported-by: Ove Brynestad Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h index 9baed6a10334..93fbaee69675 100644 --- a/drivers/media/platform/vivid/vivid-tpg.h +++ b/drivers/media/platform/vivid/vivid-tpg.h @@ -418,6 +418,8 @@ static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsi tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p]; } + if (tpg_g_interleaved(tpg)) + tpg->bytesperline[1] = tpg->bytesperline[0]; } -- cgit v1.2.3 From 9f14bab72cccc0f4adb2fefde2c3c3740e7be86c Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:24 -0200 Subject: [media] media: ti-vpe: Document CAL driver Device Tree bindings for the Camera Adaptation Layer (CAL) driver Signed-off-by: Benoit Parrot Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/ti-cal.txt diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt new file mode 100644 index 000000000000..ae9b52f37576 --- /dev/null +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -0,0 +1,72 @@ +Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL) +------------------------------------------------------ + +The Camera Adaptation Layer (CAL) is a key component for image capture +applications. The capture module provides the system interface and the +processing capability to connect CSI2 image-sensor modules to the +DRA72x device. + +Required properties: +- compatible: must be "ti,dra72-cal" +- reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX + control address space +- reg-names: cal_top, cal_rx_core0, cal_rx_core1, and camerrx_control + registers +- interrupts: should contain IRQ line for the CAL; + +CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes +should contain a 'port' child node with child 'endpoint' node. Please +refer to the bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + cal: cal@4845b000 { + compatible = "ti,dra72-cal"; + ti,hwmods = "cal"; + reg = <0x4845B000 0x400>, + <0x4845B800 0x40>, + <0x4845B900 0x40>, + <0x4A002e94 0x4>; + reg-names = "cal_top", + "cal_rx_core0", + "cal_rx_core1", + "camerrx_control"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csi2_0: port@0 { + reg = <0>; + endpoint { + slave-mode; + remote-endpoint = <&ar0330_1>; + }; + }; + csi2_1: port@1 { + reg = <1>; + }; + }; + }; + + i2c5: i2c@4807c000 { + ar0330@10 { + compatible = "ti,ar0330"; + reg = <0x10>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ar0330_1: endpoint { + reg = <0>; + clock-lanes = <1>; + data-lanes = <0 2 3 4>; + remote-endpoint = <&csi2_0>; + }; + }; + }; + }; -- cgit v1.2.3 From ccf963d3276e318fb952fffd1829ed47876bbec9 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:25 -0200 Subject: [media] MAINTAINERS: Add ti-vpe maintainer entry Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..9f1a401922de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10853,6 +10853,14 @@ L: linux-omap@vger.kernel.org S: Maintained F: drivers/thermal/ti-soc-thermal/ +TI VPE/CAL DRIVERS +M: Benoit Parrot +L: linux-media@vger.kernel.org +W: http://linuxtv.org/ +Q: http://patchwork.linuxtv.org/project/linux-media/list/ +S: Maintained +F: drivers/media/platform/ti-vpe/ + TI CDCE706 CLOCK DRIVER M: Max Filippov S: Maintained -- cgit v1.2.3 From 343e89a792a571b28b9c02850db7af2ef25ffb20 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:26 -0200 Subject: [media] media: ti-vpe: Add CAL v4l2 camera capture driver The Camera Adaptation Layer (CAL) is a block which consists of a dual port CSI2/MIPI camera capture engine. Port #0 can handle CSI2 camera connected to up to 4 data lanes. Port #1 can handle CSI2 camera connected to up to 2 data lanes. The driver implements the required API/ioctls to be V4L2 compliant. Driver supports the following: - V4L2 API using DMABUF/MMAP buffer access based on videobuf2 api - Asynchronous sensor sub device registration - DT support Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 12 + drivers/media/platform/Makefile | 2 + drivers/media/platform/ti-vpe/Makefile | 4 + drivers/media/platform/ti-vpe/cal.c | 1970 ++++++++++++++++++++++++++++++ drivers/media/platform/ti-vpe/cal_regs.h | 479 ++++++++ 5 files changed, 2467 insertions(+) create mode 100644 drivers/media/platform/ti-vpe/cal.c create mode 100644 drivers/media/platform/ti-vpe/cal_regs.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 526359447ff9..6f0f28fc4e2f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -120,6 +120,18 @@ source "drivers/media/platform/s5p-tv/Kconfig" source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" +config VIDEO_TI_CAL + tristate "TI CAL (Camera Adaptation Layer) driver" + depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on SOC_DRA7XX || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + default n + ---help--- + Support for the TI CAL (Camera Adaptation Layer) block + found on DRA72X SoC. + In TI Technical Reference Manual this module is referred as + Camera Interface Subsystem (CAMSS). + endif # V4L_PLATFORM_DRIVERS menuconfig V4L_MEM2MEM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index efa0295af87b..028a7233096b 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe/ +obj-$(CONFIG_VIDEO_TI_CAL) += ti-vpe/ + obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o obj-$(CONFIG_VIDEO_CODA) += coda/ diff --git a/drivers/media/platform/ti-vpe/Makefile b/drivers/media/platform/ti-vpe/Makefile index be680f839e77..e236059a60ad 100644 --- a/drivers/media/platform/ti-vpe/Makefile +++ b/drivers/media/platform/ti-vpe/Makefile @@ -3,3 +3,7 @@ obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o ti-vpe-y := vpe.o sc.o csc.o vpdma.o ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG + +obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o + +ti-cal-y := cal.o diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c new file mode 100644 index 000000000000..69ec79ba49ee --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal.c @@ -0,0 +1,1970 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * Benoit Parrot, + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cal_regs.h" + +#define CAL_MODULE_NAME "cal" + +#define MAX_WIDTH 1920 +#define MAX_HEIGHT 1200 + +#define CAL_VERSION "0.1.0" + +MODULE_DESCRIPTION("TI CAL driver"); +MODULE_AUTHOR("Benoit Parrot, "); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(CAL_VERSION); + +static unsigned video_nr = -1; +module_param(video_nr, uint, 0644); +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect"); + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +/* timeperframe: min/max and default */ +static const struct v4l2_fract + tpf_default = {.numerator = 1001, .denominator = 30000}; + +#define cal_dbg(level, caldev, fmt, arg...) \ + v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg) +#define cal_info(caldev, fmt, arg...) \ + v4l2_info(&caldev->v4l2_dev, fmt, ##arg) +#define cal_err(caldev, fmt, arg...) \ + v4l2_err(&caldev->v4l2_dev, fmt, ##arg) + +#define ctx_dbg(level, ctx, fmt, arg...) \ + v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg) +#define ctx_info(ctx, fmt, arg...) \ + v4l2_info(&ctx->v4l2_dev, fmt, ##arg) +#define ctx_err(ctx, fmt, arg...) \ + v4l2_err(&ctx->v4l2_dev, fmt, ##arg) + +#define CAL_NUM_INPUT 1 +#define CAL_NUM_CONTEXT 2 + +#define bytes_per_line(pixel, bpp) (ALIGN(pixel * bpp, 16)) + +#define reg_read(dev, offset) ioread32(dev->base + offset) +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset) + +#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \ + mask) +#define reg_write_field(dev, offset, field, mask) { \ + u32 val = reg_read(dev, offset); \ + set_field(&val, field, mask); \ + reg_write(dev, offset, val); } + +/* ------------------------------------------------------------------ + * Basic structures + * ------------------------------------------------------------------ + */ + +struct cal_fmt { + u32 fourcc; + u32 code; + u8 depth; +}; + +static struct cal_fmt cal_formats[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ + .code = MEDIA_BUS_FMT_RGB888_2X12_LE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ + .code = MEDIA_BUS_FMT_RGB888_2X12_BE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ + .code = MEDIA_BUS_FMT_ARGB8888_1X32, + .depth = 32, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 16, + }, +}; + +/* Print Four-character-code (FOURCC) */ +static char *fourcc_to_str(u32 fmt) +{ + static char code[5]; + + code[0] = (unsigned char)(fmt & 0xff); + code[1] = (unsigned char)((fmt >> 8) & 0xff); + code[2] = (unsigned char)((fmt >> 16) & 0xff); + code[3] = (unsigned char)((fmt >> 24) & 0xff); + code[4] = '\0'; + + return code; +} + +/* buffer for one video frame */ +struct cal_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; + struct list_head list; + const struct cal_fmt *fmt; +}; + +struct cal_dmaqueue { + struct list_head active; + + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +struct cm_data { + void __iomem *base; + struct resource *res; + + unsigned int camerrx_control; + + struct platform_device *pdev; +}; + +struct cc_data { + void __iomem *base; + struct resource *res; + + struct platform_device *pdev; +}; + +/* + * there is one cal_dev structure in the driver, it is shared by + * all instances. + */ +struct cal_dev { + int irq; + void __iomem *base; + struct resource *res; + struct platform_device *pdev; + struct v4l2_device v4l2_dev; + + /* Control Module handle */ + struct cm_data *cm; + /* Camera Core Module handle */ + struct cc_data *cc[CAL_NUM_CSI2_PORTS]; + + struct cal_ctx *ctx[CAL_NUM_CONTEXT]; +}; + +/* + * There is one cal_ctx structure for each camera core context. + */ +struct cal_ctx { + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler ctrl_handler; + struct video_device vdev; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *sensor; + struct v4l2_of_endpoint endpoint; + + struct v4l2_async_subdev asd; + struct v4l2_async_subdev *asd_list[1]; + + struct v4l2_fh fh; + struct cal_dev *dev; + struct cc_data *cc; + + /* v4l2_ioctl mutex */ + struct mutex mutex; + /* v4l2 buffers lock */ + spinlock_t slock; + + /* Several counters */ + unsigned long jiffies; + + struct vb2_alloc_ctx *alloc_ctx; + struct cal_dmaqueue vidq; + + /* Input Number */ + int input; + + /* video capture */ + const struct cal_fmt *fmt; + /* Used to store current pixel format */ + struct v4l2_format v_fmt; + /* Used to store current mbus frame format */ + struct v4l2_mbus_framefmt m_fmt; + + /* Current subdev enumerated format */ + struct cal_fmt *active_fmt[ARRAY_SIZE(cal_formats)]; + int num_active_fmt; + + struct v4l2_fract timeperframe; + unsigned int sequence; + unsigned int external_rate; + struct vb2_queue vb_vidq; + unsigned int seq_count; + unsigned int csi2_port; + unsigned int virtual_channel; + + /* Pointer pointing to current v4l2_buffer */ + struct cal_buffer *cur_frm; + /* Pointer pointing to next v4l2_buffer */ + struct cal_buffer *next_frm; +}; + +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx, + u32 pixelformat) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} + +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx, + u32 code) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->code == code) + return fmt; + } + + return NULL; +} + +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n) +{ + return container_of(n, struct cal_ctx, notifier); +} + +static inline int get_field(u32 value, u32 mask) +{ + return (value & mask) >> __ffs(mask); +} + +static inline void set_field(u32 *valp, u32 field, u32 mask) +{ + u32 val = *valp; + + val &= ~mask; + val |= (field << __ffs(mask)) & mask; + *valp = val; +} + +/* + * Control Module block access + */ +static struct cm_data *cm_create(struct cal_dev *dev) +{ + struct platform_device *pdev = dev->pdev; + struct cm_data *cm; + + cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL); + if (!cm) + return ERR_PTR(-ENOMEM); + + cm->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "camerrx_control"); + cm->base = devm_ioremap_resource(&pdev->dev, cm->res); + if (IS_ERR(cm->base)) { + cal_err(dev, "failed to ioremap\n"); + return cm->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cm->res->name, &cm->res->start, &cm->res->end); + + return cm; +} + +static void camerarx_phy_enable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0xf, CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_MODE_MASK); + } else if (ctx->csi2_port == 2) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0x3, CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_MODE_MASK); + } + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +static void camerarx_phy_disable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + else if (ctx->csi2_port == 2) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +/* + * Camera Instance access block + */ +static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core) +{ + struct platform_device *pdev = dev->pdev; + struct cc_data *cc; + + cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return ERR_PTR(-ENOMEM); + + cc->res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, + (core == 0) ? + "cal_rx_core0" : + "cal_rx_core1"); + cc->base = devm_ioremap_resource(&pdev->dev, cc->res); + if (IS_ERR(cc->base)) { + cal_err(dev, "failed to ioremap\n"); + return cc->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cc->res->name, &cc->res->start, &cc->res->end); + + return cc; +} + +/* + * Get Revision and HW info + */ +static void cal_get_hwinfo(struct cal_dev *dev) +{ + u32 revision = 0; + u32 hwinfo = 0; + + revision = reg_read(dev, CAL_HL_REVISION); + cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n", + revision); + + hwinfo = reg_read(dev, CAL_HL_HWINFO); + cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n", + hwinfo); +} + +static inline int cal_runtime_get(struct cal_dev *dev) +{ + int r; + + r = pm_runtime_get_sync(&dev->pdev->dev); + + return r; +} + +static inline void cal_runtime_put(struct cal_dev *dev) +{ + pm_runtime_put_sync(&dev->pdev->dev); +} + +static void cal_quickdump_regs(struct cal_dev *dev) +{ + cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->base, resource_size(dev->res), false); + + if (dev->ctx[0]) { + cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n", + &dev->ctx[0]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[0]->cc->base, + resource_size(dev->ctx[0]->cc->res), + false); + } + + if (dev->ctx[1]) { + cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n", + &dev->ctx[1]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[1]->cc->base, + resource_size(dev->ctx[1]->cc->res), + false); + } + + cal_info(dev, "CAMERRX_Control Registers @ %pa:\n", + &dev->cm->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->cm->base, + resource_size(dev->cm->res), false); +} + +/* + * Enable the expected IRQ sources + */ +static void enable_irqs(struct cal_ctx *ctx) +{ + /* Enable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(2), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Enable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(3), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000); +} + +static void disable_irqs(struct cal_ctx *ctx) +{ + /* Disable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(2), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Disable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(3), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0); +} + +static void csi2_init(struct cal_ctx *ctx) +{ + int i; + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK); + set_field(&val, CAL_GEN_DISABLE, + CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK); + set_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK); + reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL, + CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON, + CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK); + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + for (i = 0; i < 10; i++) { + if (reg_read_field(ctx->dev, + CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) == + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON) + break; + usleep_range(1000, 1100); + } + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CTRL); + set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK); + set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK); + set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED, + CAL_CTRL_POSTED_WRITES_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK); + reg_write(ctx->dev, CAL_CTRL, val); + ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->dev, CAL_CTRL)); +} + +static void csi2_lane_config(struct cal_ctx *ctx) +{ + u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK; + u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK; + struct v4l2_of_bus_mipi_csi2 *mipi_csi2 = &ctx->endpoint.bus.mipi_csi2; + int lane; + + set_field(&val, mipi_csi2->clock_lane + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask); + for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) { + /* + * Every lane are one nibble apart starting with the + * clock followed by the data lanes so shift masks by 4. + */ + lane_mask <<= 4; + polarity_mask <<= 4; + set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[lane + 1], + polarity_mask); + } + + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", + ctx->csi2_port, val); +} + +static void csi2_ppi_enable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_ENABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ppi_disable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_DISABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ctx_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK); + /* + * DT type: MIPI CSI-2 Specs + * 0x1: All - DT filter is disabled + * 0x24: RGB888 1 pixel = 3 bytes + * 0x2B: RAW10 4 pixels = 5 bytes + * 0x2A: RAW8 1 pixel = 1 byte + * 0x1E: YUV422 2 pixels = 4 bytes + */ + set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK); + /* Virtual Channel from the CSI2 sensor usually 0! */ + set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK); + /* NUM_LINES_PER_FRAME => 0 means auto detect */ + set_field(&val, 0, CAL_CSI2_CTX_LINES_MASK); + set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK); + set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE, + CAL_CSI2_CTX_PACK_MODE_MASK); + reg_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port))); +} + +static void pix_proc_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)); + set_field(&val, CAL_PIX_PROC_EXTRACT_B8, CAL_PIX_PROC_EXTRACT_MASK); + set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK); + set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK); + set_field(&val, CAL_PIX_PROC_PACK_B8, CAL_PIX_PROC_PACK_MASK); + set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK); + reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port))); +} + +static void cal_wr_dma_config(struct cal_ctx *ctx, + unsigned int width) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK); + set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT, + CAL_WR_DMA_CTRL_DTAG_MASK); + set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST, + CAL_WR_DMA_CTRL_MODE_MASK); + set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR, + CAL_WR_DMA_CTRL_PATTERN_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_WR_DMA_CTRL_STALL_RD_MASK); + reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port))); + + /* + * width/16 not sure but giving it a whirl. + * zero does not work right + */ + reg_write_field(ctx->dev, + CAL_WR_DMA_OFST(ctx->csi2_port), + (width / 16), + CAL_WR_DMA_OFST_MASK); + ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)); + /* 64 bit word means no skipping */ + set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK); + /* + * (width*8)/64 this should be size of an entire line + * in 64bit word but 0 means all data until the end + * is detected automagically + */ + set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK); + reg_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port))); +} + +static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr) +{ + reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr); +} + +/* + * TCLK values are OK at their reset values + */ +#define TCLK_TERM 0 +#define TCLK_MISS 1 +#define TCLK_SETTLE 14 +#define THS_SETTLE 15 + +static void csi2_phy_config(struct cal_ctx *ctx) +{ + unsigned int reg0, reg1; + unsigned int ths_term, ths_settle; + unsigned int ddrclkperiod_us; + + /* + * THS_TERM: Programmed value = floor(20 ns/DDRClk period) - 2. + */ + ddrclkperiod_us = ctx->external_rate / 2000000; + ddrclkperiod_us = 1000000 / ddrclkperiod_us; + ctx_dbg(1, ctx, "ddrclkperiod_us: %d\n", ddrclkperiod_us); + + ths_term = 20000 / ddrclkperiod_us; + ths_term = (ths_term >= 2) ? ths_term - 2 : ths_term; + ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term); + + /* + * THS_SETTLE: Programmed value = floor(176.3 ns/CtrlClk period) - 1. + * Since CtrlClk is fixed at 96Mhz then we get + * ths_settle = floor(176.3 / 10.416) - 1 = 15 + * If we ever switch to a dynamic clock then this code might be useful + * + * unsigned int ctrlclkperiod_us; + * ctrlclkperiod_us = 96000000 / 1000000; + * ctrlclkperiod_us = 1000000 / ctrlclkperiod_us; + * ctx_dbg(1, ctx, "ctrlclkperiod_us: %d\n", ctrlclkperiod_us); + + * ths_settle = 176300 / ctrlclkperiod_us; + * ths_settle = (ths_settle > 1) ? ths_settle - 1 : ths_settle; + */ + + ths_settle = THS_SETTLE; + ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle); + + reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0); + set_field(®0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE, + CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK); + set_field(®0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK); + set_field(®0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port - 1), reg0); + reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0); + + reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1); + set_field(®1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK); + set_field(®1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK); + set_field(®1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK); + set_field(®1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port - 1), reg1); + reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1); +} + +static int cal_get_external_info(struct cal_ctx *ctx) +{ + struct v4l2_ctrl *ctrl; + + ctrl = v4l2_ctrl_find(ctx->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) { + ctx_err(ctx, "no pixel rate control in subdev: %s\n", + ctx->sensor->name); + return -EPIPE; + } + + ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); + ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate); + + return 0; +} + +static inline void cal_schedule_next_buffer(struct cal_ctx *ctx) +{ + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf; + unsigned long addr; + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->next_frm = buf; + list_del(&buf->list); + + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); + cal_wr_dma_addr(ctx, addr); +} + +static inline void cal_process_buffer_complete(struct cal_ctx *ctx) +{ + ctx->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); + ctx->cur_frm->vb.field = ctx->m_fmt.field; + ctx->cur_frm->vb.sequence = ctx->sequence++; + + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); + ctx->cur_frm = ctx->next_frm; +} + +#define isvcirqset(irq, vc, ff) (irq & \ + (CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK)) + +#define isportirqset(irq, port) (irq & CAL_HL_IRQ_MASK(port)) + +static irqreturn_t cal_irq(int irq_cal, void *data) +{ + struct cal_dev *dev = (struct cal_dev *)data; + struct cal_ctx *ctx; + struct cal_dmaqueue *dma_q; + u32 irqst2, irqst3; + + /* Check which DMA just finished */ + irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2)); + if (irqst2) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2); + + /* Need to check both port */ + if (isportirqset(irqst2, 1)) { + ctx = dev->ctx[0]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + + if (isportirqset(irqst2, 2)) { + ctx = dev->ctx[1]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + } + + /* Check which DMA just started */ + irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3)); + if (irqst3) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3); + + /* Need to check both port */ + if (isportirqset(irqst3, 1)) { + ctx = dev->ctx[0]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + + if (isportirqset(irqst3, 2)) { + ctx = dev->ctx[1]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + } + + return IRQ_HANDLED; +} + +/* + * video ioctls + */ +static int cal_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cal_ctx *ctx = video_drvdata(file); + + strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver)); + strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card)); + + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", ctx->v4l2_dev.name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int cal_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt = NULL; + + if (f->index >= ctx->num_active_fmt) + return -EINVAL; + + fmt = ctx->active_fmt[f->index]; + + f->pixelformat = fmt->fourcc; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return 0; +} + +static int __subdev_get_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + + ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + *fmt = *mbus_fmt; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int __subdev_set_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + *mbus_fmt = *fmt; + + ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int cal_calc_format_size(struct cal_ctx *ctx, + const struct cal_fmt *fmt, + struct v4l2_format *f) +{ + if (!fmt) { + ctx_dbg(3, ctx, "No cal_fmt provided!\n"); + return -EINVAL; + } + + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, + &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); + f->fmt.pix.bytesperline = bytes_per_line(f->fmt.pix.width, + fmt->depth >> 3); + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + + ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n", + __func__, fourcc_to_str(f->fmt.pix.pixelformat), + f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); + + return 0; +} + +static int cal_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *f = ctx->v_fmt; + + return 0; +} + +static int cal_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret, found; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + if (!fmt) { + ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n", + f->fmt.pix.pixelformat); + + /* Just get the first one enumerated */ + fmt = ctx->active_fmt[0]; + f->fmt.pix.pixelformat = fmt->fourcc; + } + + f->fmt.pix.field = ctx->v_fmt.fmt.pix.field; + + /* check for/find a valid width/height */ + ret = 0; + found = false; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + break; + + if ((f->fmt.pix.width == fse.max_width) && + (f->fmt.pix.height == fse.max_height)) { + found = true; + break; + } else if ((f->fmt.pix.width >= fse.min_width) && + (f->fmt.pix.width <= fse.max_width) && + (f->fmt.pix.height >= fse.min_height) && + (f->fmt.pix.height <= fse.max_height)) { + found = true; + break; + } + } + + if (!found) { + /* use existing values as default */ + f->fmt.pix.width = ctx->v_fmt.fmt.pix.width; + f->fmt.pix.height = ctx->v_fmt.fmt.pix.height; + } + + /* + * Use current colorspace for now, it will get + * updated properly during s_fmt + */ + f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace; + return cal_calc_format_size(ctx, fmt, f); +} + +static int cal_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + struct vb2_queue *q = &ctx->vb_vidq; + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + if (vb2_is_busy(q)) { + ctx_dbg(3, ctx, "%s device busy\n", __func__); + return -EBUSY; + } + + ret = cal_try_fmt_vid_cap(file, priv, f); + if (ret < 0) + return ret; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code); + + ret = __subdev_set_format(ctx, &mbus_fmt); + if (ret) + return ret; + + /* Just double check nothing has gone wrong */ + if (mbus_fmt.code != fmt->code) { + ctx_dbg(3, ctx, + "%s subdev changed format on us, this should not happen\n", + __func__); + return -EINVAL; + } + + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + *f = ctx->v_fmt; + + return 0; +} + +static int cal_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + /* check for valid format */ + fmt = find_format_by_pix(ctx, fsize->pixel_format); + if (!fmt) { + ctx_dbg(3, ctx, "Invalid pixel code: %x\n", + fsize->pixel_format); + return -EINVAL; + } + + fse.index = fsize->index; + fse.pad = 0; + fse.code = fmt->code; + + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse); + if (ret) + return -EINVAL; + + ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", + __func__, fse.index, fse.code, fse.min_width, fse.max_width, + fse.min_height, fse.max_height); + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width; + fsize->discrete.height = fse.max_height; + + return 0; +} + +static int cal_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index >= CAL_NUM_INPUT) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + sprintf(inp->name, "Camera %u", inp->index); + return 0; +} + +static int cal_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *i = ctx->input; + return 0; +} + +static int cal_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + if (i >= CAL_NUM_INPUT) + return -EINVAL; + + ctx->input = i; + return 0; +} + +/* timeperframe is arbitrary and continuous */ +static int cal_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + if (fival->index) + return -EINVAL; + + fmt = find_format_by_pix(ctx, fival->pixel_format); + if (!fmt) + return -EINVAL; + + /* check for valid width/height */ + ret = 0; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + return -EINVAL; + + if ((fival->width == fse.max_width) && + (fival->height == fse.max_height)) + break; + else if ((fival->width >= fse.min_width) && + (fival->width <= fse.max_width) && + (fival->height >= fse.min_height) && + (fival->height <= fse.max_height)) + break; + + return -EINVAL; + } + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = 30; + + return 0; +} + +/* + * Videobuf operations + */ +static int cal_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + unsigned size = ctx->v_fmt.fmt.pix.sizeimage; + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + alloc_ctxs[0] = ctx->alloc_ctx; + + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } + + *nplanes = 1; + sizes[0] = size; + + ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]); + + return 0; +} + +static int cal_buffer_prepare(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + unsigned long size; + + if (WARN_ON(!ctx->fmt)) + return -EINVAL; + + size = ctx->v_fmt.fmt.pix.sizeimage; + if (vb2_plane_size(vb, 0) < size) { + ctx_err(ctx, + "data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + return 0; +} + +static void cal_buffer_queue(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + struct cal_dmaqueue *vidq = &ctx->vidq; + unsigned long flags = 0; + + /* recheck locking */ + spin_lock_irqsave(&ctx->slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long addr = 0; + unsigned long flags; + int ret; + + spin_lock_irqsave(&ctx->slock, flags); + if (list_empty(&dma_q->active)) { + spin_unlock_irqrestore(&ctx->slock, flags); + ctx_dbg(3, ctx, "buffer queue is empty\n"); + return -EIO; + } + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->cur_frm = buf; + ctx->next_frm = buf; + list_del(&buf->list); + spin_unlock_irqrestore(&ctx->slock, flags); + + addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0); + ctx->sequence = 0; + + ret = cal_get_external_info(ctx); + if (ret < 0) + goto err; + + cal_runtime_get(ctx->dev); + + enable_irqs(ctx); + camerarx_phy_enable(ctx); + csi2_init(ctx); + csi2_phy_config(ctx); + csi2_lane_config(ctx); + csi2_ctx_config(ctx); + pix_proc_config(ctx); + cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline); + cal_wr_dma_addr(ctx, addr); + csi2_ppi_enable(ctx); + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 1)) { + ctx_err(ctx, "stream on failed in subdev\n"); + cal_runtime_put(ctx->dev); + ret = -EINVAL; + goto err; + } + } + + if (debug >= 4) + cal_quickdump_regs(ctx->dev); + + return 0; + +err: + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + return ret; +} + +static void cal_stop_streaming(struct vb2_queue *vq) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long flags; + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0)) + ctx_err(ctx, "stream off failed in subdev\n"); + } + + csi2_ppi_disable(ctx); + disable_irqs(ctx); + + /* Release all active buffers */ + spin_lock_irqsave(&ctx->slock, flags); + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + if (ctx->cur_frm == ctx->next_frm) { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } else { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + } + ctx->cur_frm = NULL; + ctx->next_frm = NULL; + spin_unlock_irqrestore(&ctx->slock, flags); + + cal_runtime_put(ctx->dev); +} + +static struct vb2_ops cal_video_qops = { + .queue_setup = cal_queue_setup, + .buf_prepare = cal_buffer_prepare, + .buf_queue = cal_buffer_queue, + .start_streaming = cal_start_streaming, + .stop_streaming = cal_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static const struct v4l2_file_operations cal_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_ioctl_ops cal_ioctl_ops = { + .vidioc_querycap = cal_querycap, + .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap, + .vidioc_enum_framesizes = cal_enum_framesizes, + .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_enum_input = cal_enum_input, + .vidioc_g_input = cal_g_input, + .vidioc_s_input = cal_s_input, + .vidioc_enum_frameintervals = cal_enum_frameintervals, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static struct video_device cal_videodev = { + .name = CAL_MODULE_NAME, + .fops = &cal_fops, + .ioctl_ops = &cal_ioctl_ops, + .minor = -1, + .release = video_device_release_empty, +}; + +/* ----------------------------------------------------------------- + * Initialization and module stuff + * ------------------------------------------------------------------ + */ +static int cal_complete_ctx(struct cal_ctx *ctx); + +static int cal_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + struct v4l2_subdev_mbus_code_enum mbus_code; + int ret = 0; + int i, j, k; + + if (ctx->sensor) { + ctx_info(ctx, "Rejecting subdev %s (Already set!!)", + subdev->name); + return 0; + } + + ctx->sensor = subdev; + ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name); + + /* Enumerate sub device formats and enable all matching local formats */ + ctx->num_active_fmt = 0; + for (j = 0, i = 0; ret != -EINVAL; ++j) { + struct cal_fmt *fmt; + + memset(&mbus_code, 0, sizeof(mbus_code)); + mbus_code.index = j; + ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, + NULL, &mbus_code); + if (ret) + continue; + + ctx_dbg(2, ctx, + "subdev %s: code: %04x idx: %d\n", + subdev->name, mbus_code.code, j); + + for (k = 0; k < ARRAY_SIZE(cal_formats); k++) { + fmt = &cal_formats[k]; + + if (mbus_code.code == fmt->code) { + ctx->active_fmt[i] = fmt; + ctx_dbg(2, ctx, + "matched fourcc: %s: code: %04x idx: %d\n", + fourcc_to_str(fmt->fourcc), + fmt->code, i); + ctx->num_active_fmt = ++i; + } + } + } + + if (i == 0) { + ctx_err(ctx, "No suitable format reported by subdev %s\n", + subdev->name); + return -EINVAL; + } + + cal_complete_ctx(ctx); + + return 0; +} + +static int cal_async_complete(struct v4l2_async_notifier *notifier) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + ret = __subdev_get_format(ctx, &mbus_fmt); + if (ret) + return ret; + + fmt = find_format_by_code(ctx, mbus_fmt.code); + if (!fmt) { + ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n", + mbus_fmt.code); + return -EINVAL; + } + + /* Save current subdev format */ + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + + return 0; +} + +static int cal_complete_ctx(struct cal_ctx *ctx) +{ + struct video_device *vfd; + struct vb2_queue *q; + int ret; + + ctx->timeperframe = tpf_default; + ctx->external_rate = 192000000; + + /* initialize locks */ + spin_lock_init(&ctx->slock); + mutex_init(&ctx->mutex); + + /* initialize queue */ + q = &ctx->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = ctx; + q->buf_struct_size = sizeof(struct cal_buffer); + q->ops = &cal_video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ctx->mutex; + q->min_buffers_needed = 3; + + ret = vb2_queue_init(q); + if (ret) + return ret; + + /* init video dma queues */ + INIT_LIST_HEAD(&ctx->vidq.active); + + vfd = &ctx->vdev; + *vfd = cal_videodev; + vfd->v4l2_dev = &ctx->v4l2_dev; + vfd->queue = q; + + /* + * Provide a mutex to v4l2 core. It will be used to protect + * all fops and v4l2 ioctls. + */ + vfd->lock = &ctx->mutex; + video_set_drvdata(vfd, ctx); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); + if (ret < 0) + return ret; + + v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(vfd)); + + ctx->alloc_ctx = vb2_dma_contig_init_ctx(vfd->v4l2_dev->dev); + if (IS_ERR(ctx->alloc_ctx)) { + ctx_err(ctx, "Failed to alloc vb2 context\n"); + ret = PTR_ERR(ctx->alloc_ctx); + goto vdev_unreg; + } + + return 0; + +vdev_unreg: + video_unregister_device(vfd); + return ret; +} + +static struct device_node * +of_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *ports; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + ports = of_get_child_by_name(parent, "ports"); + if (ports) + parent = ports; + + port = of_get_child_by_name(parent, "port"); + + /* release the 'ports' node */ + of_node_put(ports); + } else { + struct device_node *ports; + + ports = of_get_parent(prev); + if (!ports) + return NULL; + + do { + port = of_get_next_child(ports, prev); + if (!port) { + of_node_put(ports); + return NULL; + } + prev = port; + } while (of_node_cmp(port->name, "port") != 0); + } + + return port; +} + +static struct device_node * +of_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *ep = NULL; + + if (!parent) + return NULL; + + do { + ep = of_get_next_child(parent, prev); + if (!ep) + return NULL; + prev = ep; + } while (of_node_cmp(ep->name, "endpoint") != 0); + + return ep; +} + +static int of_cal_create_instance(struct cal_ctx *ctx, int inst) +{ + struct platform_device *pdev = ctx->dev->pdev; + struct device_node *ep_node, *port, *remote_ep, + *sensor_node, *parent; + struct v4l2_of_endpoint *endpoint; + struct v4l2_async_subdev *asd; + u32 regval = 0; + int ret, index, found_port = 0, lane; + + parent = pdev->dev.of_node; + + asd = &ctx->asd; + endpoint = &ctx->endpoint; + + ep_node = NULL; + port = NULL; + remote_ep = NULL; + sensor_node = NULL; + ret = -EINVAL; + + ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst); + for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) { + port = of_get_next_port(parent, port); + if (!port) { + ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n", + index); + goto cleanup_exit; + } + + /* Match the slice number with */ + of_property_read_u32(port, "reg", ®val); + ctx_dbg(3, ctx, "port:%d inst:%d :%d\n", + index, inst, regval); + if ((regval == inst) && (index == inst)) { + found_port = 1; + break; + } + } + + if (!found_port) { + ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n", + inst); + goto cleanup_exit; + } + + ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n", + inst); + + ep_node = of_get_next_endpoint(port, ep_node); + if (!ep_node) { + ctx_dbg(3, ctx, "can't get next endpoint\n"); + goto cleanup_exit; + } + + sensor_node = of_graph_get_remote_port_parent(ep_node); + if (!sensor_node) { + ctx_dbg(3, ctx, "can't get remote parent\n"); + goto cleanup_exit; + } + asd->match_type = V4L2_ASYNC_MATCH_OF; + asd->match.of.node = sensor_node; + + remote_ep = of_parse_phandle(ep_node, "remote-endpoint", 0); + if (!remote_ep) { + ctx_dbg(3, ctx, "can't get remote-endpoint\n"); + goto cleanup_exit; + } + v4l2_of_parse_endpoint(remote_ep, endpoint); + + if (endpoint->bus_type != V4L2_MBUS_CSI2) { + ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n", + inst, sensor_node->name); + goto cleanup_exit; + } + + /* Store Virtual Channel number */ + ctx->virtual_channel = endpoint->base.id; + + ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst); + ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel); + ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags); + ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane); + ctx_dbg(3, ctx, "num_data_lanes=%d\n", + endpoint->bus.mipi_csi2.num_data_lanes); + ctx_dbg(3, ctx, "data_lanes= <\n"); + for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++) + ctx_dbg(3, ctx, "\t%d\n", + endpoint->bus.mipi_csi2.data_lanes[lane]); + ctx_dbg(3, ctx, "\t>\n"); + + ctx_dbg(1, ctx, "Port: %d found sub-device %s\n", + inst, sensor_node->name); + + ctx->asd_list[0] = asd; + ctx->notifier.subdevs = ctx->asd_list; + ctx->notifier.num_subdevs = 1; + ctx->notifier.bound = cal_async_bound; + ctx->notifier.complete = cal_async_complete; + ret = v4l2_async_notifier_register(&ctx->v4l2_dev, + &ctx->notifier); + if (ret) { + ctx_err(ctx, "Error registering async notifier\n"); + ret = -EINVAL; + } + +cleanup_exit: + if (!remote_ep) + of_node_put(remote_ep); + if (!sensor_node) + of_node_put(sensor_node); + if (!ep_node) + of_node_put(ep_node); + if (!port) + of_node_put(port); + + return ret; +} + +static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst) +{ + struct cal_ctx *ctx; + struct v4l2_ctrl_handler *hdl; + int ret; + + ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return 0; + + /* save the cal_dev * for future ref */ + ctx->dev = dev; + + snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name), + "%s-%03d", CAL_MODULE_NAME, inst); + ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev); + if (ret) + goto err_exit; + + hdl = &ctx->ctrl_handler; + ret = v4l2_ctrl_handler_init(hdl, 11); + if (ret) { + ctx_err(ctx, "Failed to init ctrl handler\n"); + goto unreg_dev; + } + ctx->v4l2_dev.ctrl_handler = hdl; + + /* Make sure Camera Core H/W register area is available */ + ctx->cc = dev->cc[inst]; + + /* Store the instance id */ + ctx->csi2_port = inst + 1; + + ret = of_cal_create_instance(ctx, inst); + if (ret) { + ret = -EINVAL; + goto free_hdl; + } + return ctx; + +free_hdl: + v4l2_ctrl_handler_free(hdl); +unreg_dev: + v4l2_device_unregister(&ctx->v4l2_dev); +err_exit: + return 0; +} + +static int cal_probe(struct platform_device *pdev) +{ + struct cal_dev *dev; + int ret; + int irq; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* set pseudo v4l2 device name so we can use v4l2_printk */ + strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME, + sizeof(dev->v4l2_dev.name)); + + /* save pdev pointer */ + dev->pdev = pdev; + + dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "cal_top"); + dev->base = devm_ioremap_resource(&pdev->dev, dev->res); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + dev->res->name, &dev->res->start, &dev->res->end); + + irq = platform_get_irq(pdev, 0); + cal_dbg(1, dev, "got irq# %d\n", irq); + ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME, + dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, dev); + + dev->cm = cm_create(dev); + if (IS_ERR(dev->cm)) + return PTR_ERR(dev->cm); + + dev->cc[0] = cc_create(dev, 0); + if (IS_ERR(dev->cc[0])) + return PTR_ERR(dev->cc[0]); + + dev->cc[1] = cc_create(dev, 1); + if (IS_ERR(dev->cc[1])) + return PTR_ERR(dev->cc[1]); + + dev->ctx[0] = NULL; + dev->ctx[1] = NULL; + + dev->ctx[0] = cal_create_instance(dev, 0); + dev->ctx[1] = cal_create_instance(dev, 1); + if (!dev->ctx[0] && !dev->ctx[1]) { + cal_err(dev, "Neither port is configured, no point in staying up\n"); + return -ENODEV; + } + + pm_runtime_enable(&pdev->dev); + + ret = cal_runtime_get(dev); + if (ret) + goto runtime_disable; + + /* Just check we can actually access the module */ + cal_get_hwinfo(dev); + + cal_runtime_put(dev); + + return 0; + +runtime_disable: + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int cal_remove(struct platform_device *pdev) +{ + struct cal_dev *dev = + (struct cal_dev *)platform_get_drvdata(pdev); + struct cal_ctx *ctx; + int i; + + cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME); + + cal_runtime_get(dev); + + for (i = 0; i < CAL_NUM_CONTEXT; i++) { + ctx = dev->ctx[i]; + if (ctx) { + ctx_dbg(1, ctx, "unregistering %s\n", + video_device_node_name(&ctx->vdev)); + camerarx_phy_disable(ctx); + v4l2_async_notifier_unregister(&ctx->notifier); + vb2_dma_contig_cleanup_ctx(ctx->alloc_ctx); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_device_unregister(&ctx->v4l2_dev); + video_unregister_device(&ctx->vdev); + } + } + + cal_runtime_put(dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id cal_of_match[] = { + { .compatible = "ti,dra72-cal", }, + {}, +}; +MODULE_DEVICE_TABLE(of, cal_of_match); +#endif + +static struct platform_driver cal_pdrv = { + .probe = cal_probe, + .remove = cal_remove, + .driver = { + .name = CAL_MODULE_NAME, + .of_match_table = of_match_ptr(cal_of_match), + }, +}; + +module_platform_driver(cal_pdrv); diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h new file mode 100644 index 000000000000..82b3dcf87128 --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal_regs.h @@ -0,0 +1,479 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * + * Benoit Parrot, + * + * 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_CAL_REGS_H +#define __TI_CAL_REGS_H + +#define CAL_NUM_CSI2_PORTS 2 + +/* CAL register offsets */ + +#define CAL_HL_REVISION 0x0000 +#define CAL_HL_HWINFO 0x0004 +#define CAL_HL_SYSCONFIG 0x0010 +#define CAL_HL_IRQ_EOI 0x001c +#define CAL_HL_IRQSTATUS_RAW(m) (0x20U + ((m-1) * 0x10U)) +#define CAL_HL_IRQSTATUS(m) (0x24U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_SET(m) (0x28U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_CLR(m) (0x2cU + ((m-1) * 0x10U)) +#define CAL_PIX_PROC(m) (0xc0U + ((m-1) * 0x4U)) +#define CAL_CTRL 0x100 +#define CAL_CTRL1 0x104 +#define CAL_LINE_NUMBER_EVT 0x108 +#define CAL_VPORT_CTRL1 0x120 +#define CAL_VPORT_CTRL2 0x124 +#define CAL_BYS_CTRL1 0x130 +#define CAL_BYS_CTRL2 0x134 +#define CAL_RD_DMA_CTRL 0x140 +#define CAL_RD_DMA_PIX_ADDR 0x144 +#define CAL_RD_DMA_PIX_OFST 0x148 +#define CAL_RD_DMA_XSIZE 0x14c +#define CAL_RD_DMA_YSIZE 0x150 +#define CAL_RD_DMA_INIT_ADDR 0x154 +#define CAL_RD_DMA_INIT_OFST 0x168 +#define CAL_RD_DMA_CTRL2 0x16c +#define CAL_WR_DMA_CTRL(m) (0x200U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_ADDR(m) (0x204U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_OFST(m) (0x208U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_XSIZE(m) (0x20cU + ((m-1) * 0x10U)) +#define CAL_CSI2_PPI_CTRL(m) (0x300U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_CFG(m) (0x304U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m) (0x308U + ((m-1) * 0x80U)) +#define CAL_CSI2_SHORT_PACKET(m) (0x30cU + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQENABLE(m) (0x310U + ((m-1) * 0x80U)) +#define CAL_CSI2_TIMING(m) (0x314U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX0(m) (0x330U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX1(m) (0x334U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX2(m) (0x338U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX3(m) (0x33cU + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX4(m) (0x340U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX5(m) (0x344U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX6(m) (0x348U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX7(m) (0x34cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS0(m) (0x350U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS1(m) (0x354U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS2(m) (0x358U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS3(m) (0x35cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS4(m) (0x360U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS5(m) (0x364U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS6(m) (0x368U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS7(m) (0x36cU + ((m-1) * 0x80U)) + +/* CAL CSI2 PHY register offsets */ +#define CAL_CSI2_PHY_REG0 0x000 +#define CAL_CSI2_PHY_REG1 0x004 +#define CAL_CSI2_PHY_REG2 0x008 + +/* CAL Control Module Core Camerrx Control register offsets */ +#define CM_CTRL_CORE_CAMERRX_CONTROL 0x000 + +/********************************************************************* +* Generic value used in various field below +*********************************************************************/ + +#define CAL_GEN_DISABLE 0 +#define CAL_GEN_ENABLE 1 +#define CAL_GEN_FALSE 0 +#define CAL_GEN_TRUE 1 + +/********************************************************************* +* Field Definition Macros +*********************************************************************/ + +#define CAL_HL_REVISION_MINOR_MASK GENMASK(5, 0) +#define CAL_HL_REVISION_CUSTOM_MASK GENMASK(7, 6) +#define CAL_HL_REVISION_MAJOR_MASK GENMASK(10, 8) +#define CAL_HL_REVISION_RTL_MASK GENMASK(15, 11) +#define CAL_HL_REVISION_FUNC_MASK GENMASK(27, 16) +#define CAL_HL_REVISION_SCHEME_MASK GENMASK(31, 30) +#define CAL_HL_REVISION_SCHEME_H08 1 +#define CAL_HL_REVISION_SCHEME_LEGACY 0 + +#define CAL_HL_HWINFO_WFIFO_MASK GENMASK(3, 0) +#define CAL_HL_HWINFO_RFIFO_MASK GENMASK(7, 4) +#define CAL_HL_HWINFO_PCTX_MASK GENMASK(12, 8) +#define CAL_HL_HWINFO_WCTX_MASK GENMASK(18, 13) +#define CAL_HL_HWINFO_VFIFO_MASK GENMASK(22, 19) +#define CAL_HL_HWINFO_NCPORT_MASK GENMASK(27, 23) +#define CAL_HL_HWINFO_NPPI_CTXS0_MASK GENMASK(29, 28) +#define CAL_HL_HWINFO_NPPI_CTXS1_MASK GENMASK(31, 30) +#define CAL_HL_HWINFO_NPPI_CONTEXTS_ZERO 0 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_FOUR 1 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_EIGHT 2 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_RESERVED 3 + +#define CAL_HL_SYSCONFIG_SOFTRESET_MASK BIT_MASK(0) +#define CAL_HL_SYSCONFIG_SOFTRESET_DONE 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_PENDING 0x1 +#define CAL_HL_SYSCONFIG_SOFTRESET_NOACTION 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_RESET 0x1 +#define CAL_HL_SYSCONFIG_IDLE_MASK GENMASK(3, 2) +#define CAL_HL_SYSCONFIG_IDLEMODE_FORCE 0 +#define CAL_HL_SYSCONFIG_IDLEMODE_NO 1 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART1 2 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART2 3 + +#define CAL_HL_IRQ_EOI_LINE_NUMBER_MASK BIT_MASK(0) +#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0 +#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0 + +#define CAL_HL_IRQ_MASK(m) BIT_MASK(m-1) +#define CAL_HL_IRQ_NOACTION 0x0 +#define CAL_HL_IRQ_ENABLE 0x1 +#define CAL_HL_IRQ_CLEAR 0x1 +#define CAL_HL_IRQ_DISABLED 0x0 +#define CAL_HL_IRQ_ENABLED 0x1 +#define CAL_HL_IRQ_PENDING 0x1 + +#define CAL_PIX_PROC_EN_MASK BIT_MASK(0) +#define CAL_PIX_PROC_EXTRACT_MASK GENMASK(4, 1) +#define CAL_PIX_PROC_EXTRACT_B6 0x0 +#define CAL_PIX_PROC_EXTRACT_B7 0x1 +#define CAL_PIX_PROC_EXTRACT_B8 0x2 +#define CAL_PIX_PROC_EXTRACT_B10 0x3 +#define CAL_PIX_PROC_EXTRACT_B10_MIPI 0x4 +#define CAL_PIX_PROC_EXTRACT_B12 0x5 +#define CAL_PIX_PROC_EXTRACT_B12_MIPI 0x6 +#define CAL_PIX_PROC_EXTRACT_B14 0x7 +#define CAL_PIX_PROC_EXTRACT_B14_MIPI 0x8 +#define CAL_PIX_PROC_EXTRACT_B16_BE 0x9 +#define CAL_PIX_PROC_EXTRACT_B16_LE 0xa +#define CAL_PIX_PROC_DPCMD_MASK GENMASK(9, 5) +#define CAL_PIX_PROC_DPCMD_BYPASS 0x0 +#define CAL_PIX_PROC_DPCMD_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCMD_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_1 0x4 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_2 0x5 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_1 0x6 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_2 0x7 +#define CAL_PIX_PROC_DPCMD_DPCM_12_7_1 0xa +#define CAL_PIX_PROC_DPCMD_DPCM_12_6_1 0xc +#define CAL_PIX_PROC_DPCMD_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCMD_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCMD_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCMD_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCMD_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_DPCME_MASK GENMASK(15, 11) +#define CAL_PIX_PROC_DPCME_BYPASS 0x0 +#define CAL_PIX_PROC_DPCME_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCME_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCME_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCME_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCME_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCME_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCME_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_PACK_MASK GENMASK(18, 16) +#define CAL_PIX_PROC_PACK_B8 0x0 +#define CAL_PIX_PROC_PACK_B10_MIPI 0x2 +#define CAL_PIX_PROC_PACK_B12 0x3 +#define CAL_PIX_PROC_PACK_B12_MIPI 0x4 +#define CAL_PIX_PROC_PACK_B16 0x5 +#define CAL_PIX_PROC_PACK_ARGB 0x6 +#define CAL_PIX_PROC_CPORT_MASK GENMASK(23, 19) + +#define CAL_CTRL_POSTED_WRITES_MASK BIT_MASK(0) +#define CAL_CTRL_POSTED_WRITES_NONPOSTED 0 +#define CAL_CTRL_POSTED_WRITES 1 +#define CAL_CTRL_TAGCNT_MASK GENMASK(4, 1) +#define CAL_CTRL_BURSTSIZE_MASK GENMASK(6, 5) +#define CAL_CTRL_BURSTSIZE_BURST16 0x0 +#define CAL_CTRL_BURSTSIZE_BURST32 0x1 +#define CAL_CTRL_BURSTSIZE_BURST64 0x2 +#define CAL_CTRL_BURSTSIZE_BURST128 0x3 +#define CAL_CTRL_LL_FORCE_STATE_MASK GENMASK(12, 7) +#define CAL_CTRL_MFLAGL_MASK GENMASK(20, 13) +#define CAL_CTRL_PWRSCPCLK_MASK BIT_MASK(21) +#define CAL_CTRL_PWRSCPCLK_AUTO 0 +#define CAL_CTRL_PWRSCPCLK_FORCE 1 +#define CAL_CTRL_RD_DMA_STALL_MASK BIT_MASK(22) +#define CAL_CTRL_MFLAGH_MASK GENMASK(31, 24) + +#define CAL_CTRL1_PPI_GROUPING_MASK GENMASK(1, 0) +#define CAL_CTRL1_PPI_GROUPING_DISABLED 0 +#define CAL_CTRL1_PPI_GROUPING_RESERVED 1 +#define CAL_CTRL1_PPI_GROUPING_0 2 +#define CAL_CTRL1_PPI_GROUPING_1 3 +#define CAL_CTRL1_INTERLEAVE01_MASK GENMASK(3, 2) +#define CAL_CTRL1_INTERLEAVE01_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE01_PIX1 1 +#define CAL_CTRL1_INTERLEAVE01_PIX4 2 +#define CAL_CTRL1_INTERLEAVE01_RESERVED 3 +#define CAL_CTRL1_INTERLEAVE23_MASK GENMASK(5, 4) +#define CAL_CTRL1_INTERLEAVE23_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE23_PIX1 1 +#define CAL_CTRL1_INTERLEAVE23_PIX4 2 +#define CAL_CTRL1_INTERLEAVE23_RESERVED 3 + +#define CAL_LINE_NUMBER_EVT_CPORT_MASK GENMASK(4, 0) +#define CAL_LINE_NUMBER_EVT_MASK GENMASK(29, 16) + +#define CAL_VPORT_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_VPORT_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_VPORT_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_VPORT_CTRL1_WIDTH_MASK BIT_MASK(31) +#define CAL_VPORT_CTRL1_WIDTH_ONE 0 +#define CAL_VPORT_CTRL1_WIDTH_TWO 1 + +#define CAL_VPORT_CTRL2_CPORT_MASK GENMASK(4, 0) +#define CAL_VPORT_CTRL2_FREERUNNING_MASK BIT_MASK(15) +#define CAL_VPORT_CTRL2_FREERUNNING_GATED 0 +#define CAL_VPORT_CTRL2_FREERUNNING_FREE 1 +#define CAL_VPORT_CTRL2_FS_RESETS_MASK BIT_MASK(16) +#define CAL_VPORT_CTRL2_FS_RESETS_NO 0 +#define CAL_VPORT_CTRL2_FS_RESETS_YES 1 +#define CAL_VPORT_CTRL2_FSM_RESET_MASK BIT_MASK(17) +#define CAL_VPORT_CTRL2_FSM_RESET_NOEFFECT 0 +#define CAL_VPORT_CTRL2_FSM_RESET 1 +#define CAL_VPORT_CTRL2_RDY_THR_MASK GENMASK(31, 18) + +#define CAL_BYS_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_BYS_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_BYS_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_BYS_CTRL1_BYSINEN_MASK BIT_MASK(31) + +#define CAL_BYS_CTRL2_CPORTIN_MASK GENMASK(4, 0) +#define CAL_BYS_CTRL2_CPORTOUT_MASK GENMASK(9, 5) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_MASK BIT_MASK(10) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_NO 0 +#define CAL_BYS_CTRL2_DUPLICATEDDATA_YES 1 +#define CAL_BYS_CTRL2_FREERUNNING_MASK BIT_MASK(11) +#define CAL_BYS_CTRL2_FREERUNNING_NO 0 +#define CAL_BYS_CTRL2_FREERUNNING_YES 1 + +#define CAL_RD_DMA_CTRL_GO_MASK BIT_MASK(0) +#define CAL_RD_DMA_CTRL_GO_DIS 0 +#define CAL_RD_DMA_CTRL_GO_EN 1 +#define CAL_RD_DMA_CTRL_GO_IDLE 0 +#define CAL_RD_DMA_CTRL_GO_BUSY 1 +#define CAL_RD_DMA_CTRL_INIT_MASK BIT_MASK(1) +#define CAL_RD_DMA_CTRL_BW_LIMITER_MASK GENMASK(10, 2) +#define CAL_RD_DMA_CTRL_OCP_TAG_CNT_MASK GENMASK(14, 11) +#define CAL_RD_DMA_CTRL_PCLK_MASK GENMASK(31, 15) + +#define CAL_RD_DMA_PIX_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_PIX_OFST_MASK GENMASK(31, 4) + +#define CAL_RD_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_RD_DMA_YSIZE_MASK GENMASK(29, 16) + +#define CAL_RD_DMA_INIT_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_INIT_OFST_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_CTRL2_CIRC_MODE_MASK GENMASK(2, 0) +#define CAL_RD_DMA_CTRL2_CIRC_MODE_DIS 0 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_ONE 1 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_FOUR 2 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTEEN 3 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTYFOUR 4 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_RESERVED 5 +#define CAL_RD_DMA_CTRL2_ICM_CSTART_MASK BIT_MASK(3) +#define CAL_RD_DMA_CTRL2_PATTERN_MASK GENMASK(5, 4) +#define CAL_RD_DMA_CTRL2_PATTERN_LINEAR 0 +#define CAL_RD_DMA_CTRL2_PATTERN_YUV420 1 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP2 2 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP4 3 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_MASK BIT_MASK(6) +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_FREERUNNING 0 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_WAITFORBYSOUT 1 +#define CAL_RD_DMA_CTRL2_CIRC_SIZE_MASK GENMASK(29, 16) + +#define CAL_WR_DMA_CTRL_MODE_MASK GENMASK(2, 0) +#define CAL_WR_DMA_CTRL_MODE_DIS 0 +#define CAL_WR_DMA_CTRL_MODE_SHD 1 +#define CAL_WR_DMA_CTRL_MODE_CNT 2 +#define CAL_WR_DMA_CTRL_MODE_CNT_INIT 3 +#define CAL_WR_DMA_CTRL_MODE_CONST 4 +#define CAL_WR_DMA_CTRL_MODE_RESERVED 5 +#define CAL_WR_DMA_CTRL_PATTERN_MASK GENMASK(4, 3) +#define CAL_WR_DMA_CTRL_PATTERN_LINEAR 0 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP2 2 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP4 3 +#define CAL_WR_DMA_CTRL_PATTERN_RESERVED 1 +#define CAL_WR_DMA_CTRL_ICM_PSTART_MASK BIT_MASK(5) +#define CAL_WR_DMA_CTRL_DTAG_MASK GENMASK(8, 6) +#define CAL_WR_DMA_CTRL_DTAG_ATT_HDR 0 +#define CAL_WR_DMA_CTRL_DTAG_ATT_DAT 1 +#define CAL_WR_DMA_CTRL_DTAG 2 +#define CAL_WR_DMA_CTRL_DTAG_PIX_HDR 3 +#define CAL_WR_DMA_CTRL_DTAG_PIX_DAT 4 +#define CAL_WR_DMA_CTRL_DTAG_D5 5 +#define CAL_WR_DMA_CTRL_DTAG_D6 6 +#define CAL_WR_DMA_CTRL_DTAG_D7 7 +#define CAL_WR_DMA_CTRL_CPORT_MASK GENMASK(13, 9) +#define CAL_WR_DMA_CTRL_STALL_RD_MASK BIT_MASK(14) +#define CAL_WR_DMA_CTRL_YSIZE_MASK GENMASK(31, 18) + +#define CAL_WR_DMA_ADDR_MASK GENMASK(31, 4) + +#define CAL_WR_DMA_OFST_MASK GENMASK(18, 4) +#define CAL_WR_DMA_OFST_CIRC_MODE_MASK GENMASK(23, 22) +#define CAL_WR_DMA_OFST_CIRC_MODE_ONE 1 +#define CAL_WR_DMA_OFST_CIRC_MODE_FOUR 2 +#define CAL_WR_DMA_OFST_CIRC_MODE_SIXTYFOUR 3 +#define CAL_WR_DMA_OFST_CIRC_MODE_DISABLED 0 +#define CAL_WR_DMA_OFST_CIRC_SIZE_MASK GENMASK(31, 24) + +#define CAL_WR_DMA_XSIZE_XSKIP_MASK GENMASK(15, 3) +#define CAL_WR_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_CSI2_PPI_CTRL_IF_EN_MASK BIT_MASK(0) +#define CAL_CSI2_PPI_CTRL_ECC_EN_MASK BIT_MASK(2) +#define CAL_CSI2_PPI_CTRL_FRAME_MASK BIT_MASK(3) +#define CAL_CSI2_PPI_CTRL_FRAME_IMMEDIATE 0 +#define CAL_CSI2_PPI_CTRL_FRAME 1 + +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK GENMASK(2, 0) +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_5 5 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_4 4 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_3 3 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_2 2 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_1 1 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_NOT_USED 0 +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_CFG_POL_PLUSMINUS 0 +#define CAL_CSI2_COMPLEXIO_CFG_POL_MINUSPLUS 1 +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POSITION_MASK GENMASK(6, 4) +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POL_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POSITION_MASK GENMASK(10, 8) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POL_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POSITION_MASK GENMASK(14, 12) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POL_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POSITION_MASK GENMASK(18, 16) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POL_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_AUTO_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK GENMASK(26, 25) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK GENMASK(28, 27) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK BIT_MASK(29) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED 1 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK BIT_MASK(30) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL 1 + +#define CAL_CSI2_SHORT_PACKET_MASK GENMASK(23, 0) + +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS1_MASK BIT_MASK(0) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS2_MASK BIT_MASK(1) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS3_MASK BIT_MASK(2) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS4_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS5_MASK BIT_MASK(4) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1_MASK BIT_MASK(5) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2_MASK BIT_MASK(6) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4_MASK BIT_MASK(8) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5_MASK BIT_MASK(9) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC1_MASK BIT_MASK(10) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC2_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC3_MASK BIT_MASK(12) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC4_MASK BIT_MASK(13) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC5_MASK BIT_MASK(14) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL1_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL2_MASK BIT_MASK(16) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL3_MASK BIT_MASK(17) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL4_MASK BIT_MASK(18) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL5_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM1_MASK BIT_MASK(20) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM2_MASK BIT_MASK(21) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM3_MASK BIT_MASK(22) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM4_MASK BIT_MASK(23) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM5_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER_MASK BIT_MASK(25) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT_MASK BIT_MASK(26) +#define CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK BIT_MASK(27) +#define CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK BIT_MASK(28) +#define CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK BIT_MASK(30) + +#define CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK GENMASK(12, 0) +#define CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK BIT_MASK(13) +#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT_MASK(14) +#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT_MASK(15) + +#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT_MASK(0) +#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT_MASK(1) +#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT_MASK(2) +#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT_MASK(3) +#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT_MASK(4) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT_MASK(5) +#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT_MASK(8) +#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT_MASK(9) +#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT_MASK(10) +#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT_MASK(11) +#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT_MASK(12) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT_MASK(13) +#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT_MASK(16) +#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT_MASK(17) +#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT_MASK(18) +#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT_MASK(19) +#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT_MASK(20) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT_MASK(21) +#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT_MASK(24) +#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT_MASK(25) +#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT_MASK(26) +#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT_MASK(27) +#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT_MASK(28) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT_MASK(29) + +#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0) +#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6) +#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8) +#define CAL_CSI2_CTX_ATT_MASK BIT_MASK(13) +#define CAL_CSI2_CTX_ATT_PIX 0 +#define CAL_CSI2_CTX_ATT 1 +#define CAL_CSI2_CTX_PACK_MODE_MASK BIT_MASK(14) +#define CAL_CSI2_CTX_PACK_MODE_LINE 0 +#define CAL_CSI2_CTX_PACK_MODE_FRAME 1 +#define CAL_CSI2_CTX_LINES_MASK GENMASK(29, 16) + +#define CAL_CSI2_STATUS_FRAME_MASK GENMASK(15, 0) + +#define CAL_CSI2_PHY_REG0_THS_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG0_THS_TERM_MASK GENMASK(15, 8) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK BIT_MASK(24) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE 1 +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_ENABLE 0 + +#define CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK GENMASK(9, 8) +#define CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK GENMASK(17, 10) +#define CAL_CSI2_PHY_REG1_TCLK_TERM_MASK GENMASK(24, 18) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_MASK BIT_MASK(25) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_ERROR 1 +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_SUCCESS 0 +#define CAL_CSI2_PHY_REG1_RESET_DONE_STATUS_MASK GENMASK(29, 28) + +#define CAL_CSI2_PHY_REG2_CCP2_SYNC_PATTERN_MASK GENMASK(23, 0) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK GENMASK(25, 24) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK GENMASK(27, 26) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK GENMASK(29, 28) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK GENMASK(31, 30) + +#define CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK BIT_MASK(0) +#define CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK GENMASK(2, 1) +#define CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK GENMASK(4, 3) +#define CM_CAMERRX_CTRL_CSI1_MODE_MASK BIT_MASK(5) +#define CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK BIT_MASK(10) +#define CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK GENMASK(12, 11) +#define CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK GENMASK(16, 13) +#define CM_CAMERRX_CTRL_CSI0_MODE_MASK BIT_MASK(17) + +#endif -- cgit v1.2.3 From 80100fd9ebb9f2414892a1178d26a4253e6c0bcf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 11 Jan 2016 11:21:15 -0200 Subject: [media] media: v4l: Dual license v4l2-common.h under GPL v2 and BSD licenses The v4l2-common.h user space header was split off from videodev2.h, but the dual licensing of the videodev2.h (as well as other V4L2 headers) was missed. Change the license of the v4l2-common.h from GNU GPL v2 to both GNU GPL v2 and BSD. Sakari Ailus : > Would you approve a license change of the patches to > include/uapi/linux/v4l2-common.h (formerly include/linux/v4l2-common.h) you > or your company have contributed from GNU GPL v2 to dual GNU GPL v2 and BSD > licenses, changing the copyright notice in the file as below (from > videodev2.h): > > -------------8<------------ > * 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. > * > * This program is distributed in the hope that it will be useful, > * but WITHOUT ANY WARRANTY; without even the implied warranty of > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details. > * > * Alternatively you can redistribute this file under the terms of the > * BSD license as stated below: > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * 3. The names of its contributors may not be used to endorse or promote > * products derived from this software without specific prior written > * permission. > * > * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED > * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR > * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS > * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > -------------8<------------ Mauro Carvalho Chehab : > No problem from my side. Hans Verkuil : > Acked-by: Hans Verkuil Aaro Koskinen : > This fine also for us. > > Acked-by: Aaro Koskinen Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Acked-by: Aaro Koskinen Acked-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/v4l2-common.h | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/v4l2-common.h b/include/uapi/linux/v4l2-common.h index 15273987093e..5b3f685a2d50 100644 --- a/include/uapi/linux/v4l2-common.h +++ b/include/uapi/linux/v4l2-common.h @@ -10,19 +10,43 @@ * Copyright (C) 2012 Nokia Corporation * Contact: Sakari Ailus * - * 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. + * 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. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -- cgit v1.2.3 From 3f1321cbaa1f2221be7444b7fab0905a31bdfd9f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve nvt_hw_detect Check for the case that no Nuvoton chip is found on either EFM port. Also move the position of nvt_efm_disable to reduce the time the EFM ports are locked. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 17 +++++++++++++---- drivers/media/rc/nuvoton-cir.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5790ee46a38d..f587a727df2e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -291,7 +291,7 @@ static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id) /* detect hardware features */ -static void nvt_hw_detect(struct nvt_dev *nvt) +static int nvt_hw_detect(struct nvt_dev *nvt) { const char *chip_name; int chip_id; @@ -306,10 +306,17 @@ static void nvt_hw_detect(struct nvt_dev *nvt) nvt_efm_enable(nvt); nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); } - nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); + nvt_efm_disable(nvt); + chip_id = nvt->chip_major << 8 | nvt->chip_minor; + if (chip_id == NVT_INVALID) { + dev_err(&nvt->pdev->dev, + "No device found on either EFM port\n"); + return -ENODEV; + } + chip_name = nvt_find_chip(nvt, chip_id); /* warn, but still let the driver load, if we don't know this chip */ @@ -322,7 +329,7 @@ static void nvt_hw_detect(struct nvt_dev *nvt) "found %s or compatible: chip id: 0x%02x 0x%02x", chip_name, nvt->chip_major, nvt->chip_minor); - nvt_efm_disable(nvt); + return 0; } static void nvt_cir_ldev_init(struct nvt_dev *nvt) @@ -1057,7 +1064,9 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) init_waitqueue_head(&nvt->tx.queue); - nvt_hw_detect(nvt); + ret = nvt_hw_detect(nvt); + if (ret) + goto exit_free_dev_rdev; /* Initialize CIR & CIR Wake Logical Devices */ nvt_efm_enable(nvt); diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 6a3de08a17c0..48c09c7a101c 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -68,7 +68,8 @@ enum nvt_chip_ver { NVT_W83667HG = 0xa510, NVT_6775F = 0xb470, NVT_6776F = 0xc330, - NVT_6779D = 0xc560 + NVT_6779D = 0xc560, + NVT_INVALID = 0xffff, }; struct nvt_chip { -- cgit v1.2.3 From fb2b0065756a5ed6b6852e663574f9331d47fdec Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:36 -0200 Subject: [media] media: rc: nuvoton-cir: add locking to calls of nvt_enable_wake Add locking to nvt_enable_wake calls. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f587a727df2e..3097ff0eb176 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1174,16 +1174,16 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) nvt_dbg("%s called", __func__); - /* zero out misc state tracking */ - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->study_state = ST_STUDY_NONE; - nvt->wake_state = ST_WAKE_NONE; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - spin_lock_irqsave(&nvt->tx.lock, flags); nvt->tx.tx_state = ST_TX_NONE; spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->nvt_lock, flags); + + /* zero out misc state tracking */ + nvt->study_state = ST_STUDY_NONE; + nvt->wake_state = ST_WAKE_NONE; + /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -1193,6 +1193,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* make sure wake is enabled */ nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + return 0; } @@ -1211,7 +1213,11 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit v1.2.3 From 88205f01fe30590d04c81f09f003af8c2cf6aeaf Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:00 -0200 Subject: [media] media: rc: nuvoton-cir: fix wakeup interrupt bits Most likely a copy & paste error. The wakeup interrupt supports less triggering events. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 48c09c7a101c..4a5650dffa29 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -293,10 +293,7 @@ struct nvt_dev { #define CIR_WAKE_IREN_RTR 0x40 #define CIR_WAKE_IREN_PE 0x20 #define CIR_WAKE_IREN_RFO 0x10 -#define CIR_WAKE_IREN_TE 0x08 -#define CIR_WAKE_IREN_TTR 0x04 -#define CIR_WAKE_IREN_TFU 0x02 -#define CIR_WAKE_IREN_GH 0x01 +#define CIR_WAKE_IREN_GH 0x08 /* CIR WAKE FIFOCON settings */ #define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 -- cgit v1.2.3 From d42fd29769f52c056032bbf1b9b2d1d914fd145a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:51 -0200 Subject: [media] media: rc: nuvoton-cir: fix interrupt handling Only handle an interrupt if at least one combination of event bit and related interrupt bit is set. Previously it was just checked that at least one event bit and at least one interrupt bit are set. This fixes issues like the following which was caused by interrupt sharing: An interrupt intended for nvt_cir_isr was handled by nvt_cir_wake_isr first and because status bit CIR_WAKE_IRSTS_IR_PENDING was set the wake fifo was accidently cleared. This patch also fixes the bug that nvt_cir_wake_isr returned IRQ_HANDLED even if it detected that the (shared) interrupt was meant for another handler. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 3097ff0eb176..291d870e618f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -825,9 +825,13 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * 0: CIR_IRSTS_GH - Min Length Detected */ status = nvt_cir_reg_read(nvt, CIR_IRSTS); - if (!status) { + iren = nvt_cir_reg_read(nvt, CIR_IREN); + + /* IRQ may be shared with CIR WAKE, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) { nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); return IRQ_NONE; } @@ -835,13 +839,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_cir_reg_write(nvt, status, CIR_IRSTS); nvt_cir_reg_write(nvt, 0, CIR_IRSTS); - /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - if (!iren) { - nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_NONE; - } - nvt_cir_log_irqs(status, iren); if (status & CIR_IRSTS_RTR) { @@ -914,7 +911,12 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); - if (!status) + iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); + + /* IRQ may be shared with CIR, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) return IRQ_NONE; if (status & CIR_WAKE_IRSTS_IR_PENDING) @@ -923,13 +925,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); - /* Interrupt may be shared with CIR, bail if Wake not enabled */ - iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); - if (!iren) { - nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_HANDLED; - } - if ((status & CIR_WAKE_IRSTS_PE) && (nvt->wake_state == ST_WAKE_START)) { while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { -- cgit v1.2.3 From e60c1e87c76068c3756369048cd63ed6e55b0155 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:46:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve locking in both interrupt handlers Extend the locking to protect more critical actions like register accesses in the interrupt handlers. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 291d870e618f..d428b4e6e26f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -727,7 +727,6 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) /* copy data from hardware rx fifo into driver buffer */ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) { - unsigned long flags; u8 fifocount, val; unsigned int b_idx; bool overrun = false; @@ -746,8 +745,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); - spin_lock_irqsave(&nvt->nvt_lock, flags); - b_idx = nvt->pkts; /* This should never happen, but lets check anyway... */ @@ -769,8 +766,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) if (overrun) nvt_handle_rx_fifo_overrun(nvt); - - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static void nvt_cir_log_irqs(u8 status, u8 iren) @@ -811,6 +806,8 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* * Get IR Status register contents. Write 1 to ack/clear * @@ -831,6 +828,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * status bit whether the related interrupt source is enabled */ if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); return IRQ_NONE; } @@ -852,16 +850,14 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) if (nvt_cir_tx_inactive(nvt)) nvt_get_rx_ir_data(nvt); - spin_lock_irqsave(&nvt->nvt_lock, flags); - cur_state = nvt->study_state; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - if (cur_state == ST_STUDY_NONE) nvt_clear_cir_fifo(nvt); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + if (status & CIR_IRSTS_TE) nvt_clear_tx_fifo(nvt); @@ -910,14 +906,18 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); /* IRQ may be shared with CIR, therefore check for each * status bit whether the related interrupt source is enabled */ - if (!(status & iren)) + if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); return IRQ_NONE; + } if (status & CIR_WAKE_IRSTS_IR_PENDING) nvt_clear_cir_wake_fifo(nvt); @@ -933,11 +933,11 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) } nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt->wake_state = ST_WAKE_FINISH; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + nvt_dbg_wake("%s done", __func__); return IRQ_HANDLED; } -- cgit v1.2.3 From 9398ddfe4ef38f26b8e25f510c5f6ffe01698e8b Mon Sep 17 00:00:00 2001 From: Andrei Koshkosh Date: Sun, 3 Jan 2016 23:31:26 -0200 Subject: [media] si2157.c: fix frequency range According with: https://www.silabs.com/Support%20Documents/TechnicalDocs/Si2157-short.pdf The RF input frequency range of this demod is from 42MHz to 870 MHz. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 0e1ca2b00e61..5da5b421d310 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -364,8 +364,8 @@ static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) static const struct dvb_tuner_ops si2157_ops = { .info = { .name = "Silicon Labs Si2146/2147/2148/2157/2158", - .frequency_min = 55000000, - .frequency_max = 862000000, + .frequency_min = 42000000, + .frequency_max = 870000000, }, .init = si2157_init, -- cgit v1.2.3 From 93b66420a4eb846ed8859d25c0a2056486f2929d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:32:51 -0200 Subject: [media] dw2102: Add support for Terratec Cinergy S2 USB BOX The Terratec Cinergy S2 USB BOX uses a Montage M88TS2022 tuner and a M88DS3103 demodulator, same as Technotrend TT-connect S2-4600. This patch adds the missing USB Product ID to make it work. Signed-off-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index bc19da5ad3b7..dd46d6c78c4e 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1688,6 +1688,7 @@ enum dw2102_table_entry { TECHNOTREND_S2_4600, TEVII_S482_1, TEVII_S482_2, + TERRATEC_CINERGY_S2_BOX, }; static struct usb_device_id dw2102_table[] = { @@ -1715,6 +1716,7 @@ static struct usb_device_id dw2102_table[] = { USB_PID_TECHNOTREND_CONNECT_S2_4600)}, [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, [TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)}, + [TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)}, { } }; @@ -2232,7 +2234,7 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { } }, } }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "TechnoTrend TT-connect S2-4600", { &dw2102_table[TECHNOTREND_S2_4600], NULL }, @@ -2246,6 +2248,10 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { { &dw2102_table[TEVII_S482_2], NULL }, { NULL }, }, + { "Terratec Cinergy S2 USB BOX", + { &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL }, + { NULL }, + }, } }; -- cgit v1.2.3 From b8278f8b961a6a65a4939f646483866fb5bef112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6schel?= Date: Mon, 4 Jan 2016 19:16:55 -0200 Subject: [media] af9035: add support for 2nd tuner of MSI DigiVox Diversity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIP tested with VLC. Diversity tested with the Windows driver. Signed-off-by: Stefan Pöschel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 4 ++-- drivers/media/usb/dvb-usb-v2/af9035.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 6e02a15d39ce..b3c09fe54d9b 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -684,7 +684,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) { + if (tmp == 1 || tmp == 3 || tmp == 5) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -823,7 +823,7 @@ static int af9035_read_config(struct dvb_usb_device *d) if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) + if (tmp == 1 || tmp == 3 || tmp == 5) state->dual_mode = true; dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 416a97f05ec8..df22001f9e41 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -112,9 +112,10 @@ static const u32 clock_lut_it9135[] = { * 0 TS * 1 DCA + PIP * 3 PIP + * 5 DCA + PIP * n DCA * - * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. + * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS. */ #define EEPROM_BASE_AF9035 0x42fd -- cgit v1.2.3 From d309c8bb70beef4128a78d5208e692800c68b8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Jansson?= Date: Wed, 6 Jan 2016 14:26:31 -0200 Subject: [media] dvb-usb-dvbsky: add new product id for TT CT2-4650 CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new product id to dvb-usb-dvbsky for new version of TechnoTrend CT2-4650 CI Signed-off-by: Torbjörn Jansson Reviewed-by: Olli Salonen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/dvbsky.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 750d23f9928d..dbdbb84294c5 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -248,6 +248,7 @@ #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d #define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012 +#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2 0x3015 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 2d922b96ed83..02dbc6c45423 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -847,6 +847,10 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TECHNOTREND, + USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2, + &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1", + RC_MAP_TT_1500) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", -- cgit v1.2.3 From 4c7cad4bbf718e73a49e236e2b79489f1ee83810 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 7 Jan 2016 06:35:21 -0200 Subject: [media] rtl28xxu: retry failed i2c messages Sometimes i2c transfer fails. That happens especially when large amount of data is written sequentially eg. firmware download. Problem arises with both integrated rtl2832 demod and external mn88472 demod, which is clear indicator it is busy i2c bus issue. Use i2c core retry logic in order fix the issue by repeating failed message. Another solution which also works is to add ~100us delay between i2c messages - but repeating sounds more elegant and does not cause any extra delay for success cases. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index eb5787a3191e..c4c6e92e8643 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -259,6 +259,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EOPNOTSUPP; } + /* Retry failed I2C messages */ + if (ret == -EPIPE) + ret = -EAGAIN; + err_mutex_unlock: mutex_unlock(&d->i2c_mutex); @@ -619,6 +623,10 @@ static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name) } dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id); + /* Retry failed I2C messages */ + d->i2c_adap.retries = 1; + d->i2c_adap.timeout = msecs_to_jiffies(10); + return WARM; err: dev_dbg(&d->intf->dev, "failed=%d\n", ret); -- cgit v1.2.3 From 631c694f7d7e17147bcf6c7c3669c8f4dc84cc09 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:45 -0200 Subject: [media] af9013: cancel_delayed_work_sync before device removal / kfree af9013_remove was calling kfree(state) with possibly still active schedule_delayed_work(&state->statistics_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9013.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index e23197da84af..41ab5defb798 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1344,6 +1344,10 @@ err: static void af9013_release(struct dvb_frontend *fe) { struct af9013_state *state = fe->demodulator_priv; + + /* stop statistics polling */ + cancel_delayed_work_sync(&state->statistics_work); + kfree(state); } -- cgit v1.2.3 From 4bdcaa054e1c73697b390c32c434d96836121306 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:46 -0200 Subject: [media] af9033: cancel_delayed_work_sync before device removal / kfree af9033_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9033.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index bc35206a0821..8b328d1ca8d3 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -1372,6 +1372,9 @@ static int af9033_remove(struct i2c_client *client) dev_dbg(&dev->client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + dev->fe.ops.release = NULL; dev->fe.demodulator_priv = NULL; kfree(dev); -- cgit v1.2.3 From 01d1d714e26624bc50ba95c49cf6e15bb215c150 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:43 -0200 Subject: [media] si2157: cancel_delayed_work_sync before device removal / kfree si2157_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). This caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 5da5b421d310..3450dfb7c427 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -458,6 +458,9 @@ static int si2157_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = NULL; kfree(dev); -- cgit v1.2.3 From 4fd57ed61564bd4706e71cfd8c5a259079ddabf3 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:47 -0200 Subject: [media] rtl2830: cancel_delayed_work_sync before device removal / kfree rtl2830_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index b792f305cf15..74b771218033 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -900,6 +900,9 @@ static int rtl2830_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + i2c_del_mux_adapter(dev->adapter); regmap_exit(dev->regmap); kfree(dev); -- cgit v1.2.3 From 41ff9142df375ac319b1d9fe50d88e4247da6f1a Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:44 -0200 Subject: [media] ts2020: cancel_delayed_work_sync before device removal / kfree ts2020_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/ts2020.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index 7979e5d6498b..14b410ffe612 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -712,6 +712,10 @@ static int ts2020_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + if (!dev->dont_poll) + cancel_delayed_work_sync(&dev->stat_work); + regmap_exit(dev->regmap); kfree(dev); return 0; -- cgit v1.2.3 From df47512d59c0db59a6785f0208001a4b7dd90aaf Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 10 Jan 2016 05:20:16 -0200 Subject: [media] netup_unidvb: Remove a useless memset This memory is allocated using kzalloc so there is no need to call memset(..., 0, ...) [mchehab@osg.samsung.com: as suggested by Joe Perches, It's unusual to not see the alloc above the if, removed a blank line between kzalloc/if and added a blank line after if] Signed-off-by: Christophe JAILLET Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 525ebfefeee8..c94cecd2aa40 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -771,10 +771,9 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, /* allocate device context */ ndev = kzalloc(sizeof(*ndev), GFP_KERNEL); - if (!ndev) goto dev_alloc_err; - memset(ndev, 0, sizeof(*ndev)); + ndev->old_fw = old_firmware; ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME); if (!ndev->wq) { -- cgit v1.2.3 From 417b552331df8181e8033503c1cb2749290073e7 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 11 Jan 2016 00:13:20 -0200 Subject: [media] rcar_jpu: Add R-Car Gen2 Fallback Compatibility String Add fallback compatibility string. This is in keeping with the fallback scheme being adopted wherever appropriate for drivers for Renesas SoCs. Signed-off-by: Simon Horman Acked-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,jpu.txt | 13 +++++++------ drivers/media/platform/rcar_jpu.c | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,jpu.txt b/Documentation/devicetree/bindings/media/renesas,jpu.txt index 0cb94201bf92..d3436e5190f9 100644 --- a/Documentation/devicetree/bindings/media/renesas,jpu.txt +++ b/Documentation/devicetree/bindings/media/renesas,jpu.txt @@ -5,11 +5,12 @@ and decoding function conforming to the JPEG baseline process, so that the JPU can encode image data and decode JPEG data quickly. Required properties: - - compatible: should containg one of the following: - - "renesas,jpu-r8a7790" for R-Car H2 - - "renesas,jpu-r8a7791" for R-Car M2-W - - "renesas,jpu-r8a7792" for R-Car V2H - - "renesas,jpu-r8a7793" for R-Car M2-N +- compatible: "renesas,jpu-", "renesas,rcar-gen2-jpu" as fallback. + Examples with soctypes are: + - "renesas,jpu-r8a7790" for R-Car H2 + - "renesas,jpu-r8a7791" for R-Car M2-W + - "renesas,jpu-r8a7792" for R-Car V2H + - "renesas,jpu-r8a7793" for R-Car M2-N - reg: Base address and length of the registers block for the JPU. - interrupts: JPU interrupt specifier. @@ -17,7 +18,7 @@ Required properties: Example: R8A7790 (R-Car H2) JPU node jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7790"; + compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; reg = <0 0xfe980000 0 0x10300>; interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7790_CLK_JPU>; diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 485f5259acb0..552789a69c86 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -1613,6 +1613,7 @@ static const struct of_device_id jpu_dt_ids[] = { { .compatible = "renesas,jpu-r8a7791" }, /* M2-W */ { .compatible = "renesas,jpu-r8a7792" }, /* V2H */ { .compatible = "renesas,jpu-r8a7793" }, /* M2-N */ + { .compatible = "renesas,rcar-gen2-jpu" }, { }, }; MODULE_DEVICE_TABLE(of, jpu_dt_ids); -- cgit v1.2.3 From 8aeec38f9c61b4dfdfd2a4a74d111590b4b83230 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Jan 2016 02:07:42 -0200 Subject: [media] v4l: Merge the YUV and YVU 4:2:0 tri-planar non-contiguous formats docs The two formats are very similar, having two separate pages to describe them is overkill. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml | 26 ++-- Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml | 154 --------------------- Documentation/DocBook/media/v4l/pixfmt.xml | 1 - 3 files changed, 17 insertions(+), 164 deletions(-) delete mode 100644 Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml index e781cc61786c..7d13fe96657d 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml @@ -1,35 +1,43 @@ - + - V4L2_PIX_FMT_YUV420M ('YM12') + V4L2_PIX_FMT_YUV420M ('YM12'), V4L2_PIX_FMT_YVU420M ('YM21') &manvol; - V4L2_PIX_FMT_YUV420M - Variation of V4L2_PIX_FMT_YUV420 - with planes non contiguous in memory. + V4L2_PIX_FMT_YUV420M + V4L2_PIX_FMT_YVU420M + Variation of V4L2_PIX_FMT_YUV420 and + V4L2_PIX_FMT_YVU420 with planes non contiguous + in memory. Description This is a multi-planar format, as opposed to a packed format. -The three components are separated into three sub- images or planes. +The three components are separated into three sub-images or planes. -The Y plane is first. The Y plane has one byte per pixel. The Cb data + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV420M the Cb data constitutes the second plane which is half the width and half the height of the Y plane (and of the image). Each Cb belongs to four pixels, a two-by-two square of the image. For example, Cb0 belongs to Y'00, Y'01, Y'10, and Y'11. The Cr data, just like the Cb plane, is -in the third plane. +in the third plane. + + V4L2_PIX_FMT_YVU420M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + If the Y plane has pad bytes after each row, then the Cb and Cr planes have half as many pad bytes after their rows. In other words, two Cx rows (including padding) is exactly as long as one Y row (including padding). - V4L2_PIX_FMT_YUV420M is intended to be + V4L2_PIX_FMT_YUV420M and +V4L2_PIX_FMT_YVU420M are intended to be used only in drivers and applications that support the multi-planar API, described in . diff --git a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml deleted file mode 100644 index 2330667907c7..000000000000 --- a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - V4L2_PIX_FMT_YVU420M ('YM21') - &manvol; - - - V4L2_PIX_FMT_YVU420M - Variation of V4L2_PIX_FMT_YVU420 - with planes non contiguous in memory. - - - - Description - - This is a multi-planar format, as opposed to a packed format. -The three components are separated into three sub-images or planes. - -The Y plane is first. The Y plane has one byte per pixel. The Cr data -constitutes the second plane which is half the width and half -the height of the Y plane (and of the image). Each Cr belongs to four -pixels, a two-by-two square of the image. For example, -Cr0 belongs to Y'00, -Y'01, Y'10, and -Y'11. The Cb data, just like the Cr plane, constitutes -the third plane. - - If the Y plane has pad bytes after each row, then the Cr -and Cb planes have half as many pad bytes after their rows. In other -words, two Cx rows (including padding) is exactly as long as one Y row -(including padding). - - V4L2_PIX_FMT_YVU420M is intended to be -used only in drivers and applications that support the multi-planar API, -described in . - - - <constant>V4L2_PIX_FMT_YVU420M</constant> 4 × 4 -pixel image - - - Byte Order. - Each cell is one byte. - - - - - - start0 + 0: - Y'00 - Y'01 - Y'02 - Y'03 - - - start0 + 4: - Y'10 - Y'11 - Y'12 - Y'13 - - - start0 + 8: - Y'20 - Y'21 - Y'22 - Y'23 - - - start0 + 12: - Y'30 - Y'31 - Y'32 - Y'33 - - - - start1 + 0: - Cr00 - Cr01 - - - start1 + 2: - Cr10 - Cr11 - - - - start2 + 0: - Cb00 - Cb01 - - - start2 + 2: - Cb10 - Cb11 - - - - - - - - - Color Sample Location. - - - - - - - 01 - 23 - - - 0 - YY - YY - - - - C - C - - - 1 - YY - YY - - - - - - 2 - YY - YY - - - - C - C - - - 3 - YY - YY - - - - - - - - - diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index d871245d2973..9e77ff353feb 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -1628,7 +1628,6 @@ information. &sub-y41p; &sub-yuv420; &sub-yuv420m; - &sub-yvu420m; &sub-yuv410; &sub-yuv422p; &sub-yuv411p; -- cgit v1.2.3 From f7842cfd3cab4566b28ede860344fcf8a7b409f6 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:09 -0200 Subject: [media] v4l: of: Correct v4l2_of_parse_endpoint() kernel-doc The v4l2_of_parse_endpoint function kernel-doc says that the return value is always 0. But that is not true since the function can fail and a error negative code is returned on failure. So correct the kernel-doc to match. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index b27cbb1f5afe..93b33681776c 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -146,7 +146,7 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, * variable without a low fixed limit. Please use * v4l2_of_alloc_parse_endpoint() in new drivers instead. * - * Return: 0. + * Return: 0 on success or a negative error code on failure. */ int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) -- cgit v1.2.3 From 7f6cd6c40d7bf3c640294359a8a835d03c94d634 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:10 -0200 Subject: [media] adv7604: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 5d4dbd05f9d6..801a9b09d5e5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2820,6 +2820,7 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) struct device_node *endpoint; struct device_node *np; unsigned int flags; + int ret; u32 v; np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node; @@ -2829,7 +2830,11 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) if (!endpoint) return -EINVAL; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); + ret = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + if (ret) { + of_node_put(endpoint); + return ret; + } if (!of_property_read_u32(endpoint, "default-input", &v)) state->pdata.default_input = v; -- cgit v1.2.3 From fda8b13ddce96335de2c6ae46bd3b14829318afe Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:11 -0200 Subject: [media] s5c73m3: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 57b3d27993a4..08af58fb8e7d 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1639,8 +1639,10 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) return 0; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; if (ep.bus_type != V4L2_MBUS_CSI2) { dev_err(dev, "unsupported bus type\n"); -- cgit v1.2.3 From 2388309c7480550e64e20221640f6a5c717be662 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:12 -0200 Subject: [media] s5k5baf: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k5baf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index fc3a5a8e6c9c..db82ed05792e 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1868,8 +1868,11 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) return -EINVAL; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; + state->bus_type = ep.bus_type; switch (state->bus_type) { -- cgit v1.2.3 From fe1e6ac6145b82f17c19653fc6bde626dfd8d861 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:13 -0200 Subject: [media] tvp514x: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 7fa5f1e4fe37..7cdd94842938 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1001,7 +1001,7 @@ static struct tvp514x_decoder tvp514x_dev = { static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { - struct tvp514x_platform_data *pdata; + struct tvp514x_platform_data *pdata = NULL; struct v4l2_of_endpoint bus_cfg; struct device_node *endpoint; unsigned int flags; @@ -1013,11 +1013,13 @@ tvp514x_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit v1.2.3 From baf40b5f79e0d8579cef5beaa18a91980dc77bfd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:14 -0200 Subject: [media] tvp7002: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 83c79fa5f61d..4df640c3aa40 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -894,7 +894,7 @@ static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { struct v4l2_of_endpoint bus_cfg; - struct tvp7002_config *pdata; + struct tvp7002_config *pdata = NULL; struct device_node *endpoint; unsigned int flags; @@ -905,11 +905,13 @@ tvp7002_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit v1.2.3 From 234eab8407afbedb4428012f8292357db75e24cd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:15 -0200 Subject: [media] exynos4-is: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 8 +++++++- drivers/media/platform/exynos4-is/mipi-csis.c | 10 +++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f3b2dd30ec77..662d4a5c584e 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -332,13 +332,19 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *ep, *np; struct v4l2_of_endpoint endpoint; + int ret; /* Assume here a port node can have only one endpoint node. */ ep = of_get_next_child(port, NULL); if (!ep) return 0; - v4l2_of_parse_endpoint(ep, &endpoint); + ret = v4l2_of_parse_endpoint(ep, &endpoint); + if (ret) { + of_node_put(ep); + return ret; + } + if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) return -EINVAL; diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index ac5e50e595be..bd5c46c3d4b7 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -736,6 +736,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, { struct device_node *node = pdev->dev.of_node; struct v4l2_of_endpoint endpoint; + int ret; if (of_property_read_u32(node, "clock-frequency", &state->clk_frequency)) @@ -751,7 +752,9 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, return -EINVAL; } /* Get port node and validate MIPI-CSI channel id. */ - v4l2_of_parse_endpoint(node, &endpoint); + ret = v4l2_of_parse_endpoint(node, &endpoint); + if (ret) + goto err; state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; if (state->index >= CSIS_MAX_ENTITIES) @@ -764,9 +767,10 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, "samsung,csis-wclk"); state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes; - of_node_put(node); - return 0; +err: + of_node_put(node); + return ret; } static int s5pcsis_pm_resume(struct device *dev, bool runtime); -- cgit v1.2.3 From c517b35211aed34cb7c78d508a0b9fb209fd60c9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:16 -0200 Subject: [media] omap3isp: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 67efa9ea551e..f9e5245f26ac 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2235,8 +2235,11 @@ static int isp_of_parse_node(struct device *dev, struct device_node *node, struct isp_bus_cfg *buscfg = &isd->bus; struct v4l2_of_endpoint vep; unsigned int i; + int ret; - v4l2_of_parse_endpoint(node, &vep); + ret = v4l2_of_parse_endpoint(node, &vep); + if (ret) + return ret; dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name, vep.base.port); -- cgit v1.2.3 From c89f8d47a171243fcac56b136e8526189035f8ee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 12:23:51 -0200 Subject: [media] s5c73m3: remove duplicate module device table Clang complains about an extraneous definition of the module device table after the patch to add it was accidentally merged twice: ../drivers/media/i2c/s5c73m3/s5c73m3-spi.c:40:1: error: redefinition of '__mod_of__s5c73m3_spi_ids_device_table' MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); ^ ../include/linux/module.h:223:27: note: expanded from macro 'MODULE_DEVICE_TABLE' extern const typeof(name) __mod_##type##__##name##_device_table \ ^ :99:1: note: expanded from here __mod_of__s5c73m3_spi_ids_device_table This removes the second definition. Fixes: f934a94bb566 ("[media] s5c73m3: Export OF module alias information") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 7d65b36434b1..72ef9f936e6c 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -37,7 +37,6 @@ enum spi_direction { SPI_DIR_RX, SPI_DIR_TX }; -MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len, enum spi_direction dir) -- cgit v1.2.3 From 7445e45d19a09e5269dc85f17f9635be29d2f76c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 22 Jan 2016 08:53:55 -0200 Subject: [media] pwc: Add USB id for Philips Spc880nc webcam SPC 880NC PC camera discussions: http://www.pclinuxos.com/forum/index.php/topic,135688.0.html Cc: stable@vger.kernel.org Reported-by: Kikim Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pwc/pwc-if.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 086cf1c7bd7d..18aed5dd325e 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -91,6 +91,7 @@ static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ + { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ @@ -810,6 +811,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id name = "Philips SPC 900NC webcam"; type_id = 740; break; + case 0x032C: + PWC_INFO("Philips SPC 880NC USB webcam detected.\n"); + name = "Philips SPC 880NC webcam"; + type_id = 740; + break; default: return -ENODEV; break; -- cgit v1.2.3 From eac287adb305820661f528e35a50bd54d7c515f1 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:15:00 -0200 Subject: [media] dvbdev: remove useless parentheses after return The parentheses are not required after return, and just remove it. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a7de62ebc415..a48421e96b5e 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -352,7 +352,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, ret = media_device_register_entity(dvbdev->adapter->mdev, dvbdev->entity); if (ret) - return (ret); + return ret; printk(KERN_DEBUG "%s: media entity '%s' registered.\n", __func__, dvbdev->entity->name); -- cgit v1.2.3 From 5c3fbc5e033ae2e089883c7294304a9a5bf404b2 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:58 -0200 Subject: [media] dvbdev: replace kcalloc with kzalloc Since the number of elements equals to 1, so just use kzalloc to simplify the code and make it more readable. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a48421e96b5e..9fd687a1f593 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -620,8 +620,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, return -ENOMEM; adap->conn = conn; - adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads), - GFP_KERNEL); + adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); if (!adap->conn_pads) return -ENOMEM; -- cgit v1.2.3 From 0ede1876f7eb43ee6a47f5081d8902db6dd8b4ab Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:59 -0200 Subject: [media] dvbdev: the space is required after ',' The space is missing after ',', and this will be introduce much noise when checking new patch around them. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 9fd687a1f593..1b9732ee0a4f 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -58,7 +58,7 @@ static const char * const dnames[] = { #define DVB_MAX_IDS MAX_DVB_MINORS #else #define DVB_MAX_IDS 4 -#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) #endif @@ -85,7 +85,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->private_data = dvbdev; replace_fops(file, new_fops); if (file->f_op->open) - err = file->f_op->open(inode,file); + err = file->f_op->open(inode, file); up_read(&minor_rwsem); mutex_unlock(&dvbdev_mutex); return err; @@ -867,7 +867,7 @@ int dvb_usercopy(struct file *file, parg = sbuf; } else { /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (NULL == mbuf) return -ENOMEM; parg = mbuf; -- cgit v1.2.3 From 458a39523542c4479a69b98743436fb761f03796 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Mon, 25 Jan 2016 13:21:37 -0200 Subject: [media] media: platform: exynos4-is: media-dev: Add missing of_node_put for_each_available_child_of_node and for_each_child_of_node perform an of_node_get on each iteration, so to break out of the loop an of_node_put is required. Found using Coccinelle. The simplified version of the semantic patch that is used for this is as follows: // @@ local idexpression n; expression e,r; @@ for_each_available_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 662d4a5c584e..26a4e5c7b47a 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -435,8 +435,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) continue; ret = fimc_md_parse_port_node(fmd, port, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); goto rpm_put; + } index++; } @@ -447,8 +449,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) for_each_child_of_node(ports, node) { ret = fimc_md_parse_port_node(fmd, node, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } index++; } rpm_put: @@ -656,8 +660,10 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd, ret = fimc_md_register_platform_entity(fmd, pdev, plat_entity); put_device(&pdev->dev); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } } return ret; -- cgit v1.2.3 From b97baa3e22e18dac42001e665cf27ad1211bf878 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:56 -0200 Subject: [media] hdpvr: hide unused variable The i2c client pointer is only used when CONFIG_I2C is set, and otherwise produces a compile-time warning: drivers/media/usb/hdpvr/hdpvr-core.c: In function 'hdpvr_probe': drivers/media/usb/hdpvr/hdpvr-core.c:276:21: error: unused variable 'client' [-Werror=unused-variable] This uses the same #ifdef to hide the variable when the code using it is hidden. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 3fc64197b4e6..08f0ca7aa012 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -273,7 +273,9 @@ static int hdpvr_probe(struct usb_interface *interface, struct hdpvr_device *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; +#if IS_ENABLED(CONFIG_I2C) struct i2c_client *client; +#endif size_t buffer_size; int i; int retval = -ENOMEM; -- cgit v1.2.3 From 733d0def3ebdd1d088330d904149af21fa4b9ae2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:58 -0200 Subject: [media] b2c2: flexcop: avoid unused function warnings The flexcop driver has two functions that are normally used, except when multiple frontend drivers are disabled: drivers/media/common/b2c2/flexcop-fe-tuner.c:42:12: warning: 'flexcop_set_voltage' defined but not used [-Wunused-function] drivers/media/common/b2c2/flexcop-fe-tuner.c:71:12: warning: 'flexcop_sleep' defined but not used [-Wunused-function] This avoids the build warning by updating the #ifdef for flexcop_set_voltage to the exact condition under which it is used. For flexcop_sleep, the condition is rather complex, so I resort to marking it as __maybe_unused, so the compiler can silently drop it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/b2c2/flexcop-fe-tuner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c index 9c59f4306883..f5956402fc69 100644 --- a/drivers/media/common/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c @@ -38,7 +38,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend *fe, #endif /* lnb control */ -#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) +#if (FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)) && FE_SUPPORTED(PLL) static int flexcop_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { @@ -68,7 +68,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, #endif #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) -static int flexcop_sleep(struct dvb_frontend* fe) +static int __maybe_unused flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; if (fc->fe_sleep) -- cgit v1.2.3 From 7c8fe516bd81d991feb73ccd969ec29850af3013 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 19:46:02 -0200 Subject: [media] v4l: remove MEDIA_TUNER dependency for VIDEO_TUNER em28xx selects VIDEO_TUNER, which has a dependency on MEDIA_TUNER, so we get a Kconfig warning if that is disabled: warning: (VIDEO_PVRUSB2 && VIDEO_USBVISION && VIDEO_GO7007 && VIDEO_AU0828_V4L2 && VIDEO_CX231XX && VIDEO_TM6000 && VIDEO_EM28XX && VIDEO_IVTV && VIDEO_MXB && VIDEO_CX18 && VIDEO_CX23885 && VIDEO_CX88 && VIDEO_BT848 && VIDEO_SAA7134 && VIDEO_SAA7164) selects VIDEO_TUNER which has unmet direct dependencies (MEDIA_SUPPORT && MEDIA_TUNER) VIDEO_TUNER does not actually depend on MEDIA_TUNER, and the dependency does nothing except cause the above warning, so let's remove it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 9beece00869b..29b3436d0910 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -37,7 +37,6 @@ config VIDEO_PCI_SKELETON # Used by drivers that need tuner.ko config VIDEO_TUNER tristate - depends on MEDIA_TUNER # Used by drivers that need v4l2-mem2mem.ko config V4L2_MEM2MEM_DEV -- cgit v1.2.3 From d40ec6fdb0b03b7be4c7923a3da0e46bf943740a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Jan 2016 21:49:33 -0200 Subject: [media] media: Fix media_open() to clear filp->private_data in error leg Fix media_open() to clear filp->private_data when file open fails. Signed-off-by: Shuah Khan Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index cea35bf20011..29409f440f1c 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -181,6 +181,7 @@ static int media_open(struct inode *inode, struct file *filp) ret = mdev->fops->open(filp); if (ret) { put_device(&mdev->dev); + filp->private_data = NULL; return ret; } } -- cgit v1.2.3 From 3801bc7d1b8dd70d47a92e58d6fb5653c10b7c95 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sat, 30 Jan 2016 18:10:52 -0200 Subject: [media] media: Media Controller fix to not let stream_count go negative Change media_entity_pipeline_stop() to not decrement stream_count of an inactive media pipeline. Doing so, results in preventing starting the pipeline. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e89d85a7d31b..f2e43603d6d2 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -452,9 +452,12 @@ error: media_entity_graph_walk_start(graph, entity_err); while ((entity_err = media_entity_graph_walk_next(graph))) { - entity_err->stream_count--; - if (entity_err->stream_count == 0) - entity_err->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity_err->stream_count--; + if (entity_err->stream_count == 0) + entity_err->pipe = NULL; + } /* * We haven't increased stream_count further than this @@ -486,9 +489,12 @@ void media_entity_pipeline_stop(struct media_entity *entity) media_entity_graph_walk_start(graph, entity); while ((entity = media_entity_graph_walk_next(graph))) { - entity->stream_count--; - if (entity->stream_count == 0) - entity->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity->stream_count--; + if (entity->stream_count == 0) + entity->pipe = NULL; + } } if (!--pipe->streaming_count) -- cgit v1.2.3 From 6b3f99989eb73e5250bba9dfeaa852939acfbf70 Mon Sep 17 00:00:00 2001 From: Abhilash Jindal Date: Sun, 31 Jan 2016 03:47:31 -0200 Subject: [media] dvb-frontend: Use boottime Wall time obtained from ktime_get_real is susceptible to sudden jumps due to user setting the time or due to NTP. Boot time is constantly increasing time better suited for comparing two timestamps. [mchehab@osg.samsung.com: fix trivial merge conflicts] Signed-off-by: Abhilash Jindal Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 8 ++++---- drivers/media/dvb-frontends/stv0299.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 40080645341e..03cc508b8c42 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -899,10 +899,10 @@ void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec) s32 delta; *waketime = ktime_add_us(*waketime, add_usec); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); if (delta > 2500) { msleep((delta - 1500) / 1000); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); } if (delta > 0) udelay(delta); @@ -2451,7 +2451,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, u8 last = 1; if (dvb_frontend_debug) printk("%s switch command: 0x%04lx\n", __func__, swcmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (dvb_frontend_debug) tv[0] = nexttime; /* before sending a command, initialize by sending @@ -2462,7 +2462,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, for (i = 0; i < 9; i++) { if (dvb_frontend_debug) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if ((swcmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index a8177807fb65..c43f36d32340 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -422,7 +422,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long if (debug_legacy_dish_switch) printk ("%s switch command: 0x%04lx\n",__func__, cmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (debug_legacy_dish_switch) tv[0] = nexttime; stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ @@ -431,7 +431,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long for (i=0; i<9; i++) { if (debug_legacy_dish_switch) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if((cmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50)); -- cgit v1.2.3 From 842096fc40519e85bd4c0751e65a07cc3e23bd66 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:49:32 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue with nvt_enable_cir nvt_enable_cir calls nvt_enable_logical_dev (that may sleep) while holding a spinlock. This patch fixes this and moves the content of nvt_enable_cir to nvt_open as this is the only caller. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d428b4e6e26f..46a9ece66f75 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -942,23 +942,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) return IRQ_HANDLED; } -static void nvt_enable_cir(struct nvt_dev *nvt) -{ - /* set function enable flags */ - nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - /* enable the CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - - /* clear all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* enable interrupts */ - nvt_set_cir_iren(nvt); -} - static void nvt_disable_cir(struct nvt_dev *nvt) { /* disable CIR interrupts */ @@ -984,9 +967,23 @@ static int nvt_open(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt_enable_cir(nvt); + + /* set function enable flags */ + nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + /* clear all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* enable interrupts */ + nvt_set_cir_iren(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + return 0; } -- cgit v1.2.3 From b883af30bcd1f37ed39948be529a13f5ac4ec6a2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:26 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_enable_wake nvt_enable_wake calls nvt_select_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 46a9ece66f75..efff08a37d4d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -503,6 +503,8 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) static void nvt_enable_wake(struct nvt_dev *nvt) { + unsigned long flags; + nvt_efm_enable(nvt); nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); @@ -514,12 +516,16 @@ static void nvt_enable_wake(struct nvt_dev *nvt) nvt_efm_disable(nvt); + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); + + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } #if 0 /* Currently unused */ @@ -1152,9 +1158,10 @@ static void nvt_remove(struct pnp_dev *pdev) /* disable CIR */ nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); rc_unregister_device(nvt->rdev); } @@ -1179,14 +1186,14 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable cir logical dev */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - return 0; } @@ -1205,11 +1212,8 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit v1.2.3 From 137aa3617b3e7e780800855cdc5d3258aa0ea8d9 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:55 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_disable_cir nvt_disable_cir calls nvt_disable_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this and remove the unneeded clearing of CIR_IREN as this is done in nvt_cir_disable already. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index efff08a37d4d..c96da3aaf00b 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -950,6 +950,10 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) static void nvt_disable_cir(struct nvt_dev *nvt) { + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* disable CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -963,6 +967,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable the CIR logical device */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } @@ -996,11 +1002,8 @@ static int nvt_open(struct rc_dev *dev) static void nvt_close(struct rc_dev *dev) { struct nvt_dev *nvt = dev->priv; - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } /* Allocate memory, probe hardware, and initialize everything */ @@ -1152,13 +1155,8 @@ exit_free_dev_rdev: static void nvt_remove(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); - /* disable CIR */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); -- cgit v1.2.3 From 5ce625a42d6206d5a18222c6475f6b866ef68569 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Mon, 1 Feb 2016 13:59:30 -0200 Subject: [media] usbvision: fix locking error When remove_pending is non-zero, v4l2_lock is never unlocked. Signed-off-by: Insu Yun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 7f5d6f15a49f..12f5ebbd0436 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1147,6 +1147,7 @@ static int usbvision_radio_close(struct file *file) usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); @@ -1155,7 +1156,6 @@ static int usbvision_radio_close(struct file *file) return 0; } - mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return v4l2_fh_release(file); } -- cgit v1.2.3 From 24095e766037018e7a4b636834a383f86a9b30f2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 13:47:58 -0200 Subject: [media] msp3400: use IS_ENABLED check instead of #if A recent patch broke the msp3400 driver when CONFIG_MEDIA_CONTROLLER is not set: drivers/media/i2c/msp3400-driver.h:107:5: error: "CONFIG_MEDIA_CONTROLLER" is not defined [-Werror=undef] It was clearly a typo, and this patch changes the "#if CONFIG_MEDIA_CONTROLLER" to a working IS_ENABLED() check. Fixes: fb4932821731 ("[media] msp3400: initialize MC data") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index f0bb37dc9013..a8702aca187a 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -104,7 +104,7 @@ struct msp_state { unsigned int restart:1; unsigned int watch_stereo:1; -#if CONFIG_MEDIA_CONTROLLER +#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; #endif }; -- cgit v1.2.3 From c29ebb64a553074dc52b6ad36cf0e573d6991c09 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Feb 2016 17:29:41 -0200 Subject: [media] dvb_frontend: print DTV property dump also for SET_PROPERTY When debugging troubles with DTV properties get/set, it is important to be able to see not only the properties from get, but also the ones from set. So, improve the dumps to allow reporting both. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 03cc508b8c42..b1255b7c0b0e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1162,18 +1162,24 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) +static void dtv_property_dump(struct dvb_frontend *fe, + bool is_set, + struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n", - __func__, tvp->cmd); + dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", + __func__, + is_set ? "SET" : "GET", + tvp->cmd); return; } - dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__, - tvp->cmd, dtv_cmds[tvp->cmd].name); + dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__, + is_set ? "SET" : "GET", + tvp->cmd, + dtv_cmds[tvp->cmd].name); if (dtv_cmds[tvp->cmd].buffer) { dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n", @@ -1589,7 +1595,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(fe, tvp); + dtv_property_dump(fe, false, tvp); return 0; } @@ -1830,6 +1836,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, return r; } + dtv_property_dump(fe, true, tvp); + switch(tvp->cmd) { case DTV_CLEAR: /* -- cgit v1.2.3 From 210bd104c6acd31c3c6b8b075b3f12d4a9f6b60d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Feb 2016 13:34:00 -0200 Subject: [media] xc2028: unlock on error in xc2028_set_config() We have to unlock before returning -ENOMEM. Fixes: 8dfbcc4351a0 ('[media] xc2028: avoid use after free') Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 082ff5608455..317ef63ee789 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1407,8 +1407,10 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); - if (priv->ctrl.fname == NULL) - return -ENOMEM; + if (priv->ctrl.fname == NULL) { + rc = -ENOMEM; + goto unlock; + } } /* @@ -1440,6 +1442,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) } else priv->state = XC2028_WAITING_FIRMWARE; } +unlock: mutex_unlock(&priv->lock); return rc; -- cgit v1.2.3 From 2ea9a08d59b99fbb257bcd8c47e2cbc8be136f8c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:45:14 -0200 Subject: [media] dvb_frontend: add props argument to dtv_get_frontend() Instead of implicitly using the DTV cache properties at dtv_get_frontend(), pass it as an additional argument. This patch prepares to use a separate cache for G_PROPERTY, in order to avoid it to mangle with the DVB thread zigzag logic. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index b1255b7c0b0e..ca6d60f9d492 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -140,9 +140,12 @@ struct dvb_frontend_private { static void dvb_frontend_wakeup(struct dvb_frontend *fe); static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out); -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p); +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p); static bool has_get_frontend(struct dvb_frontend *fe) { @@ -202,6 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, enum fe_status status) { struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_fe_events *events = &fepriv->events; struct dvb_frontend_event *e; int wp; @@ -209,7 +213,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, dev_dbg(fe->dvb->device, "%s:\n", __func__); if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) - dtv_get_frontend(fe, &fepriv->parameters_out); + dtv_get_frontend(fe, c, &fepriv->parameters_out); mutex_lock(&events->mtx); @@ -687,6 +691,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) static int dvb_frontend_thread(void *data) { struct dvb_frontend *fe = data; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; enum fe_status s; enum dvbfe_algo algo; @@ -807,7 +812,7 @@ restart: fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->delay = HZ / 2; } - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); /* update event list */ @@ -1274,11 +1279,11 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, /* Ensure the cached values are set correctly in the frontend * legacy tuning structures, for the advanced tuning API. */ -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p) { - const struct dtv_frontend_properties *c = &fe->dtv_property_cache; - p->frequency = c->frequency; p->inversion = c->inversion; @@ -1350,6 +1355,7 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, * If p_out is not null, it will update the DVBv3 params pointed by it. */ static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out) { int r; @@ -1359,7 +1365,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, if (unlikely(r < 0)) return r; if (p_out) - dtv_property_legacy_params_sync(fe, p_out); + dtv_property_legacy_params_sync(fe, c, p_out); return 0; } @@ -2107,7 +2113,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, * is not idle. Otherwise, returns the cached content */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, NULL); + err = dtv_get_frontend(fe, c, NULL); if (err < 0) goto out; } @@ -2147,7 +2153,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe) * the user. FE_SET_FRONTEND triggers an initial frontend event * with status = 0, which copies output parameters to userspace. */ - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); /* * Be sure that the bandwidth will be filled for all @@ -2518,7 +2524,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, parg); + err = dtv_get_frontend(fe, c, parg); break; case FE_SET_FRONTEND_TUNE_MODE: -- cgit v1.2.3 From 83a74ff8e63e39d8122ff17ac000064605884127 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:54:25 -0200 Subject: [media] siano: remove get_frontend stub There's nothing at siano's get_frontend() callback. So, remove it, as the core will handle it. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smsdvb-main.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index d31f468830cf..9148e14c9d07 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1015,12 +1015,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe) } } -/* Nothing to do here, as stats are automatically updated */ -static int smsdvb_get_frontend(struct dvb_frontend *fe) -{ - return 0; -} - static int smsdvb_init(struct dvb_frontend *fe) { struct smsdvb_client_t *client = @@ -1069,7 +1063,6 @@ static struct dvb_frontend_ops smsdvb_fe_ops = { .release = smsdvb_release, .set_frontend = smsdvb_set_frontend, - .get_frontend = smsdvb_get_frontend, .get_tune_settings = smsdvb_get_tune_settings, .read_status = smsdvb_read_status, -- cgit v1.2.3 From 6f1bd426122da4a2d22570494bba9cf3dffbd753 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:01:05 -0200 Subject: [media] friio-fe: remove get_frontend() callback This driver doesn't support getting frontend information and it only works in automatic mode. So, let's remove get_frontend() and update the cache at set_frontend(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/friio-fe.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c index 8ec92fbeabad..979f05b4b87c 100644 --- a/drivers/media/usb/dvb-usb/friio-fe.c +++ b/drivers/media/usb/dvb-usb/friio-fe.c @@ -283,20 +283,6 @@ static int jdvbt90502_set_property(struct dvb_frontend *fe, return r; } -static int jdvbt90502_get_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - p->inversion = INVERSION_AUTO; - p->bandwidth_hz = 6000000; - p->code_rate_HP = FEC_AUTO; - p->code_rate_LP = FEC_AUTO; - p->modulation = QAM_64; - p->transmission_mode = TRANSMISSION_MODE_AUTO; - p->guard_interval = GUARD_INTERVAL_AUTO; - p->hierarchy = HIERARCHY_AUTO; - return 0; -} - static int jdvbt90502_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -312,8 +298,16 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe) deb_fe("%s: Freq:%d\n", __func__, p->frequency); - /* for recovery from DTV_CLEAN */ - fe->dtv_property_cache.delivery_system = SYS_ISDBT; + /* This driver only works on auto mode */ + p->inversion = INVERSION_AUTO; + p->bandwidth_hz = 6000000; + p->code_rate_HP = FEC_AUTO; + p->code_rate_LP = FEC_AUTO; + p->modulation = QAM_64; + p->transmission_mode = TRANSMISSION_MODE_AUTO; + p->guard_interval = GUARD_INTERVAL_AUTO; + p->hierarchy = HIERARCHY_AUTO; + p->delivery_system = SYS_ISDBT; ret = jdvbt90502_pll_set_freq(state, p->frequency); if (ret) { @@ -466,7 +460,6 @@ static struct dvb_frontend_ops jdvbt90502_ops = { .set_property = jdvbt90502_set_property, .set_frontend = jdvbt90502_set_frontend, - .get_frontend = jdvbt90502_get_frontend, .read_status = jdvbt90502_read_status, .read_signal_strength = jdvbt90502_read_signal_strength, -- cgit v1.2.3 From 0fa301d796ce7d78d12cf35440143e3f232f5663 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:37:37 -0200 Subject: [media] lgs8gxx: don't export get_frontend() callback This device doesn't really have a get_frontend(). All it does is to blindly set everything to auto mode. Remove the get_frontend(), as the code does that already, and put the frontend changes at set_frontend, where it belongs. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/lgs8gxx.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/dvb-frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c index e2c191c8b196..919daeb96747 100644 --- a/drivers/media/dvb-frontends/lgs8gxx.c +++ b/drivers/media/dvb-frontends/lgs8gxx.c @@ -672,7 +672,7 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len) static int lgs8gxx_set_fe(struct dvb_frontend *fe) { - + struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct lgs8gxx_state *priv = fe->demodulator_priv; dprintk("%s\n", __func__); @@ -689,17 +689,7 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe) msleep(10); - return 0; -} - -static int lgs8gxx_get_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; - dprintk("%s\n", __func__); - /* TODO: get real readings from device */ - /* inversion status */ - fe_params->inversion = INVERSION_OFF; /* bandwidth */ fe_params->bandwidth_hz = 8000000; @@ -1016,7 +1006,6 @@ static struct dvb_frontend_ops lgs8gxx_ops = { .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, .set_frontend = lgs8gxx_set_fe, - .get_frontend = lgs8gxx_get_fe, .get_tune_settings = lgs8gxx_get_tune_settings, .read_status = lgs8gxx_read_status, -- cgit v1.2.3 From a7497049841f04712ad525969e5eb4a42b5a1704 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:47:04 -0200 Subject: [media] mb86a20s: get rid of dummy get_frontend() This is not needed, as the core handles well if get_frontend() is not present. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mb86a20s.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index cfc005ee11d8..fb88dddaf3a3 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -2028,16 +2028,6 @@ static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe, return 0; } -static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe) -{ - /* - * get_frontend is now handled together with other stats - * retrival, when read_status() is called, as some statistics - * will depend on the layers detection. - */ - return 0; -}; - static int mb86a20s_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, @@ -2136,7 +2126,6 @@ static struct dvb_frontend_ops mb86a20s_ops = { .init = mb86a20s_initfe, .set_frontend = mb86a20s_set_frontend, - .get_frontend = mb86a20s_get_frontend_dummy, .read_status = mb86a20s_read_status_and_stats, .read_signal_strength = mb86a20s_read_signal_strength_from_cache, .tune = mb86a20s_tune, -- cgit v1.2.3 From 7e3e68bcfd7713fb1470070c8fa0f108609dd76b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:58:30 -0200 Subject: [media] dvb_frontend: pass the props cache to get_frontend() as arg Instead of using the DTV properties cache directly, pass the get frontend data as an argument. For now, everything should remain the same, but the next patch will prevent get_frontend to affect the global cache. This is needed because several drivers don't care enough to only change the properties if locked. Due to that, calling G_PROPERTY before locking on those drivers will make them to never lock. Ok, those drivers are crap and should never be merged like that, but the core should not rely that the drivers would be doing the right thing. Reviewed-by: Michael Ira Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 2 +- drivers/media/dvb-core/dvb_frontend.h | 3 +- drivers/media/dvb-frontends/af9013.c | 4 +- drivers/media/dvb-frontends/af9033.c | 4 +- drivers/media/dvb-frontends/as102_fe.c | 4 +- drivers/media/dvb-frontends/atbm8830.c | 4 +- drivers/media/dvb-frontends/au8522_dig.c | 4 +- drivers/media/dvb-frontends/cx22700.c | 4 +- drivers/media/dvb-frontends/cx22702.c | 4 +- drivers/media/dvb-frontends/cx24110.c | 4 +- drivers/media/dvb-frontends/cx24117.c | 4 +- drivers/media/dvb-frontends/cx24120.c | 4 +- drivers/media/dvb-frontends/cx24123.c | 4 +- drivers/media/dvb-frontends/cxd2820r_c.c | 4 +- drivers/media/dvb-frontends/cxd2820r_core.c | 9 ++-- drivers/media/dvb-frontends/cxd2820r_priv.h | 9 ++-- drivers/media/dvb-frontends/cxd2820r_t.c | 4 +- drivers/media/dvb-frontends/cxd2820r_t2.c | 6 +-- drivers/media/dvb-frontends/cxd2841er.c | 4 +- drivers/media/dvb-frontends/dib3000mb.c | 9 ++-- drivers/media/dvb-frontends/dib3000mc.c | 6 +-- drivers/media/dvb-frontends/dib7000m.c | 6 +-- drivers/media/dvb-frontends/dib7000p.c | 6 +-- drivers/media/dvb-frontends/dib8000.c | 75 ++++++++++++++------------- drivers/media/dvb-frontends/dib9000.c | 23 ++++---- drivers/media/dvb-frontends/dvb_dummy_fe.c | 7 ++- drivers/media/dvb-frontends/hd29l2.c | 4 +- drivers/media/dvb-frontends/l64781.c | 4 +- drivers/media/dvb-frontends/lg2160.c | 62 +++++++++++----------- drivers/media/dvb-frontends/lgdt3305.c | 4 +- drivers/media/dvb-frontends/lgdt3306a.c | 4 +- drivers/media/dvb-frontends/lgdt330x.c | 5 +- drivers/media/dvb-frontends/lgs8gl5.c | 5 +- drivers/media/dvb-frontends/m88ds3103.c | 4 +- drivers/media/dvb-frontends/m88rs2000.c | 5 +- drivers/media/dvb-frontends/mt312.c | 4 +- drivers/media/dvb-frontends/mt352.c | 4 +- drivers/media/dvb-frontends/or51132.c | 4 +- drivers/media/dvb-frontends/rtl2830.c | 4 +- drivers/media/dvb-frontends/rtl2832.c | 4 +- drivers/media/dvb-frontends/s5h1409.c | 4 +- drivers/media/dvb-frontends/s5h1411.c | 4 +- drivers/media/dvb-frontends/s5h1420.c | 4 +- drivers/media/dvb-frontends/s921.c | 4 +- drivers/media/dvb-frontends/stb0899_drv.c | 4 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0297.c | 4 +- drivers/media/dvb-frontends/stv0299.c | 4 +- drivers/media/dvb-frontends/stv0367.c | 8 +-- drivers/media/dvb-frontends/stv0900_core.c | 4 +- drivers/media/dvb-frontends/tc90522.c | 10 ++-- drivers/media/dvb-frontends/tda10021.c | 4 +- drivers/media/dvb-frontends/tda10023.c | 4 +- drivers/media/dvb-frontends/tda10048.c | 4 +- drivers/media/dvb-frontends/tda1004x.c | 4 +- drivers/media/dvb-frontends/tda10071.c | 4 +- drivers/media/dvb-frontends/tda10086.c | 4 +- drivers/media/dvb-frontends/tda8083.c | 4 +- drivers/media/dvb-frontends/ves1820.c | 4 +- drivers/media/dvb-frontends/ves1x93.c | 4 +- drivers/media/dvb-frontends/zl10353.c | 4 +- drivers/media/pci/bt8xx/dst.c | 4 +- drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c | 4 +- drivers/media/usb/dvb-usb/af9005-fe.c | 4 +- drivers/media/usb/dvb-usb/dtt200u-fe.c | 5 +- 65 files changed, 230 insertions(+), 213 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index ca6d60f9d492..d009478f16c4 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1361,7 +1361,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, int r; if (fe->ops.get_frontend) { - r = fe->ops.get_frontend(fe); + r = fe->ops.get_frontend(fe, c); if (unlikely(r < 0)) return r; if (p_out) diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 458bcce20e38..9592573a0b41 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -449,7 +449,8 @@ struct dvb_frontend_ops { int (*set_frontend)(struct dvb_frontend *fe); int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); - int (*get_frontend)(struct dvb_frontend *fe); + int (*get_frontend)(struct dvb_frontend *fe, + struct dtv_frontend_properties *props); int (*read_status)(struct dvb_frontend *fe, enum fe_status *status); int (*read_ber)(struct dvb_frontend* fe, u32* ber); diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 41ab5defb798..8bcde336ffd7 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -866,9 +866,9 @@ err: return ret; } -static int af9013_get_frontend(struct dvb_frontend *fe) +static int af9013_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct af9013_state *state = fe->demodulator_priv; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 8b328d1ca8d3..efebe5ce2429 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -691,10 +691,10 @@ err: return ret; } -static int af9033_get_frontend(struct dvb_frontend *fe) +static int af9033_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct af9033_dev *dev = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[8]; diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c index 544c5f65d19a..9412fcd1bddb 100644 --- a/drivers/media/dvb-frontends/as102_fe.c +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -190,10 +190,10 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe) return state->ops->set_tune(state->priv, &tune_args); } -static int as102_fe_get_frontend(struct dvb_frontend *fe) +static int as102_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct as102_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret = 0; struct as10x_tps tps = { 0 }; diff --git a/drivers/media/dvb-frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c index 8fe552e293ed..47248b868e38 100644 --- a/drivers/media/dvb-frontends/atbm8830.c +++ b/drivers/media/dvb-frontends/atbm8830.c @@ -297,9 +297,9 @@ static int atbm8830_set_fe(struct dvb_frontend *fe) return 0; } -static int atbm8830_get_fe(struct dvb_frontend *fe) +static int atbm8830_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; dprintk("%s\n", __func__); /* TODO: get real readings from device */ diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index 6c1e97640f3f..e676b9461a59 100644 --- a/drivers/media/dvb-frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -816,9 +816,9 @@ static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) return au8522_read_ucblocks(fe, ber); } -static int au8522_get_frontend(struct dvb_frontend *fe) +static int au8522_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct au8522_state *state = fe->demodulator_priv; c->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c index fd033cca6e11..5cad925609e0 100644 --- a/drivers/media/dvb-frontends/cx22700.c +++ b/drivers/media/dvb-frontends/cx22700.c @@ -345,9 +345,9 @@ static int cx22700_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx22700_get_frontend(struct dvb_frontend *fe) +static int cx22700_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22700_state* state = fe->demodulator_priv; u8 reg09 = cx22700_readreg (state, 0x09); diff --git a/drivers/media/dvb-frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c index d2d06dcd7683..c0e54c59cccf 100644 --- a/drivers/media/dvb-frontends/cx22702.c +++ b/drivers/media/dvb-frontends/cx22702.c @@ -562,9 +562,9 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int cx22702_get_frontend(struct dvb_frontend *fe) +static int cx22702_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22702_state *state = fe->demodulator_priv; u8 reg0C = cx22702_readreg(state, 0x0C); diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c index cb36475e322b..6cb81ec12847 100644 --- a/drivers/media/dvb-frontends/cx24110.c +++ b/drivers/media/dvb-frontends/cx24110.c @@ -550,9 +550,9 @@ static int cx24110_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24110_get_frontend(struct dvb_frontend *fe) +static int cx24110_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24110_state *state = fe->demodulator_priv; s32 afc; unsigned sclk; diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 5f77bc80a896..a3f7eb4e609d 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -1560,10 +1560,10 @@ static int cx24117_get_algo(struct dvb_frontend *fe) return DVBFE_ALGO_HW; } -static int cx24117_get_frontend(struct dvb_frontend *fe) +static int cx24117_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cx24117_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24117_cmd cmd; u8 reg, st, inv; int ret, idx; diff --git a/drivers/media/dvb-frontends/cx24120.c b/drivers/media/dvb-frontends/cx24120.c index 3b0ef52bb834..6ccbd86c9490 100644 --- a/drivers/media/dvb-frontends/cx24120.c +++ b/drivers/media/dvb-frontends/cx24120.c @@ -1502,9 +1502,9 @@ static int cx24120_sleep(struct dvb_frontend *fe) return 0; } -static int cx24120_get_frontend(struct dvb_frontend *fe) +static int cx24120_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24120_state *state = fe->demodulator_priv; u8 freq1, freq2, freq3; diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index 0fe7fb11124b..113b0949408a 100644 --- a/drivers/media/dvb-frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c @@ -945,9 +945,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24123_get_frontend(struct dvb_frontend *fe) +static int cx24123_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24123_state *state = fe->demodulator_priv; dprintk("\n"); diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 42fad6aa3958..a674a6312c38 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -101,10 +101,10 @@ error: return ret; } -int cxd2820r_get_frontend_c(struct dvb_frontend *fe) +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index ba4cb7557aa5..314d3b8c1080 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -313,7 +313,8 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status) return ret; } -static int cxd2820r_get_frontend(struct dvb_frontend *fe) +static int cxd2820r_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; @@ -326,13 +327,13 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe) switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: - ret = cxd2820r_get_frontend_t(fe); + ret = cxd2820r_get_frontend_t(fe, p); break; case SYS_DVBT2: - ret = cxd2820r_get_frontend_t2(fe); + ret = cxd2820r_get_frontend_t2(fe, p); break; case SYS_DVBC_ANNEX_A: - ret = cxd2820r_get_frontend_c(fe); + ret = cxd2820r_get_frontend_c(fe, p); break; default: ret = -EINVAL; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index a0d53f01a8bf..e31c48e53097 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -76,7 +76,8 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val); /* cxd2820r_c.c */ -int cxd2820r_get_frontend_c(struct dvb_frontend *fe); +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_c(struct dvb_frontend *fe); @@ -99,7 +100,8 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, /* cxd2820r_t.c */ -int cxd2820r_get_frontend_t(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t(struct dvb_frontend *fe); @@ -122,7 +124,8 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, /* cxd2820r_t2.c */ -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t2(struct dvb_frontend *fe); diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 21abf1b4ed4d..75ce7d8ded00 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -138,10 +138,10 @@ error: return ret; } -int cxd2820r_get_frontend_t(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 4e028b41c0d5..704475676234 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -23,8 +23,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { - struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret, i, bw_i; u32 if_freq, if_ctl; u64 num; @@ -169,10 +169,10 @@ error: } -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index fdffb2f0ded8..900186ba8e62 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -2090,13 +2090,13 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, return 0; } -static int cxd2841er_get_frontend(struct dvb_frontend *fe) +static int cxd2841er_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { enum fe_status status = 0; u16 strength = 0, snr = 0; u32 errors = 0, ber = 0; struct cxd2841er_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); if (priv->state == STATE_ACTIVE_S) diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 3ca300939f79..6821ecb53d63 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -112,7 +112,8 @@ static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ } }; -static int dib3000mb_get_frontend(struct dvb_frontend* fe); +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c); static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) { @@ -359,7 +360,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count); if (search_state == 1) { - if (dib3000mb_get_frontend(fe) == 0) { + if (dib3000mb_get_frontend(fe, c) == 0) { deb_setf("reading tuning data from frontend succeeded.\n"); return dib3000mb_set_frontend(fe, 0); } @@ -450,9 +451,9 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) return 0; } -static int dib3000mb_get_frontend(struct dvb_frontend* fe) +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dib3000_state* state = fe->demodulator_priv; enum fe_code_rate *cr; u16 tps_val; diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index ac90ed3af37e..da0f1dc5aaf7 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -636,9 +636,9 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master); -static int dib3000mc_get_frontend(struct dvb_frontend* fe) +static int dib3000mc_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib3000mc_state *state = fe->demodulator_priv; u16 tps = dib3000mc_read_word(state,458); @@ -726,7 +726,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib3000mc_get_frontend(fe); + dib3000mc_get_frontend(fe, fep); } ret = dib3000mc_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 8b21cccf3c3a..b3ddae8885ac 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1151,9 +1151,9 @@ static int dib7000m_identify(struct dib7000m_state *state) } -static int dib7000m_get_frontend(struct dvb_frontend* fe) +static int dib7000m_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000m_state *state = fe->demodulator_priv; u16 tps = dib7000m_read_word(state,480); @@ -1246,7 +1246,7 @@ static int dib7000m_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib7000m_get_frontend(fe); + dib7000m_get_frontend(fe, fep); } ret = dib7000m_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 65ab79ed5e3e..b861d4437f2a 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -1405,9 +1405,9 @@ static int dib7000p_identify(struct dib7000p_state *st) return 0; } -static int dib7000p_get_frontend(struct dvb_frontend *fe) +static int dib7000p_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000p_state *state = fe->demodulator_priv; u16 tps = dib7000p_read_word(state, 463); @@ -1540,7 +1540,7 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; - dib7000p_get_frontend(fe); + dib7000p_get_frontend(fe, fep); } ret = dib7000p_tune(fe); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 349d2f1f62ce..ddf9c44877a2 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3382,14 +3382,15 @@ static int dib8000_sleep(struct dvb_frontend *fe) static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat); -static int dib8000_get_frontend(struct dvb_frontend *fe) +static int dib8000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib8000_state *state = fe->demodulator_priv; u16 i, val = 0; enum fe_status stat = 0; u8 index_frontend, sub_index_frontend; - fe->dtv_property_cache.bandwidth_hz = 6000000; + c->bandwidth_hz = 6000000; /* * If called to early, get_frontend makes dib8000_tune to either @@ -3406,7 +3407,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (stat&FE_HAS_SYNC) { dprintk("TMCC lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; @@ -3426,57 +3427,57 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) } } - fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; + c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; if (state->revision == 0x8090) val = dib8000_read_word(state, 572); else val = dib8000_read_word(state, 570); - fe->dtv_property_cache.inversion = (val & 0x40) >> 6; + c->inversion = (val & 0x40) >> 6; switch ((val & 0x30) >> 4) { case 1: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; + c->transmission_mode = TRANSMISSION_MODE_2K; dprintk("dib8000_get_frontend: transmission mode 2K"); break; case 2: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K; + c->transmission_mode = TRANSMISSION_MODE_4K; dprintk("dib8000_get_frontend: transmission mode 4K"); break; case 3: default: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; + c->transmission_mode = TRANSMISSION_MODE_8K; dprintk("dib8000_get_frontend: transmission mode 8K"); break; } switch (val & 0x3) { case 0: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; + c->guard_interval = GUARD_INTERVAL_1_32; dprintk("dib8000_get_frontend: Guard Interval = 1/32 "); break; case 1: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; + c->guard_interval = GUARD_INTERVAL_1_16; dprintk("dib8000_get_frontend: Guard Interval = 1/16 "); break; case 2: dprintk("dib8000_get_frontend: Guard Interval = 1/8 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; + c->guard_interval = GUARD_INTERVAL_1_8; break; case 3: dprintk("dib8000_get_frontend: Guard Interval = 1/4 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; + c->guard_interval = GUARD_INTERVAL_1_4; break; } val = dib8000_read_word(state, 505); - fe->dtv_property_cache.isdbt_partial_reception = val & 1; - dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); + c->isdbt_partial_reception = val & 1; + dprintk("dib8000_get_frontend: partial_reception = %d ", c->isdbt_partial_reception); for (i = 0; i < 3; i++) { int show; val = dib8000_read_word(state, 493 + i) & 0x0f; - fe->dtv_property_cache.layer[i].segment_count = val; + c->layer[i].segment_count = val; if (val == 0 || val > 13) show = 0; @@ -3485,41 +3486,41 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (show) dprintk("dib8000_get_frontend: Layer %d segments = %d ", - i, fe->dtv_property_cache.layer[i].segment_count); + i, c->layer[i].segment_count); val = dib8000_read_word(state, 499 + i) & 0x3; /* Interleaving can be 0, 1, 2 or 4 */ if (val == 3) val = 4; - fe->dtv_property_cache.layer[i].interleaving = val; + c->layer[i].interleaving = val; if (show) dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ", - i, fe->dtv_property_cache.layer[i].interleaving); + i, c->layer[i].interleaving); val = dib8000_read_word(state, 481 + i); switch (val & 0x7) { case 1: - fe->dtv_property_cache.layer[i].fec = FEC_1_2; + c->layer[i].fec = FEC_1_2; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i); break; case 2: - fe->dtv_property_cache.layer[i].fec = FEC_2_3; + c->layer[i].fec = FEC_2_3; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i); break; case 3: - fe->dtv_property_cache.layer[i].fec = FEC_3_4; + c->layer[i].fec = FEC_3_4; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i); break; case 5: - fe->dtv_property_cache.layer[i].fec = FEC_5_6; + c->layer[i].fec = FEC_5_6; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i); break; default: - fe->dtv_property_cache.layer[i].fec = FEC_7_8; + c->layer[i].fec = FEC_7_8; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i); break; @@ -3528,23 +3529,23 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) val = dib8000_read_word(state, 487 + i); switch (val & 0x3) { case 0: - fe->dtv_property_cache.layer[i].modulation = DQPSK; + c->layer[i].modulation = DQPSK; if (show) dprintk("dib8000_get_frontend: Layer %d DQPSK ", i); break; case 1: - fe->dtv_property_cache.layer[i].modulation = QPSK; + c->layer[i].modulation = QPSK; if (show) dprintk("dib8000_get_frontend: Layer %d QPSK ", i); break; case 2: - fe->dtv_property_cache.layer[i].modulation = QAM_16; + c->layer[i].modulation = QAM_16; if (show) dprintk("dib8000_get_frontend: Layer %d QAM16 ", i); break; case 3: default: - fe->dtv_property_cache.layer[i].modulation = QAM_64; + c->layer[i].modulation = QAM_64; if (show) dprintk("dib8000_get_frontend: Layer %d QAM64 ", i); break; @@ -3553,16 +3554,16 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode; - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception; + state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception; for (i = 0; i < 3; i++) { - state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count; - state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving; - state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec; - state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation; + state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count; + state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving; + state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec; + state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation; } } return 0; @@ -3671,7 +3672,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) if (state->channel_parameters_set == 0) { /* searching */ if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { dprintk("autosearch succeeded on fe%i", index_frontend); - dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */ + dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */ state->channel_parameters_set = 1; for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 91888a2f5301..bab8c5a980a2 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -1889,7 +1889,8 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron return 0; } -static int dib9000_get_frontend(struct dvb_frontend *fe) +static int dib9000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib9000_state *state = fe->demodulator_priv; u8 index_frontend, sub_index_frontend; @@ -1909,7 +1910,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) dprintk("TPS lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { @@ -1943,14 +1944,14 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation; - state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy; - state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP; - state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; - state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.modulation = c->modulation; + state->fe[index_frontend]->dtv_property_cache.hierarchy = c->hierarchy; + state->fe[index_frontend]->dtv_property_cache.code_rate_HP = c->code_rate_HP; + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = c->code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = c->rolloff; } ret = 0; @@ -2083,7 +2084,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe) /* synchronize all the channel cache */ state->get_frontend_internal = 1; - dib9000_get_frontend(state->fe[0]); + dib9000_get_frontend(state->fe[0], &state->fe[0]->dtv_property_cache); state->get_frontend_internal = 0; /* retune the other frontends with the found channel */ diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c index 14e996d45fac..e5bd8c62ad3a 100644 --- a/drivers/media/dvb-frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c @@ -70,9 +70,12 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) } /* - * Only needed if it actually reads something from the hardware + * Should only be implemented if it actually reads something from the hardware. + * Also, it should check for the locks, in order to avoid report wrong data + * to userspace. */ -static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe) +static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { return 0; } diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c index 40e359f2d17d..1c7eb477e2cd 100644 --- a/drivers/media/dvb-frontends/hd29l2.c +++ b/drivers/media/dvb-frontends/hd29l2.c @@ -560,11 +560,11 @@ static int hd29l2_get_frontend_algo(struct dvb_frontend *fe) return DVBFE_ALGO_CUSTOM; } -static int hd29l2_get_frontend(struct dvb_frontend *fe) +static int hd29l2_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { int ret; struct hd29l2_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; u8 buf[3]; u32 if_ctl; char *str_constellation, *str_code_rate, *str_constellation_code_rate, diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c index 0977871232a2..2f3d0519e19b 100644 --- a/drivers/media/dvb-frontends/l64781.c +++ b/drivers/media/dvb-frontends/l64781.c @@ -243,9 +243,9 @@ static int apply_frontend_param(struct dvb_frontend *fe) return 0; } -static int get_frontend(struct dvb_frontend *fe) +static int get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct l64781_state* state = fe->demodulator_priv; int tmp; diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index 7880f71ccd8a..f51a3a0b3949 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c @@ -942,101 +942,102 @@ static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err) /* ------------------------------------------------------------------------ */ -static int lg216x_get_frontend(struct dvb_frontend *fe) +static int lg216x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct lg216x_state *state = fe->demodulator_priv; int ret; lg_dbg("\n"); - fe->dtv_property_cache.modulation = VSB_8; - fe->dtv_property_cache.frequency = state->current_frequency; - fe->dtv_property_cache.delivery_system = SYS_ATSCMH; + c->modulation = VSB_8; + c->frequency = state->current_frequency; + c->delivery_system = SYS_ATSCMH; ret = lg216x_get_fic_version(state, - &fe->dtv_property_cache.atscmh_fic_ver); + &c->atscmh_fic_ver); if (lg_fail(ret)) goto fail; - if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) { - state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver; + if (state->fic_ver != c->atscmh_fic_ver) { + state->fic_ver = c->atscmh_fic_ver; #if 0 ret = lg2160_get_parade_id(state, - &fe->dtv_property_cache.atscmh_parade_id); + &c->atscmh_parade_id); if (lg_fail(ret)) goto fail; /* #else */ - fe->dtv_property_cache.atscmh_parade_id = state->parade_id; + c->atscmh_parade_id = state->parade_id; #endif ret = lg216x_get_nog(state, - &fe->dtv_property_cache.atscmh_nog); + &c->atscmh_nog); if (lg_fail(ret)) goto fail; ret = lg216x_get_tnog(state, - &fe->dtv_property_cache.atscmh_tnog); + &c->atscmh_tnog); if (lg_fail(ret)) goto fail; ret = lg216x_get_sgn(state, - &fe->dtv_property_cache.atscmh_sgn); + &c->atscmh_sgn); if (lg_fail(ret)) goto fail; ret = lg216x_get_prc(state, - &fe->dtv_property_cache.atscmh_prc); + &c->atscmh_prc); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_mode(state, (enum atscmh_rs_frame_mode *) - &fe->dtv_property_cache.atscmh_rs_frame_mode); + &c->atscmh_rs_frame_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_ensemble(state, (enum atscmh_rs_frame_ensemble *) - &fe->dtv_property_cache.atscmh_rs_frame_ensemble); + &c->atscmh_rs_frame_ensemble); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_code_mode(state, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_pri, + &c->atscmh_rs_code_mode_pri, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_sec); + &c->atscmh_rs_code_mode_sec); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_block_mode(state, (enum atscmh_sccc_block_mode *) - &fe->dtv_property_cache.atscmh_sccc_block_mode); + &c->atscmh_sccc_block_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_code_mode(state, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_a, + &c->atscmh_sccc_code_mode_a, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_b, + &c->atscmh_sccc_code_mode_b, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_c, + &c->atscmh_sccc_code_mode_c, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_d); + &c->atscmh_sccc_code_mode_d); if (lg_fail(ret)) goto fail; } #if 0 ret = lg216x_read_fic_err_count(state, - (u8 *)&fe->dtv_property_cache.atscmh_fic_err); + (u8 *)&c->atscmh_fic_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_crc_err_count(state, - &fe->dtv_property_cache.atscmh_crc_err); + &c->atscmh_crc_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_rs_err_count(state, - &fe->dtv_property_cache.atscmh_rs_err); + &c->atscmh_rs_err); if (lg_fail(ret)) goto fail; switch (state->cfg->lg_chip) { case LG2160: - if (((fe->dtv_property_cache.atscmh_rs_err >= 240) && - (fe->dtv_property_cache.atscmh_crc_err >= 240)) && + if (((c->atscmh_rs_err >= 240) && + (c->atscmh_crc_err >= 240)) && ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000)) ret = lg216x_soft_reset(state); break; @@ -1054,14 +1055,17 @@ fail: static int lg216x_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + return (DTV_ATSCMH_FIC_VER == tvp->cmd) ? - lg216x_get_frontend(fe) : 0; + lg216x_get_frontend(fe, c) : 0; } static int lg2160_set_frontend(struct dvb_frontend *fe) { struct lg216x_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; lg_dbg("(%d)\n", fe->dtv_property_cache.frequency); @@ -1129,7 +1133,7 @@ static int lg2160_set_frontend(struct dvb_frontend *fe) ret = lg216x_enable_fic(state, 1); lg_fail(ret); - lg216x_get_frontend(fe); + lg216x_get_frontend(fe, c); fail: return ret; } diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 47121866163d..4503e8852fd1 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -812,9 +812,9 @@ fail: return ret; } -static int lgdt3305_get_frontend(struct dvb_frontend *fe) +static int lgdt3305_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt3305_state *state = fe->demodulator_priv; lg_dbg("\n"); diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 721fbc07e9ee..179c26e5eb4e 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -1040,10 +1040,10 @@ fail: return ret; } -static int lgdt3306a_get_frontend(struct dvb_frontend *fe) +static int lgdt3306a_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct lgdt3306a_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dbg_info("(%u, %d)\n", state->current_frequency, state->current_modulation); diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index cf3cc20510da..96bf254da21e 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -439,10 +439,11 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe) return 0; } -static int lgdt330x_get_frontend(struct dvb_frontend *fe) +static int lgdt330x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt330x_state *state = fe->demodulator_priv; + p->frequency = state->current_frequency; return 0; } diff --git a/drivers/media/dvb-frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c index 7bbb2c18c2dd..fbfd87b5b803 100644 --- a/drivers/media/dvb-frontends/lgs8gl5.c +++ b/drivers/media/dvb-frontends/lgs8gl5.c @@ -336,10 +336,11 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe) static int -lgs8gl5_get_frontend(struct dvb_frontend *fe) +lgs8gl5_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgs8gl5_state *state = fe->demodulator_priv; + u8 inv = lgs8gl5_read_reg(state, REG_INVERSION); p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index ce73a5ec6036..76883600ec6f 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -791,11 +791,11 @@ err: return ret; } -static int m88ds3103_get_frontend(struct dvb_frontend *fe) +static int m88ds3103_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct m88ds3103_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 9b6f464c48bd..a09b12313a73 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c @@ -708,10 +708,11 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) return 0; } -static int m88rs2000_get_frontend(struct dvb_frontend *fe) +static int m88rs2000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct m88rs2000_state *state = fe->demodulator_priv; + c->fec_inner = state->fec_inner; c->frequency = state->tuner_frequency; c->symbol_rate = state->symbol_rate; diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index c36e6764eead..fc08429c99b7 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -647,9 +647,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe) return 0; } -static int mt312_get_frontend(struct dvb_frontend *fe) +static int mt312_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mt312_state *state = fe->demodulator_priv; int ret; diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index 123bb2f8e4b6..c0bb6328956b 100644 --- a/drivers/media/dvb-frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c @@ -311,9 +311,9 @@ static int mt352_set_parameters(struct dvb_frontend *fe) return 0; } -static int mt352_get_parameters(struct dvb_frontend* fe) +static int mt352_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *op) { - struct dtv_frontend_properties *op = &fe->dtv_property_cache; struct mt352_state* state = fe->demodulator_priv; u16 tps; u16 div; diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 35b1053b3640..a165af990672 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -375,9 +375,9 @@ static int or51132_set_parameters(struct dvb_frontend *fe) return 0; } -static int or51132_get_parameters(struct dvb_frontend* fe) +static int or51132_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct or51132_state* state = fe->demodulator_priv; int status; int retry = 1; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 74b771218033..3f96429af0e5 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -279,11 +279,11 @@ err: return ret; } -static int rtl2830_get_frontend(struct dvb_frontend *fe) +static int rtl2830_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 10f2119935da..c2469fb42f12 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -575,11 +575,11 @@ err: return ret; } -static int rtl2832_get_frontend(struct dvb_frontend *fe) +static int rtl2832_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct rtl2832_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c index 10964848a2f1..c68965ad97c0 100644 --- a/drivers/media/dvb-frontends/s5h1409.c +++ b/drivers/media/dvb-frontends/s5h1409.c @@ -925,9 +925,9 @@ static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1409_read_ucblocks(fe, ber); } -static int s5h1409_get_frontend(struct dvb_frontend *fe) +static int s5h1409_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1409_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 9afc3f42290e..90f86e82b087 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -840,9 +840,9 @@ static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1411_read_ucblocks(fe, ber); } -static int s5h1411_get_frontend(struct dvb_frontend *fe) +static int s5h1411_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1411_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index 9c22a4c70d87..d7d0b7d57ad7 100644 --- a/drivers/media/dvb-frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c @@ -756,9 +756,9 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe) return 0; } -static int s5h1420_get_frontend(struct dvb_frontend* fe) +static int s5h1420_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1420_state* state = fe->demodulator_priv; p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state); diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c index d6a8fa63040b..b5e3d90eba5e 100644 --- a/drivers/media/dvb-frontends/s921.c +++ b/drivers/media/dvb-frontends/s921.c @@ -433,9 +433,9 @@ static int s921_set_frontend(struct dvb_frontend *fe) return 0; } -static int s921_get_frontend(struct dvb_frontend *fe) +static int s921_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s921_state *state = fe->demodulator_priv; /* FIXME: Probably it is possible to get it from regs f1 and f2 */ diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 756650f154ab..3d171b0e00c2 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1568,9 +1568,9 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe) return DVBFE_ALGO_SEARCH_ERROR; } -static int stb0899_get_frontend(struct dvb_frontend *fe) +static int stb0899_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stb0899_state *state = fe->demodulator_priv; struct stb0899_internal *internal = &state->internal; diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index c978c801c7aa..b9c2511bf019 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -346,7 +346,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) if (fe->ops.get_frontend) { dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters"); - fe->ops.get_frontend(fe); + fe->ops.get_frontend(fe, p); } srate = p->symbol_rate; diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c index 75b4d8b25657..81b27b7c0c96 100644 --- a/drivers/media/dvb-frontends/stv0297.c +++ b/drivers/media/dvb-frontends/stv0297.c @@ -615,9 +615,9 @@ timeout: return 0; } -static int stv0297_get_frontend(struct dvb_frontend *fe) +static int stv0297_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0297_state *state = fe->demodulator_priv; int reg_00, reg_83; diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index c43f36d32340..7927fa925f2f 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -602,9 +602,9 @@ static int stv0299_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0299_get_frontend(struct dvb_frontend *fe) +static int stv0299_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0299_state* state = fe->demodulator_priv; s32 derot_freq; int invval; diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 44cb73f68af6..abc379aea713 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -1938,9 +1938,9 @@ static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int stv0367ter_get_frontend(struct dvb_frontend *fe) +static int stv0367ter_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367ter_state *ter_state = state->ter_state; enum stv0367_ter_mode mode; @@ -3146,9 +3146,9 @@ static int stv0367cab_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0367cab_get_frontend(struct dvb_frontend *fe) +static int stv0367cab_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367cab_state *cab_state = state->cab_state; diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index fe31dd541955..28239b1fd954 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c @@ -1859,9 +1859,9 @@ static int stv0900_sleep(struct dvb_frontend *fe) return 0; } -static int stv0900_get_frontend(struct dvb_frontend *fe) +static int stv0900_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0900_state *state = fe->demodulator_priv; struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 456cdc7fb1e7..31cd32532387 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -201,10 +201,10 @@ static const enum fe_code_rate fec_conv_sat[] = { FEC_2_3, /* for 8PSK. (trellis code) */ }; -static int tc90522s_get_frontend(struct dvb_frontend *fe) +static int tc90522s_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -212,7 +212,6 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBS; c->symbol_rate = 28860000; @@ -337,10 +336,10 @@ static const enum fe_modulation mod_conv[] = { DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 }; -static int tc90522t_get_frontend(struct dvb_frontend *fe) +static int tc90522t_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -348,7 +347,6 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBT; c->bandwidth_hz = 6000000; mode = 1; diff --git a/drivers/media/dvb-frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c index a684424e665a..806c56691ca5 100644 --- a/drivers/media/dvb-frontends/tda10021.c +++ b/drivers/media/dvb-frontends/tda10021.c @@ -387,9 +387,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10021_get_frontend(struct dvb_frontend *fe) +static int tda10021_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10021_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c index 44a55656093f..3b8c7e499d0d 100644 --- a/drivers/media/dvb-frontends/tda10023.c +++ b/drivers/media/dvb-frontends/tda10023.c @@ -457,9 +457,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10023_get_frontend(struct dvb_frontend *fe) +static int tda10023_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10023_state* state = fe->demodulator_priv; int sync,inv; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c index 8451086c563f..c2bf89d0b0b0 100644 --- a/drivers/media/dvb-frontends/tda10048.c +++ b/drivers/media/dvb-frontends/tda10048.c @@ -1028,9 +1028,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int tda10048_get_frontend(struct dvb_frontend *fe) +static int tda10048_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10048_state *state = fe->demodulator_priv; dprintk(1, "%s()\n", __func__); diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c index 0e209b56c76c..3137a9ba3a32 100644 --- a/drivers/media/dvb-frontends/tda1004x.c +++ b/drivers/media/dvb-frontends/tda1004x.c @@ -899,9 +899,9 @@ static int tda1004x_set_fe(struct dvb_frontend *fe) return 0; } -static int tda1004x_get_fe(struct dvb_frontend *fe) +static int tda1004x_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda1004x_state* state = fe->demodulator_priv; dprintk("%s\n", __func__); diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 119d47596ac8..37ebeef2bbd0 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -701,11 +701,11 @@ error: return ret; } -static int tda10071_get_frontend(struct dvb_frontend *fe) +static int tda10071_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tda10071_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 buf[5], tmp; diff --git a/drivers/media/dvb-frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c index 95a33e187f8e..31d0acb54fe8 100644 --- a/drivers/media/dvb-frontends/tda10086.c +++ b/drivers/media/dvb-frontends/tda10086.c @@ -459,9 +459,9 @@ static int tda10086_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda10086_get_frontend(struct dvb_frontend *fe) +static int tda10086_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda10086_state* state = fe->demodulator_priv; u8 val; int tmp; diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 796543fa2c8d..9072d6463094 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c @@ -342,9 +342,9 @@ static int tda8083_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda8083_get_frontend(struct dvb_frontend *fe) +static int tda8083_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda8083_state* state = fe->demodulator_priv; /* FIXME: get symbolrate & frequency offset...*/ diff --git a/drivers/media/dvb-frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c index aacfdda3e005..b09fe88c40f8 100644 --- a/drivers/media/dvb-frontends/ves1820.c +++ b/drivers/media/dvb-frontends/ves1820.c @@ -312,9 +312,9 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int ves1820_get_frontend(struct dvb_frontend *fe) +static int ves1820_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1820_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c index 526952396422..ed113e216e14 100644 --- a/drivers/media/dvb-frontends/ves1x93.c +++ b/drivers/media/dvb-frontends/ves1x93.c @@ -406,9 +406,9 @@ static int ves1x93_set_frontend(struct dvb_frontend *fe) return 0; } -static int ves1x93_get_frontend(struct dvb_frontend *fe) +static int ves1x93_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1x93_state* state = fe->demodulator_priv; int afc; diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index ef9764a02d4c..1832c2f7695c 100644 --- a/drivers/media/dvb-frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c @@ -371,9 +371,9 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) return 0; } -static int zl10353_get_parameters(struct dvb_frontend *fe) +static int zl10353_get_parameters(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct zl10353_state *state = fe->demodulator_priv; int s6, s9; u16 tps; diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 4a90eee5e3bb..35bc9b2287b4 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1688,9 +1688,9 @@ static int dst_get_tuning_algo(struct dvb_frontend *fe) return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } -static int dst_get_frontend(struct dvb_frontend *fe) +static int dst_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dst_state *state = fe->demodulator_priv; p->frequency = state->decode_freq; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index 84f6de6fa07d..047a32fe43ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -507,9 +507,9 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe, return 0; } -static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe) +static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mxl111sf_demod_state *state = fe->demodulator_priv; mxl_dbg("()"); diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index ac97075d75f7..09db3d02bd82 100644 --- a/drivers/media/usb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c @@ -1227,9 +1227,9 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int af9005_fe_get_frontend(struct dvb_frontend *fe) +static int af9005_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct af9005_fe_state *state = fe->demodulator_priv; int ret; u8 temp; diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 7e72a1bef76a..c09332bd99cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -140,10 +140,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int dtt200u_fe_get_frontend(struct dvb_frontend* fe) +static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dtt200u_fe_state *state = fe->demodulator_priv; + memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties)); return 0; } -- cgit v1.2.3 From bb31d2381c730485be00a7da44c45416e9781709 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 13:26:22 -0200 Subject: [media] dvb_frontend: Don't let drivers to trash data at cache GET_FRONTEND and G_PROPERTY can be called anytime, even when the tuner/demod is not fully locked. However, several parameters returned by those calls are available only after the demod get VITERBI lock. While several drivers do the right thing by checking the status before returning the parameter, some drivers simply blindly update the DTV properties cache without checking if the registers at the hardware contain valid values. Due to that, programs that call G_PROPERTY (or GET_FRONTEND) before having a tuner lock may interfere at the zigzag logic, as the DVB kthread calls the set_frontend() callback several times, to fine tune the frequency and to identify if the signal is inverted or not. While the drivers should be fixed to report the right status, we should prevent that such bugs would actually interfere at the device operation. So, let's use a separate var for userspace calls to get frontend. As we copy the content of the cache, this should not cause any troubles. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index d009478f16c4..4c35eb47472b 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2087,6 +2087,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); } else if (cmd == FE_GET_PROPERTY) { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); @@ -2108,17 +2110,18 @@ static int dvb_frontend_ioctl_properties(struct file *file, } /* - * Fills the cache out struct with the cache contents, plus - * the data retrieved from get_frontend, if the frontend - * is not idle. Otherwise, returns the cached content + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, c, NULL); + err = dtv_get_frontend(fe, &getp, NULL); if (err < 0) goto out; } for (i = 0; i < tvps->num; i++) { - err = dtv_property_process_get(fe, c, tvp + i, file); + err = dtv_property_process_get(fe, &getp, tvp + i, file); if (err < 0) goto out; (tvp + i)->result = err; @@ -2523,10 +2526,18 @@ static int dvb_frontend_ioctl_legacy(struct file *file, err = dvb_frontend_get_event (fe, parg, file->f_flags); break; - case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, c, parg); - break; + case FE_GET_FRONTEND: { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + /* + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. + */ + err = dtv_get_frontend(fe, &getp, parg); + break; + } case FE_SET_FRONTEND_TUNE_MODE: fepriv->tune_mode_flags = (unsigned long) parg; err = 0; -- cgit v1.2.3 From 54d0dbac1266d2b9a6b5a87316162a068ad545bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 07:02:43 -0200 Subject: [media] v4l2-mc: add a generic function to create the media graph The em28xx_v4l2_create_media_graph() is almost generic enough to be at the core, as an ancillary function. Make it even more generic, by getting rid of em28xx-specific code, relying only at the media_device, in order to discover all entities found on PC-customer's hardware and add it at the V4L2 core. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 1 + drivers/media/v4l2-core/v4l2-mc.c | 186 ++++++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 25 +++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/media/v4l2-core/v4l2-mc.c diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 1dc8bba2b198..795a5352761d 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -16,6 +16,7 @@ endif ifeq ($(CONFIG_TRACEPOINTS),y) videodev-objs += vb2-trace.o v4l2-trace.o endif +videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o obj-$(CONFIG_VIDEO_V4L2) += videodev.o obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c new file mode 100644 index 000000000000..e6d2a711bb0b --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -0,0 +1,186 @@ +/* + * Media Controller ancillary functions + * + * (c) 2016 Mauro Carvalho Chehab + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +int v4l2_mc_create_media_graph(struct media_device *mdev) + +{ + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL, *sensor = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; + bool is_webcam = false; + u32 flags; + int ret; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + case MEDIA_ENT_F_IO_V4L: + io_v4l = entity; + break; + case MEDIA_ENT_F_IO_VBI: + io_vbi = entity; + break; + case MEDIA_ENT_F_IO_SWRADIO: + io_swradio = entity; + break; + case MEDIA_ENT_F_CAM_SENSOR: + sensor = entity; + is_webcam = true; + break; + } + } + + /* It should have at least one I/O entity */ + if (!io_v4l && !io_vbi && !io_swradio) + return -EINVAL; + + /* + * Here, webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is not enough + * for mc-centric hardware, it is enough for v4l2 interface centric + * PC-consumer's hardware. + */ + if (is_webcam) { + if (!io_v4l) + return -EINVAL; + + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + if (!decoder) + return 0; + } + + /* The device isn't a webcam. So, it should have a decoder */ + if (!decoder) + return -EINVAL; + + /* Link the tuner and IF video output pads */ + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + + /* Create demod to V4L, VBI and SDR radio links */ + if (io_v4l) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_swradio) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_swradio, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_vbi) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + io_vbi, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + /* Create links for the media connectors */ + flags = MEDIA_LNK_FL_ENABLED; + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_CONN_RF: + if (!tuner) + continue; + + ret = media_create_pad_link(entity, 0, tuner, + TUNER_PAD_RF_INPUT, + flags); + break; + case MEDIA_ENT_F_CONN_SVIDEO: + case MEDIA_ENT_F_CONN_COMPOSITE: + case MEDIA_ENT_F_CONN_TEST: + ret = media_create_pad_link(entity, 0, decoder, + DEMOD_PAD_IF_INPUT, + flags); + break; + default: + continue; + } + if (ret) + return ret; + + flags = 0; + } + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph); diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index df115195690e..aed9e9b87f82 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +#include + /** * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER * @@ -89,3 +91,26 @@ enum demod_pad_index { DEMOD_PAD_VBI_OUT, DEMOD_NUM_PADS }; + +/** + * v4l2_mc_create_media_graph() - create Media Controller links at the graph. + * + * @mdev: pointer to the &media_device struct. + * + * Add links between the entities commonly found on PC customer's hardware at + * the V4L2 side: camera sensors, audio and video PLL-IF decoders, tuners, + * analog TV decoder and I/O entities (video, VBI and Software Defined Radio). + * NOTE: webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is enough for v4l2 + * interface centric PC-consumer's hardware, V4L2 subdev centric camera + * hardware should not use this routine, as it will not build the right graph. + */ +#ifdef CONFIG_MEDIA_CONTROLLER +int v4l2_mc_create_media_graph(struct media_device *mdev); +#else +static inline int v4l2_mc_create_media_graph(struct media_device *mdev) +{ + return 0; +} +#endif -- cgit v1.2.3 From de39078779cb08b21e7e3d2daa7d3b64a53a8d20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 07:08:25 -0200 Subject: [media] em2xx: use v4l2_mc_create_media_graph() Now that the core has a function to create the media graph, we can get rid of the specialized code at em28xx. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 131 +------------------------------- 1 file changed, 1 insertion(+), 130 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 16a2d4039330..e7fd0bac4a08 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -883,135 +883,6 @@ static void em28xx_v4l2_media_release(struct em28xx *dev) * Media Controller helper functions */ -static int em28xx_v4l2_create_media_graph(struct em28xx *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct em28xx_v4l2 *v4l2 = dev->v4l2; - struct media_device *mdev = dev->media_dev; - struct media_entity *entity; - struct media_entity *if_vid = NULL, *if_aud = NULL; - struct media_entity *tuner = NULL, *decoder = NULL; - int i, ret; - - if (!mdev) - return 0; - - /* Webcams are really simple */ - if (dev->board.is_webcam) { - media_device_for_each_entity(entity, mdev) { - if (entity->function != MEDIA_ENT_F_CAM_SENSOR) - continue; - ret = media_create_pad_link(entity, 0, - &v4l2->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - return 0; - } - - /* Non-webcams have analog TV decoder and other complexities */ - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_IF_VID_DECODER: - if_vid = entity; - break; - case MEDIA_ENT_F_IF_AUD_DECODER: - if_aud = entity; - break; - case MEDIA_ENT_F_TUNER: - tuner = entity; - break; - case MEDIA_ENT_F_ATV_DECODER: - decoder = entity; - break; - } - } - - /* Analog setup, using tuner as a link */ - - /* Something bad happened! */ - if (!decoder) - return -EINVAL; - - if (tuner) { - if (if_vid) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - if_vid, - IF_VID_DEC_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } else { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - - if (if_aud) { - ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, - if_aud, - IF_AUD_DEC_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } else { - if_aud = tuner; - } - - } - ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, - &v4l2->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - if (em28xx_vbi_supported(dev)) { - ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, - &v4l2->vbi_dev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - - for (i = 0; i < MAX_EM28XX_INPUT; i++) { - struct media_entity *ent = &dev->input_ent[i]; - - if (!INPUT(i)->type) - break; - - switch (INPUT(i)->type) { - case EM28XX_VMUX_COMPOSITE: - case EM28XX_VMUX_SVIDEO: - ret = media_create_pad_link(ent, 0, decoder, - DEMOD_PAD_IF_INPUT, 0); - if (ret) - return ret; - break; - default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ - if (!tuner) - break; - - ret = media_create_pad_link(ent, 0, tuner, - TUNER_PAD_RF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - break; - } - } -#endif - return 0; -} - static int em28xx_enable_analog_tuner(struct em28xx *dev) { #ifdef CONFIG_MEDIA_CONTROLLER @@ -2842,7 +2713,7 @@ static int em28xx_v4l2_init(struct em28xx *dev) /* Init entities at the Media Controller */ em28xx_v4l2_create_entities(dev); - ret = em28xx_v4l2_create_media_graph(dev); + ret = v4l2_mc_create_media_graph(dev->media_dev); if (ret) { em28xx_errdev("failed to create media graph\n"); em28xx_v4l2_media_release(dev); -- cgit v1.2.3 From 2773b0e9baa68beed1f93d04a8ae8ca04b35a60d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 08:35:50 -0200 Subject: [media] add media controller support to videobuf2-dvb Allow devices to pass an optional argument to register the DVB driver at the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 3 ++- drivers/media/pci/cx88/cx88-dvb.c | 3 ++- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 4 ++-- drivers/media/pci/saa7134/saa7134-dvb.c | 2 +- drivers/media/v4l2-core/videobuf2-dvb.c | 13 +++++++++++-- include/media/videobuf2-dvb.h | 5 +++++ 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 80319bb73d94..5131c9f555fb 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -2301,7 +2301,8 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = vb2_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, + adapter_nr, mfe_shared); if (ret) goto frontend_detach; diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index afb20756d7a5..851d2a9caed3 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1642,7 +1642,8 @@ static int dvb_register(struct cx8802_dev *dev) /* register everything */ res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, adapter_nr, + mfe_shared); if (res) goto frontend_detach; return res; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index c94cecd2aa40..2b667b315913 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -462,8 +462,8 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev, } if (vb2_dvb_register_bus(&ndev->frontends[num], - THIS_MODULE, NULL, - &ndev->pci_dev->dev, adapter_nr, 1)) { + THIS_MODULE, NULL, + &ndev->pci_dev->dev, NULL, adapter_nr, 1)) { dev_dbg(&ndev->pci_dev->dev, "%s(): unable to register DVB bus %d\n", __func__, num); diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index 101ba8729416..ed84f7dea94c 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1884,7 +1884,7 @@ static int dvb_init(struct saa7134_dev *dev) /* register everything else */ ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, 0); + &dev->pci->dev, NULL, adapter_nr, 0); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/v4l2-core/videobuf2-dvb.c b/drivers/media/v4l2-core/videobuf2-dvb.c index d09269846b7e..9f38b4218c0d 100644 --- a/drivers/media/v4l2-core/videobuf2-dvb.c +++ b/drivers/media/v4l2-core/videobuf2-dvb.c @@ -77,6 +77,7 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, char *adapter_name, short *adapter_nr, int mfe_shared) @@ -94,7 +95,10 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, } fe->adapter.priv = adapter_priv; fe->adapter.mfe_shared = mfe_shared; - +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + if (mdev) + fe->adapter.mdev = mdev; +#endif return result; } @@ -193,6 +197,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared) { @@ -207,7 +212,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, } /* Bring up the adapter */ - res = vb2_dvb_register_adapter(f, module, adapter_priv, device, + res = vb2_dvb_register_adapter(f, module, adapter_priv, device, mdev, fe->dvb.name, adapter_nr, mfe_shared); if (res < 0) { pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res); @@ -224,7 +229,11 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, fe->dvb.name, res); goto err; } + res = dvb_create_media_graph(&f->adapter, false); + if (res < 0) + goto err; } + mutex_unlock(&f->lock); return 0; diff --git a/include/media/videobuf2-dvb.h b/include/media/videobuf2-dvb.h index 5b64c9eac2c9..87b559024b4a 100644 --- a/include/media/videobuf2-dvb.h +++ b/include/media/videobuf2-dvb.h @@ -8,6 +8,10 @@ #include #include + +/* We don't actually need to include media-device.h here */ +struct media_device; + /* * TODO: This header file should be replaced with videobuf2-core.h * Currently, vb2_thread is not a stuff of videobuf2-core, @@ -50,6 +54,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared); -- cgit v1.2.3 From 8fc3486783f1571c7d836d397c8ff4fa2ca6457c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 10:24:37 -0200 Subject: [media] saa7134: use input types, instead of hardcoding strings Currently, the saa7134 driver is hardcoding input names on each board entry. More modern drivers define, instead, an enum for each input type. While the current logic works, it adds extra complexity at the driver, as it needs to discover the type of the input using some euristics. Instead, let's standardize the input types and use a type, instead of a name on all places. That will allow further patches to properly report the input type via VIDIOC_G_INPUT and to remove an extra field from the struct to identify if the input is for TV. Please notice that several boards define an input for receiving composite signals via a S-Video connector. The name of such input was inconsistent, so this patch cleans it and make it to be properly reported the same way for all boards. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-cards.c | 1619 ++++++++++++++------------- drivers/media/pci/saa7134/saa7134-core.c | 2 +- drivers/media/pci/saa7134/saa7134-tvaudio.c | 13 +- drivers/media/pci/saa7134/saa7134-video.c | 11 +- drivers/media/pci/saa7134/saa7134.h | 33 +- 5 files changed, 853 insertions(+), 825 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 29d2094c42a0..19975cec5da7 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -36,17 +36,23 @@ #include "xc5000.h" #include "s5h1411.h" -/* commly used strings */ -static char name_mute[] = "mute"; -static char name_radio[] = "Radio"; -static char name_tv[] = "Television"; -static char name_tv_mono[] = "TV (mono only)"; -static char name_comp[] = "Composite"; -static char name_comp1[] = "Composite1"; -static char name_comp2[] = "Composite2"; -static char name_comp3[] = "Composite3"; -static char name_comp4[] = "Composite4"; -static char name_svideo[] = "S-Video"; +/* Input names */ +const char * const saa7134_input_name[] = { + [SAA7134_INPUT_MUTE] = "mute", + [SAA7134_INPUT_RADIO] = "Radio", + [SAA7134_INPUT_TV] = "Television", + [SAA7134_INPUT_TV_MONO] = "TV (mono only)", + [SAA7134_INPUT_COMPOSITE] = "Composite", + [SAA7134_INPUT_COMPOSITE0] = "Composite0", + [SAA7134_INPUT_COMPOSITE1] = "Composite1", + [SAA7134_INPUT_COMPOSITE2] = "Composite2", + [SAA7134_INPUT_COMPOSITE3] = "Composite3", + [SAA7134_INPUT_COMPOSITE4] = "Composite4", + [SAA7134_INPUT_SVIDEO] = "S-Video", + [SAA7134_INPUT_SVIDEO0] = "S-Video0", + [SAA7134_INPUT_SVIDEO1] = "S-Video1", + [SAA7134_INPUT_COMPOSITE_OVER_SVIDEO] = "Composite over S-Video", +}; /* ------------------------------------------------------------------ */ /* board config info */ @@ -69,7 +75,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = "default", + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE1, }}, @@ -84,22 +90,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -114,40 +120,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -163,34 +169,34 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x8000, }, @@ -205,20 +211,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -235,40 +241,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x1E000, /* Set GP16 and unused 15,14,13 to Output */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x10000, /* GP16=1 selects TV input */ .tv = 1, },{ -/* .name = name_tv_mono, +/* .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ -*/ .name = name_comp1, /* Composite signal on S-Video input */ +*/ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, /* .gpio = 0x4000, */ },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, /* .gpio = 0x4000, */ },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, /* .gpio = 0x4000, */ }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00000, /* GP16=0 selects FM radio antenna */ }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x10000, }, @@ -285,40 +291,40 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0xe000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, }, { - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -334,21 +340,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -364,21 +370,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -390,35 +396,35 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ /* workaround for problems with normal TV sound */ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -432,32 +438,32 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -472,24 +478,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x820000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x20000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x20000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x20000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x20000, }, @@ -504,20 +510,20 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }} @@ -531,31 +537,31 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ /* workaround for problems with normal TV sound */ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -567,15 +573,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -590,25 +596,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -622,25 +628,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -655,21 +661,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -681,15 +687,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, .tv = 1, @@ -703,16 +709,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 8, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 8, .amux = LINE2, .tv = 1, @@ -726,21 +732,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 6, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -753,21 +759,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -780,29 +786,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, .gpio = 0x0000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, .gpio = 0x0000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .gpio = 0x0000, }, @@ -815,15 +821,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -839,34 +845,34 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x8000, }, @@ -881,23 +887,23 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 0, .amux = LINE1, },{ - .name = name_comp4, + .type = SAA7134_INPUT_COMPOSITE4, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -912,15 +918,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -935,17 +941,17 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x06c00012, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x0ac20012, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x08c20012, @@ -968,23 +974,23 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xcf00, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .gpio = 2 << 14, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .gpio = 1 << 14, },{ - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 0, .gpio = 0 << 14, },{ - .name = name_comp4, + .type = SAA7134_INPUT_COMPOSITE4, .vmux = 0, .gpio = 3 << 14, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .gpio = 2 << 14, }}, @@ -999,34 +1005,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x02, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, .gpio = 0x02, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x02, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x00, }, @@ -1041,15 +1047,15 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, @@ -1068,22 +1074,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -1096,20 +1102,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1123,21 +1129,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1150,21 +1156,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1177,16 +1183,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1199,30 +1205,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1234,30 +1240,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1270,30 +1276,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1306,30 +1312,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x200000, }, @@ -1343,10 +1349,10 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, }}, }, @@ -1360,7 +1366,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -1375,15 +1381,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, }}, }, @@ -1396,29 +1402,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1432,29 +1438,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1467,12 +1473,12 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 7, .amux = TV, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, }}, @@ -1486,21 +1492,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1512,25 +1518,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, }, }, @@ -1544,29 +1550,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x808c0080, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00080, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00080, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2_LEFT, .tv = 1, .gpio = 0x00080, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x80000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x40000, }, @@ -1580,21 +1586,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1607,15 +1613,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -1631,29 +1637,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x4000, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x8000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x8000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x8000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x8000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio =0x8000, } @@ -1672,29 +1678,29 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, },{ - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE1, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -1709,29 +1715,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00300003, /* .gpiomask = 0x8c240003, */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00300001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -1745,21 +1751,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -1774,24 +1780,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x08000000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x08000000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x08000000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x08000000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x00000000, }, @@ -1805,21 +1811,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -1834,25 +1840,25 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1866,29 +1872,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x1ce780, .inputs = {{ - .name = name_svideo, - .vmux = 0, /* CVideo over SVideo Connector - ok? */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, + .vmux = 0, .amux = LINE1, .gpio = 0x008080, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x008080, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x008080, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x80000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x0c8000, }, @@ -1903,20 +1909,20 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1931,22 +1937,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1961,25 +1967,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1995,26 +2001,26 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00200000, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2028,11 +2034,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2049,20 +2055,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2075,16 +2081,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2098,29 +2104,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x0700, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, /* gpio by DScaler */ },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x200, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x000, }, @@ -2135,26 +2141,26 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2168,29 +2174,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x8c1880, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x800800, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x801000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x800000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x880000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x840000, }, @@ -2213,29 +2219,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x0700, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, /* gpio by DScaler */ },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x200, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x000, }, @@ -2248,30 +2254,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, /* radio unconfirmed */ + .type = SAA7134_INPUT_RADIO, /* radio unconfirmed */ .amux = LINE2, }, }, @@ -2286,24 +2292,24 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x0000000, .tv = 1, },{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0000000, },{ - .name = name_svideo, /* S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0000000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2322,29 +2328,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr= ADDR_UNSET, .gpiomask = 0x00010003, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x00010003, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -2362,21 +2368,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -2392,34 +2398,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00200003, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00200003, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x00200003, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00200003, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00200003, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x00200003, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x00200003, }, @@ -2434,16 +2440,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2458,16 +2464,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2481,11 +2487,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2499,27 +2505,28 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x21, .inputs = {{ - .name = "Composite 0", + .type = SAA7134_INPUT_COMPOSITE0, .vmux = 0, .amux = LINE1, },{ - .name = "Composite 1", + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = "Composite 2", + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 2, .amux = LINE1, },{ - .name = "Composite 3", + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 3, .amux = LINE2, },{ - .name = "S-Video 0", + .type = SAA7134_INPUT_SVIDEO0, + .vmux = 8, .amux = LINE1, },{ - .name = "S-Video 1", + .type = SAA7134_INPUT_SVIDEO1, .vmux = 9, .amux = LINE2, }}, @@ -2538,27 +2545,27 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = "Composite 0", + .type = SAA7134_INPUT_COMPOSITE0, .vmux = 0, .amux = LINE1, },{ - .name = "Composite 1", + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = "Composite 2", + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 2, .amux = LINE1, },{ - .name = "Composite 3", + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 3, .amux = LINE2, },{ - .name = "S-Video 0", + .type = SAA7134_INPUT_SVIDEO0, .vmux = 8, .amux = LINE1, },{ - .name = "S-Video 1", + .type = SAA7134_INPUT_SVIDEO1, .vmux = 9, .amux = LINE2, }}, @@ -2572,20 +2579,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2604,11 +2611,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2622,16 +2629,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -2645,25 +2652,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x080200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2678,29 +2685,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0200000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2717,21 +2724,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xe880c0, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -2745,16 +2752,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2770,21 +2777,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2798,25 +2805,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, /* unconfirmed, taken from Philips driver */ },{ - .name = name_comp2, - .vmux = 0, /* untested, Composite over S-Video */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, + .vmux = 0, /* untested */ .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2834,17 +2841,17 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x80200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_svideo, /* NOT tested */ + .type = SAA7134_INPUT_SVIDEO, /* NOT tested */ .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2861,26 +2868,26 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00200000, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, /* Analog broadcast/cable TV */ + .type = SAA7134_INPUT_TV, /* Analog broadcast/cable TV */ .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2894,11 +2901,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2914,11 +2921,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2933,7 +2940,7 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -2950,25 +2957,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2983,21 +2990,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3012,16 +3019,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -3052,17 +3059,17 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0xca60000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, .gpio = 0x04a61000, },{ - .name = name_comp2, /* Composite SVIDEO (B/W if signal is carried with SVIDEO) */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, /* 9 is correct as S-VIDEO1 according to a169.inf! */ .amux = LINE1, }}, @@ -3086,26 +3093,26 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -3121,40 +3128,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -3168,16 +3175,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -3193,11 +3200,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -3211,25 +3218,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -3244,21 +3251,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -3272,21 +3279,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT| TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -3301,25 +3308,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x000200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3335,34 +3342,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x00, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x00, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x00, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -3378,16 +3385,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -3405,22 +3412,22 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200100, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200100, }, @@ -3438,22 +3445,22 @@ struct saa7134_board saa7134_boards[] = { .ts_force_val = 1, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0800100, /* GPIO 23 HI for FM */ }, @@ -3470,22 +3477,22 @@ struct saa7134_board saa7134_boards[] = { .ts_type = SAA7134_MPEG_TS_SERIAL, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0800100, /* GPIO 23 HI for FM */ }, @@ -3499,16 +3506,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -3523,33 +3530,33 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = 2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, /* .gpio = 0x00300001,*/ .gpio = 0x20000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = 0, }, }, @@ -3562,32 +3569,32 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = 2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x20000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = 0, }, }, @@ -3600,29 +3607,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x7000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 1, .tv = 1, .gpio = 0x50000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, .gpio = 0x2000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = 2, .gpio = 0x2000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = 1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .gpio = 0xf000, .amux = 0, }, @@ -3635,26 +3642,26 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = 0x61, .radio_addr = 0x60, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x43000, }, @@ -3668,16 +3675,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -3693,21 +3700,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3721,16 +3728,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1<<21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, @@ -3746,7 +3753,7 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -3764,29 +3771,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0200000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3800,26 +3807,26 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3832,25 +3839,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -3864,24 +3871,24 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x7000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x2000, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x3000, }, @@ -3896,7 +3903,7 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, /* FIXME: analog tv untested */ + .type = SAA7134_INPUT_TV, /* FIXME: analog tv untested */ .vmux = 1, .amux = TV, .tv = 1, @@ -3912,26 +3919,26 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_GP0_HIGH_OFF }, .gpiomask = 0x020200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -3946,26 +3953,26 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .gpiomask = 0x020200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -3981,21 +3988,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -4010,15 +4017,15 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, @@ -4035,21 +4042,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4065,15 +4072,15 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, @@ -4092,21 +4099,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4122,17 +4129,17 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, @@ -4151,24 +4158,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, .gpio = 0xc0c000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0xc0c000, }, @@ -4185,16 +4192,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -4211,25 +4218,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4246,25 +4253,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4280,21 +4287,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4311,21 +4318,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4342,21 +4349,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4372,24 +4379,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x000A8004, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, .gpio = 0x000A8004, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0x000A8000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x000A8000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x000A8000, }, @@ -4404,21 +4411,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4432,21 +4439,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4460,21 +4467,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4488,21 +4495,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4517,21 +4524,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4546,21 +4553,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4575,21 +4582,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4604,21 +4611,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4636,21 +4643,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4673,21 +4680,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4712,21 +4719,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4747,21 +4754,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, /* untested */ .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -4776,30 +4783,30 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xf000, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, .tv = 1 }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x2000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x1000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x6000, }, @@ -4813,11 +4820,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -4832,16 +4839,16 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -4857,21 +4864,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -4885,21 +4892,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -4912,21 +4919,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -4938,16 +4945,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -4962,21 +4969,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, } }, @@ -4990,11 +4997,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, @@ -5009,21 +5016,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5038,21 +5045,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -5067,21 +5074,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5097,21 +5104,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5125,29 +5132,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x801a8087, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, .gpio = 0x624000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0x624000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 1, .amux = LINE1, .gpio = 0x624000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x624001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -5161,16 +5168,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -5186,25 +5193,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5218,30 +5225,30 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x80000700, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, .gpio = 0x100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x200, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 8, .amux = 2, }, @@ -5257,18 +5264,18 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, #if 0 /* FIXME */ }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x200, @@ -5276,14 +5283,14 @@ struct saa7134_board saa7134_boards[] = { } }, #if 0 .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, .gpio = 0x100, }, #endif .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 0, .amux = TV, }, @@ -5298,24 +5305,24 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00300003, /* .gpiomask = 0x8c240003, */ .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x02, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00300001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -5331,29 +5338,29 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -5368,11 +5375,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, /* Not tested */ .amux = LINE1 } }, @@ -5387,21 +5394,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5416,13 +5423,13 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, } }, .radio = { /* untested */ - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5436,16 +5443,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -5459,10 +5466,10 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, } }, }, @@ -5479,25 +5486,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -5512,7 +5519,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x389c00, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x01fc00, @@ -5529,21 +5536,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5556,21 +5563,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5584,16 +5591,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -5607,25 +5614,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = 0x60, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -5642,29 +5649,29 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00050000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00050000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00050000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00050000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 0, .amux = TV, .gpio = 0x00050000, @@ -5681,21 +5688,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5710,21 +5717,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5736,15 +5743,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 2, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -5760,21 +5767,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0000000, }, @@ -5790,7 +5797,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x618E700, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x6010000, @@ -5809,21 +5816,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 11, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0000800, }, @@ -5837,16 +5844,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_GO7007, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, @@ -5862,25 +5869,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5893,29 +5900,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x0d, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE1, .gpio = 0x00, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x08, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x08, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x04, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x08, }, diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index e227b02cc122..31048f9b516a 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -112,7 +112,7 @@ int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); printk(KERN_DEBUG pr_fmt("irq: " fmt), ## arg); \ } while (0) -void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) +void saa7134_track_gpio(struct saa7134_dev *dev, const char *msg) { unsigned long mode,status; diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c index 21a579309575..38f94b742e28 100644 --- a/drivers/media/pci/saa7134/saa7134-tvaudio.c +++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c @@ -192,7 +192,7 @@ static void mute_input_7134(struct saa7134_dev *dev) in = dev->input; mute = (dev->ctl_mute || (dev->automute && (&card(dev).radio) != in)); - if (card(dev).mute.name) { + if (card(dev).mute.type) { /* * 7130 - we'll mute using some unconnected audio input * 7134 - we'll probably should switch external mux with gpio @@ -204,13 +204,14 @@ static void mute_input_7134(struct saa7134_dev *dev) if (dev->hw_mute == mute && dev->hw_input == in && !dev->insuspend) { audio_dbg(1, "mute/input: nothing to do [mute=%d,input=%s]\n", - mute, in->name); + mute, saa7134_input_name[in->type]); return; } audio_dbg(1, "ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n", dev->ctl_mute, dev->automute, - dev->input->name, mute, in->name); + saa7134_input_name[dev->input->type], mute, + saa7134_input_name[in->type]); dev->hw_mute = mute; dev->hw_input = in; @@ -245,7 +246,7 @@ static void mute_input_7134(struct saa7134_dev *dev) mask = card(dev).gpiomask; saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa7134_track_gpio(dev, saa7134_input_name[in->type]); } static void tvaudio_setmode(struct saa7134_dev *dev, @@ -756,14 +757,14 @@ static int mute_input_7133(struct saa7134_dev *dev) if (0 != card(dev).gpiomask) { mask = card(dev).gpiomask; - if (card(dev).mute.name && dev->ctl_mute) + if (card(dev).mute.type && dev->ctl_mute) in = &card(dev).mute; else in = dev->input; saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa7134_track_gpio(dev, saa7134_input_name[in->type]); } return 0; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 7a42d3ae3ac9..ae52ef019e43 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -409,7 +409,8 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) static void video_mux(struct saa7134_dev *dev, int input) { - video_dbg("video input = %d [%s]\n", input, card_in(dev, input).name); + video_dbg("video input = %d [%s]\n", + input, saa7134_input_name[card_in(dev, input).type]); dev->ctl_input = input; set_tvnorm(dev, dev->tvnorm); saa7134_tvaudio_setinput(dev, &card_in(dev, input)); @@ -1381,11 +1382,11 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i) n = i->index; if (n >= SAA7134_INPUT_MAX) return -EINVAL; - if (NULL == card_in(dev, i->index).name) + if (card_in(dev, i->index).type == SAA7134_NO_INPUT) return -EINVAL; i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, card_in(dev, n).name); + strcpy(i->name, saa7134_input_name[card_in(dev, n).type]); if (card_in(dev, n).tv) i->type = V4L2_INPUT_TYPE_TUNER; if (n == dev->ctl_input) { @@ -1419,7 +1420,7 @@ int saa7134_s_input(struct file *file, void *priv, unsigned int i) if (i >= SAA7134_INPUT_MAX) return -EINVAL; - if (NULL == card_in(dev, i).name) + if (card_in(dev, i).type == SAA7134_NO_INPUT) return -EINVAL; video_mux(dev, i); return 0; @@ -1661,7 +1662,7 @@ int saa7134_g_tuner(struct file *file, void *priv, } if (n == SAA7134_INPUT_MAX) return -EINVAL; - if (NULL != card_in(dev, n).name) { + if (card_in(dev, n).type != SAA7134_NO_INPUT) { strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; saa_call_all(dev, tuner, g_tuner, t); diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 5938bc781999..274a472e7d6b 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -361,12 +361,30 @@ struct saa7134_card_ir { #define SET_CLOCK_INVERTED (1 << 2) #define SET_VSYNC_OFF (1 << 3) +enum saa7134_input_types { + SAA7134_NO_INPUT = 0, + SAA7134_INPUT_MUTE, + SAA7134_INPUT_RADIO, + SAA7134_INPUT_TV, + SAA7134_INPUT_TV_MONO, + SAA7134_INPUT_COMPOSITE, + SAA7134_INPUT_COMPOSITE0, + SAA7134_INPUT_COMPOSITE1, + SAA7134_INPUT_COMPOSITE2, + SAA7134_INPUT_COMPOSITE3, + SAA7134_INPUT_COMPOSITE4, + SAA7134_INPUT_SVIDEO, + SAA7134_INPUT_SVIDEO0, + SAA7134_INPUT_SVIDEO1, + SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, +}; + struct saa7134_input { - char *name; - unsigned int vmux; - enum saa7134_audio_in amux; - unsigned int gpio; - unsigned int tv:1; + enum saa7134_input_types type; + unsigned int vmux; + enum saa7134_audio_in amux; + unsigned int gpio; + unsigned int tv:1; }; enum saa7134_mpeg_type { @@ -410,7 +428,7 @@ struct saa7134_board { unsigned int ts_force_val:1; }; -#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) +#define card_has_radio(dev) (SAA7134_NO_INPUT != saa7134_boards[dev->board].radio.type) #define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) #define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) #define card_is_go7007(dev) (SAA7134_MPEG_GO7007 == saa7134_boards[dev->board].mpeg) @@ -727,7 +745,7 @@ extern struct mutex saa7134_devlist_lock; extern int saa7134_no_overlay; extern bool saa7134_userptr; -void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); +void saa7134_track_gpio(struct saa7134_dev *dev, const char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); #define SAA7134_PGTABLE_SIZE 4096 @@ -760,6 +778,7 @@ extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); /* saa7134-cards.c */ extern struct saa7134_board saa7134_boards[]; +extern const char * const saa7134_input_name[]; extern const unsigned int saa7134_bcount; extern struct pci_device_id saa7134_pci_tbl[]; -- cgit v1.2.3 From 568b2febeeb139879efe93756aa58e2e42559f90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 11:14:05 -0200 Subject: [media] saa7134: unconditionlally update TV standard at demod It doesn't make any sense to only update the TV standard for TV, as composite and S-Video inputs also need it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index ae52ef019e43..59781755247a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -479,8 +479,7 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) { saa7134_set_decoder(dev); - if (card_in(dev, dev->ctl_input).tv) - saa_call_all(dev, video, s_std, dev->tvnorm->id); + saa_call_all(dev, video, s_std, dev->tvnorm->id); /* Set the correct norm for the saa6752hs. This function does nothing if there is no saa6752hs. */ saa_call_empress(dev, video, s_std, dev->tvnorm->id); -- cgit v1.2.3 From 8bf77f9e7013e46ca08151189357532f027c47e8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 10:37:18 -0200 Subject: [media] saa7134: Get rid of struct saa7134_input.tv field The saa7134_input.tv field was used to indicate if an input had a RF signal for TV input. This is not needed anymore, as the input type can be checked directly by the driver. Also, due to a past bug when setting the TV standard at the demod, all inputs should have this field set, with is wrong. This reduces the size of the saa7134_boards by about 8KB, on i386 (and probably twice on 64 bits), with is a nice colateral effect: text data bss dec hex filename 241047 136831 66356 444234 6c74a drivers/media/pci/saa7134/saa7134.o.old 240851 128895 66292 436038 6a746 drivers/media/pci/saa7134/saa7134.o Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-cards.c | 194 ------------------------------ drivers/media/pci/saa7134/saa7134-video.c | 13 +- drivers/media/pci/saa7134/saa7134.h | 1 - 3 files changed, 10 insertions(+), 198 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 19975cec5da7..9a2fdc78eb85 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -97,12 +97,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -124,13 +122,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -173,7 +169,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -214,7 +209,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -245,13 +239,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x10000, /* GP16=1 selects TV input */ - .tv = 1, },{ /* .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ */ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -295,13 +287,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, }, { .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -351,7 +341,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -373,7 +362,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -399,13 +387,11 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ /* workaround for problems with normal TV sound */ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -441,12 +427,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, @@ -481,7 +465,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x20000, },{ .type = SAA7134_INPUT_SVIDEO, @@ -513,7 +496,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -540,13 +522,11 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ /* workaround for problems with normal TV sound */ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -584,7 +564,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_CINERGY600] = { @@ -599,7 +578,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -631,7 +609,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -664,7 +641,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -698,7 +674,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_ELSA_500TV] = { @@ -716,12 +691,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 8, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 8, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_ELSA_700TV] = { @@ -735,7 +708,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 6, @@ -762,7 +734,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -790,7 +761,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -832,7 +802,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_10MOONSTVMASTER] = { @@ -849,7 +818,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -929,7 +897,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = { @@ -955,7 +922,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x08c20012, - .tv = 1, }}, /* radio and probably mute is missing */ }, [SAA7134_BOARD_CRONOS_PLUS] = { @@ -1008,7 +974,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -1058,7 +1023,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }}, .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, @@ -1077,7 +1041,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -1105,7 +1068,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1140,7 +1102,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -1167,7 +1128,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .mute = { .type = SAA7134_INPUT_MUTE, @@ -1186,7 +1146,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1208,12 +1167,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1243,12 +1200,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1279,12 +1234,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1315,12 +1268,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1369,7 +1320,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, } }, }, [SAA7134_BOARD_NOVAC_PRIMETV7133] = { @@ -1387,7 +1337,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -1405,7 +1354,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1441,7 +1389,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1476,7 +1423,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 7, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 7, @@ -1495,7 +1441,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -1521,7 +1466,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -1563,7 +1507,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2_LEFT, - .tv = 1, .gpio = 0x00080, }}, .radio = { @@ -1593,7 +1536,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -1624,7 +1566,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = { @@ -1641,7 +1582,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1681,7 +1621,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, },{ .type = SAA7134_INPUT_COMPOSITE, @@ -1718,7 +1657,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -1754,7 +1692,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1783,7 +1720,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x08000000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -1814,12 +1750,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1843,7 +1777,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -1885,7 +1818,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x008080, }}, .radio = { @@ -1912,7 +1844,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1944,12 +1875,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -1970,7 +1899,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2005,7 +1933,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -2058,7 +1985,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2084,7 +2010,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2107,7 +2032,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2145,7 +2069,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -2187,7 +2110,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x800000, }}, .radio = { @@ -2222,7 +2144,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2257,12 +2178,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2296,7 +2215,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x0000000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2331,7 +2249,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2371,7 +2288,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2401,7 +2317,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00200003, },{ .type = SAA7134_INPUT_TV_MONO, @@ -2443,7 +2358,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2467,7 +2381,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2582,7 +2495,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -2632,7 +2544,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2655,7 +2566,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2688,7 +2598,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2727,7 +2636,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2755,7 +2663,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2780,7 +2687,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2808,7 +2714,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, @@ -2844,7 +2749,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, /* NOT tested */ .vmux = 8, @@ -2872,7 +2776,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -2943,7 +2846,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00200000, }}, }, @@ -2960,7 +2862,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2993,7 +2894,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3022,7 +2922,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3062,7 +2961,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, .gpio = 0x04a61000, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, @@ -3097,7 +2995,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -3132,13 +3029,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3178,7 +3073,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3221,7 +3115,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3254,7 +3147,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3282,7 +3174,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -3311,7 +3202,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -3345,7 +3235,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -3388,7 +3277,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -3415,7 +3303,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3448,7 +3335,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3480,7 +3366,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3509,7 +3394,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3533,12 +3417,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3572,12 +3454,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3610,7 +3490,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 1, - .tv = 1, .gpio = 0x50000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3645,7 +3524,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3678,7 +3556,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3703,7 +3580,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3731,7 +3607,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3756,7 +3631,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0200000, }}, }, @@ -3774,7 +3648,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -3810,7 +3683,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3842,7 +3714,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3875,7 +3746,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3906,7 +3776,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, /* FIXME: analog tv untested */ .vmux = 1, .amux = TV, - .tv = 1, }}, }, [SAA7134_BOARD_AVERMEDIA_M135A] = { @@ -3922,7 +3791,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3956,7 +3824,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3999,7 +3866,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .mute = { .type = SAA7134_INPUT_MUTE, @@ -4028,7 +3894,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_BEHOLD_403FM] = { @@ -4053,7 +3918,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -4083,7 +3947,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_BEHOLD_405FM] = { @@ -4110,7 +3973,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -4142,7 +4004,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0xc0c000, }}, }, @@ -4171,7 +4032,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0xc0c000, }}, .radio = { @@ -4195,7 +4055,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4221,7 +4080,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4256,7 +4114,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4290,7 +4147,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4321,7 +4177,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4352,7 +4207,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4382,7 +4236,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0x000A8004, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -4414,7 +4267,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4442,7 +4294,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4470,7 +4321,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4498,7 +4348,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4527,7 +4376,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4556,7 +4404,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4585,7 +4432,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4614,7 +4460,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4646,7 +4491,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4683,7 +4527,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4722,7 +4565,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4757,7 +4599,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4787,13 +4628,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, - .tv = 1 }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -4842,7 +4681,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -4867,7 +4705,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4895,7 +4732,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4922,7 +4758,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -4948,7 +4783,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4972,7 +4806,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5019,7 +4852,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, @@ -5048,7 +4880,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5077,7 +4908,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, @@ -5107,7 +4937,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, @@ -5135,7 +4964,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, .gpio = 0x624000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5171,7 +4999,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -5196,7 +5023,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -5228,7 +5054,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, .gpio = 0x100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5267,7 +5092,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, #if 0 /* FIXME */ }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5308,7 +5132,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, }, { .type = SAA7134_INPUT_SVIDEO, @@ -5341,7 +5164,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5397,7 +5219,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5426,7 +5247,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, } }, .radio = { /* untested */ .type = SAA7134_INPUT_RADIO, @@ -5446,7 +5266,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -5489,7 +5308,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5539,7 +5357,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5566,7 +5383,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5594,7 +5410,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5617,7 +5432,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -5652,7 +5466,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00050000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5691,7 +5504,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5720,7 +5532,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5770,7 +5581,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, @@ -5819,7 +5629,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -5851,7 +5660,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 6, @@ -5872,7 +5680,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5904,7 +5711,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE1, .gpio = 0x00, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 59781755247a..9debfb549887 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1384,10 +1384,16 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i) if (card_in(dev, i->index).type == SAA7134_NO_INPUT) return -EINVAL; i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, saa7134_input_name[card_in(dev, n).type]); - if (card_in(dev, n).tv) + switch (card_in(dev, n).type) { + case SAA7134_INPUT_TV: + case SAA7134_INPUT_TV_MONO: i->type = V4L2_INPUT_TYPE_TUNER; + break; + default: + i->type = V4L2_INPUT_TYPE_CAMERA; + break; + } if (n == dev->ctl_input) { int v1 = saa_readb(SAA7134_STATUS_VIDEO1); int v2 = saa_readb(SAA7134_STATUS_VIDEO2); @@ -1656,7 +1662,8 @@ int saa7134_g_tuner(struct file *file, void *priv, return -EINVAL; memset(t, 0, sizeof(*t)); for (n = 0; n < SAA7134_INPUT_MAX; n++) { - if (card_in(dev, n).tv) + if (card_in(dev, n).type == SAA7134_INPUT_TV || + card_in(dev, n).type == SAA7134_INPUT_TV_MONO) break; } if (n == SAA7134_INPUT_MAX) diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 274a472e7d6b..e3e2392f87d6 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -384,7 +384,6 @@ struct saa7134_input { unsigned int vmux; enum saa7134_audio_in amux; unsigned int gpio; - unsigned int tv:1; }; enum saa7134_mpeg_type { -- cgit v1.2.3 From 7047f2982a223e0ecca480c11a37bd9edf62b65a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 13:16:18 -0200 Subject: [media] v4l2-mc: add an ancillary routine for PCI-based MC Instead of copyping the same code on all PCI devices that would have a media controller, add a core ancillary routine. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 35 +++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 24 +++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index e6d2a711bb0b..b6cf6dbd4cd5 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -15,9 +15,44 @@ */ #include +#include #include #include + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) +{ +#ifdef CONFIG_PCI + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &pci_dev->dev; + + if (name) + strlcpy(mdev->model, name, sizeof(mdev->model)); + else + strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); + + sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); + + mdev->hw_revision = pci_dev->subsystem_vendor << 16 + || pci_dev->subsystem_device; + + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); + int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index aed9e9b87f82..6fad97277a0b 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -92,6 +92,10 @@ enum demod_pad_index { DEMOD_NUM_PADS }; + +struct pci_dev; /* We don't need to include pci.h here */ + +#ifdef CONFIG_MEDIA_CONTROLLER /** * v4l2_mc_create_media_graph() - create Media Controller links at the graph. * @@ -106,11 +110,29 @@ enum demod_pad_index { * interface centric PC-consumer's hardware, V4L2 subdev centric camera * hardware should not use this routine, as it will not build the right graph. */ -#ifdef CONFIG_MEDIA_CONTROLLER int v4l2_mc_create_media_graph(struct media_device *mdev); + +/** + * v4l2_mc_pci_media_device_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @pci_dev: pointer to struct pci_dev + * @name: media device name. If %NULL, the routine will use the default + * name for the pci device, given by pci_name() macro. + */ +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name); + + #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { return 0; } + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) { + return NULL; +} + #endif -- cgit v1.2.3 From ac90aa02d5b9a9bde6bcd9ac3ee181a4d212d355 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 08:33:04 -0200 Subject: [media] saa7134: add media controller support Register saa7134 at the media controller core and provide support for both analog TV and DVB. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-core.c | 191 +++++++++++++++++++++++++++++- drivers/media/pci/saa7134/saa7134-dvb.c | 9 +- drivers/media/pci/saa7134/saa7134-video.c | 60 ++++++++++ drivers/media/pci/saa7134/saa7134.h | 13 ++ 4 files changed, 268 insertions(+), 5 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 31048f9b516a..42bc4172febd 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -806,6 +806,153 @@ static void must_configure_manually(int has_eeprom) } } +static void saa7134_unregister_media_device(struct saa7134_dev *dev) +{ + +#ifdef CONFIG_MEDIA_CONTROLLER + if (!dev->media_dev) + return; + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; +#endif +} + +static void saa7134_media_release(struct saa7134_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < SAA7134_INPUT_MAX + 1; i++) + media_device_unregister_entity(&dev->input_ent[i]); +#endif +} + +static void saa7134_create_entities(struct saa7134_dev *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret, i; + struct media_entity *entity; + struct media_entity *decoder = NULL; + + /* Check if it is using an external analog TV demod */ + media_device_for_each_entity(entity, dev->media_dev) { + if (entity->function == MEDIA_ENT_F_ATV_DECODER) + decoder = entity; + break; + } + + /* + * saa713x is not using an external ATV demod. + * Register the internal one + */ + if (!decoder) { + dev->demod.name = "saa713x"; + dev->demod_pad[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + dev->demod_pad[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod_pad[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod.function = MEDIA_ENT_F_ATV_DECODER; + + ret = media_entity_pads_init(&dev->demod, DEMOD_NUM_PADS, + dev->demod_pad); + if (ret < 0) + pr_err("failed to initialize demod pad!\n"); + + ret = media_device_register_entity(dev->media_dev, &dev->demod); + if (ret < 0) + pr_err("failed to register demod entity!\n"); + + dev->decoder = &dev->demod; + } else { + dev->decoder = decoder; + } + + /* Initialize Video, VBI and Radio pads */ + dev->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&dev->video_dev->entity, 1, + &dev->video_pad); + if (ret < 0) + pr_err("failed to initialize video media entity!\n"); + + dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&dev->vbi_dev->entity, 1, + &dev->vbi_pad); + if (ret < 0) + pr_err("failed to initialize vbi media entity!\n"); + + /* Create entities for each input connector */ + for (i = 0; i < SAA7134_INPUT_MAX; i++) { + struct media_entity *ent = &dev->input_ent[i]; + struct saa7134_input *in = &card_in(dev, i); + + if (in->type == SAA7134_NO_INPUT) + break; + + /* This input uses the S-Video connector */ + if (in->type == SAA7134_INPUT_COMPOSITE_OVER_SVIDEO) + continue; + + ent->name = saa7134_input_name[in->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (in->type) { + case SAA7134_INPUT_COMPOSITE: + case SAA7134_INPUT_COMPOSITE0: + case SAA7134_INPUT_COMPOSITE1: + case SAA7134_INPUT_COMPOSITE2: + case SAA7134_INPUT_COMPOSITE3: + case SAA7134_INPUT_COMPOSITE4: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case SAA7134_INPUT_SVIDEO: + case SAA7134_INPUT_SVIDEO0: + case SAA7134_INPUT_SVIDEO1: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + default: + /* + * SAA7134_INPUT_TV and SAA7134_INPUT_TV_MONO. + * + * Please notice that neither SAA7134_INPUT_MUTE or + * SAA7134_INPUT_RADIO are defined at + * saa7134_board.input. + */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } + + /* Create input for Radio RF connector */ + if (card_has_radio(dev)) { + struct saa7134_input *in = &saa7134_boards[dev->board].radio; + struct media_entity *ent = &dev->input_ent[i]; + + ent->name = saa7134_input_name[in->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + ent->function = MEDIA_ENT_F_CONN_RF; + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + static struct video_device *vdev_init(struct saa7134_dev *dev, struct video_device *template, char *type) @@ -826,6 +973,8 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, static void saa7134_unregister_video(struct saa7134_dev *dev) { + saa7134_media_release(dev); + if (dev->video_dev) { if (video_is_registered(dev->video_dev)) video_unregister_device(dev->video_dev); @@ -889,6 +1038,18 @@ static int saa7134_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + dev->nr = saa7134_devcount; + sprintf(dev->name, "saa%x[%d]", pci_dev->device, dev->nr); + +#ifdef CONFIG_MEDIA_CONTROLLER + dev->media_dev = v4l2_mc_pci_media_device_init(pci_dev, dev->name); + if (!dev->media_dev) { + err = -ENOMEM; + goto fail0; + } + dev->v4l2_dev.mdev = dev->media_dev; +#endif + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); if (err) goto fail0; @@ -900,9 +1061,6 @@ static int saa7134_initdev(struct pci_dev *pci_dev, goto fail1; } - dev->nr = saa7134_devcount; - sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr); - /* pci quirks */ if (pci_pci_problems) { if (pci_pci_problems & PCIPCI_TRITON) @@ -1102,6 +1260,15 @@ static int saa7134_initdev(struct pci_dev *pci_dev, dev->name, video_device_node_name(dev->radio_dev)); } +#ifdef CONFIG_MEDIA_CONTROLLER + saa7134_create_entities(dev); + + err = v4l2_mc_create_media_graph(dev->media_dev); + if (err) { + pr_err("failed to create media graph\n"); + goto fail5; + } +#endif /* everything worked */ saa7134_devcount++; @@ -1109,6 +1276,18 @@ static int saa7134_initdev(struct pci_dev *pci_dev, saa7134_dmasound_init(dev); request_submodules(dev); + + /* + * Do it at the end, to reduce dynamic configuration changes during + * the device init. Yet, as request_modules() can be async, the + * topology will likely change after load the saa7134 subdrivers. + */ +#ifdef CONFIG_MEDIA_CONTROLLER + err = media_device_register(dev->media_dev); + if (err) + goto fail5; +#endif + return 0; fail5: @@ -1126,6 +1305,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev, fail1: v4l2_device_unregister(&dev->v4l2_dev); fail0: +#ifdef CONFIG_MEDIA_CONTROLLER + kfree(dev->media_dev); +#endif kfree(dev); return err; } @@ -1188,9 +1370,10 @@ static void saa7134_finidev(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); - v4l2_device_unregister(&dev->v4l2_dev); + saa7134_unregister_media_device(dev); + /* free memory */ kfree(dev); } diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index ed84f7dea94c..db987e5b93eb 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1883,8 +1883,15 @@ static int dvb_init(struct saa7134_dev *dev) fe0->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ +#ifndef CONFIG_MEDIA_CONTROLLER_DVB ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, NULL, adapter_nr, 0); + &dev->pci->dev, NULL, + adapter_nr, 0); +#else + ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, dev->media_dev, + adapter_nr, 0); +#endif /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 9debfb549887..0403b34624c1 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -785,6 +785,63 @@ static int stop_preview(struct saa7134_dev *dev) return 0; } +/* + * Media Controller helper functions + */ + +static int saa7134_enable_analog_tuner(struct saa7134_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *source; + struct media_link *link, *found_link = NULL; + int ret, active_links = 0; + + if (!mdev || !dev->decoder) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + list_for_each_entry(link, &dev->decoder->links, list) { + if (link->sink->entity == dev->decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + list_for_each_entry(link, &source->links, list) { + struct media_entity *sink; + int flags = 0; + + sink = link->sink->entity; + + if (sink == dev->decoder) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + pr_err("Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } + } +#endif + return 0; +} + /* ------------------------------------------------------------------ */ static int buffer_activate(struct saa7134_dev *dev, @@ -924,6 +981,9 @@ static int queue_setup(struct vb2_queue *q, *nplanes = 1; sizes[0] = size; alloc_ctxs[0] = dev->alloc_ctx; + + saa7134_enable_analog_tuner(dev); + return 0; } diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index e3e2392f87d6..8936568fab94 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -671,6 +671,19 @@ struct saa7134_dev { /* I2C keyboard data */ struct IR_i2c_init_data init_data; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *media_dev; + + struct media_entity input_ent[SAA7134_INPUT_MAX + 1]; + struct media_pad input_pad[SAA7134_INPUT_MAX + 1]; + + struct media_entity demod; + struct media_pad demod_pad[DEMOD_NUM_PADS]; + + struct media_pad video_pad, vbi_pad; + struct media_entity *decoder; +#endif + #if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) /* SAA7134_MPEG_DVB only */ struct vb2_dvb_frontends frontends; -- cgit v1.2.3 From 82e92f4cad6e0c42f8dbe7497b39dec7b3eb7b11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Feb 2016 13:46:05 -0200 Subject: [media] au0828: only create V4L2 graph if V4L2 is registered It doesn't make sense to try to create the analog TV graph, if the device fails to register at V4L2, or if it doesn't have V4L2 support. Thanks to Shuah for pointing this issue. Reported-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index df2bc3f732b6..0a8afbf181c9 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -419,8 +419,21 @@ static int au0828_usb_probe(struct usb_interface *interface, #ifdef CONFIG_VIDEO_AU0828_V4L2 /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_register(dev, interface); + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { + retval = au0828_analog_register(dev, interface); + if (retval) { + pr_err("%s() au0282_dev_register failed to register on V4L2\n", + __func__); + goto done; + } + + retval = au0828_create_media_graph(dev); + if (retval) { + pr_err("%s() au0282_dev_register failed to create graph\n", + __func__); + goto done; + } + } #endif /* Digital TV */ @@ -443,13 +456,6 @@ static int au0828_usb_probe(struct usb_interface *interface, mutex_unlock(&dev->lock); - retval = au0828_create_media_graph(dev); - if (retval) { - pr_err("%s() au0282_dev_register failed to create graph\n", - __func__); - goto done; - } - #ifdef CONFIG_MEDIA_CONTROLLER retval = media_device_register(dev->media_dev); #endif -- cgit v1.2.3 From 7b606ffd65730bca6eaa45f74e0bdf70dbe8a854 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Feb 2016 15:53:39 -0200 Subject: [media] au0828: move V4L2-specific code to au0828-core.c Instead of having lots of #ifdefs inside au0828-core due to V4L2, move the dependencies to au0828-video.c. That allows removing all those ifdefs, as au0828-video is only compiled if CONFIG_VIDEO_AU0828_V4L2. This fixes the following warnings reported by Kbuild test with a random config with au0828 enabled, but V4L2 is disabled. All warnings (new ones prefixed by >>): drivers/media/usb/au0828/au0828-core.c: In function 'au0828_usb_probe': >> drivers/media/usb/au0828/au0828-core.c:463:1: warning: label 'done' defined but not used [-Wunused-label] done: ^ drivers/media/usb/au0828/au0828-core.c: At top level: drivers/media/usb/au0828/au0828-core.c:250:12: warning: 'au0828_create_media_graph' defined but not used [-Wunused-function] static int au0828_create_media_graph(struct au0828_dev *dev) ^ Tested with a WinTV HVR 950Q (USB ID: 2040:7200) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 157 ++----------------------------- drivers/media/usb/au0828/au0828-video.c | 162 +++++++++++++++++++++++++++++++- drivers/media/usb/au0828/au0828.h | 20 +++- 3 files changed, 187 insertions(+), 152 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 0a8afbf181c9..f23da7e7984b 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -143,7 +143,7 @@ static void au0828_unregister_media_device(struct au0828_dev *dev) #endif } -static void au0828_usb_release(struct au0828_dev *dev) +void au0828_usb_release(struct au0828_dev *dev) { au0828_unregister_media_device(dev); @@ -153,33 +153,6 @@ static void au0828_usb_release(struct au0828_dev *dev) kfree(dev); } -#ifdef CONFIG_VIDEO_AU0828_V4L2 - -static void au0828_usb_v4l2_media_release(struct au0828_dev *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - int i; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) - return; - media_device_unregister_entity(&dev->input_ent[i]); - } -#endif -} - -static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) -{ - struct au0828_dev *dev = - container_of(v4l2_dev, struct au0828_dev, v4l2_dev); - - v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); - v4l2_device_unregister(&dev->v4l2_dev); - au0828_usb_v4l2_media_release(dev); - au0828_usb_release(dev); -} -#endif - static void au0828_usb_disconnect(struct usb_interface *interface) { struct au0828_dev *dev = usb_get_intfdata(interface); @@ -202,18 +175,13 @@ static void au0828_usb_disconnect(struct usb_interface *interface) mutex_lock(&dev->mutex); dev->usbdev = NULL; mutex_unlock(&dev->mutex); -#ifdef CONFIG_VIDEO_AU0828_V4L2 - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - au0828_analog_unregister(dev); - v4l2_device_disconnect(&dev->v4l2_dev); - v4l2_device_put(&dev->v4l2_dev); + if (au0828_analog_unregister(dev)) { /* * No need to call au0828_usb_release() if V4L2 is enabled, * as this is already called via au0828_usb_v4l2_release() */ return; } -#endif au0828_usb_release(dev); } @@ -247,83 +215,6 @@ static int au0828_media_device_init(struct au0828_dev *dev, } -static int au0828_create_media_graph(struct au0828_dev *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct media_device *mdev = dev->media_dev; - struct media_entity *entity; - struct media_entity *tuner = NULL, *decoder = NULL; - int i, ret; - - if (!mdev) - return 0; - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_TUNER: - tuner = entity; - break; - case MEDIA_ENT_F_ATV_DECODER: - decoder = entity; - break; - } - } - - /* Analog setup, using tuner as a link */ - - /* Something bad happened! */ - if (!decoder) - return -EINVAL; - - if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - struct media_entity *ent = &dev->input_ent[i]; - - if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) - break; - - switch (AUVI_INPUT(i).type) { - case AU0828_VMUX_CABLE: - case AU0828_VMUX_TELEVISION: - case AU0828_VMUX_DVB: - if (!tuner) - break; - - ret = media_create_pad_link(ent, 0, tuner, - TUNER_PAD_RF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - break; - case AU0828_VMUX_COMPOSITE: - case AU0828_VMUX_SVIDEO: - default: /* AU0828_VMUX_DEBUG */ - /* FIXME: fix the decoder PAD */ - ret = media_create_pad_link(ent, 0, decoder, 0, 0); - if (ret) - return ret; - break; - } - } -#endif - return 0; -} - static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -378,32 +269,13 @@ static int au0828_usb_probe(struct usb_interface *interface, return retval; } -#ifdef CONFIG_VIDEO_AU0828_V4L2 - dev->v4l2_dev.release = au0828_usb_v4l2_release; - - /* Create the v4l2_device */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->v4l2_dev.mdev = dev->media_dev; -#endif - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); + retval = au0828_v4l2_device_register(interface, dev); if (retval) { - pr_err("%s() v4l2_device_register failed\n", - __func__); + au0828_usb_v4l2_media_release(dev); mutex_unlock(&dev->lock); kfree(dev); return retval; } - /* This control handler will inherit the controls from au8522 */ - retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); - if (retval) { - pr_err("%s() v4l2_ctrl_handler_init failed\n", - __func__); - mutex_unlock(&dev->lock); - kfree(dev); - return retval; - } - dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; -#endif /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -417,24 +289,13 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Setup */ au0828_card_setup(dev); -#ifdef CONFIG_VIDEO_AU0828_V4L2 /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - retval = au0828_analog_register(dev, interface); - if (retval) { - pr_err("%s() au0282_dev_register failed to register on V4L2\n", - __func__); - goto done; - } - - retval = au0828_create_media_graph(dev); - if (retval) { - pr_err("%s() au0282_dev_register failed to create graph\n", - __func__); - goto done; - } + retval = au0828_analog_register(dev, interface); + if (retval) { + pr_err("%s() au0282_dev_register failed to register on V4L2\n", + __func__); + goto done; } -#endif /* Digital TV */ retval = au0828_dvb_register(dev); diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 8c54fd21022e..4164302dd8ac 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -638,6 +638,144 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) return rc; } +void au0828_usb_v4l2_media_release(struct au0828_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) + return; + media_device_unregister_entity(&dev->input_ent[i]); + } +#endif +} + +static int au0828_create_media_graph(struct au0828_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *tuner = NULL, *decoder = NULL; + int i, ret; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + /* Something bad happened! */ + if (!decoder) + return -EINVAL; + + if (tuner) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) + break; + + switch (AUVI_INPUT(i).type) { + case AU0828_VMUX_CABLE: + case AU0828_VMUX_TELEVISION: + case AU0828_VMUX_DVB: + if (!tuner) + break; + + ret = media_create_pad_link(ent, 0, tuner, + TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + break; + case AU0828_VMUX_COMPOSITE: + case AU0828_VMUX_SVIDEO: + default: /* AU0828_VMUX_DEBUG */ + /* FIXME: fix the decoder PAD */ + ret = media_create_pad_link(ent, 0, decoder, 0, 0); + if (ret) + return ret; + break; + } + } +#endif + return 0; +} + +static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) +{ + struct au0828_dev *dev = + container_of(v4l2_dev, struct au0828_dev, v4l2_dev); + + v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); + v4l2_device_unregister(&dev->v4l2_dev); + au0828_usb_v4l2_media_release(dev); + au0828_usb_release(dev); +} + +int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev) +{ + int retval; + + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + + /* Create the v4l2_device */ +#ifdef CONFIG_MEDIA_CONTROLLER + dev->v4l2_dev.mdev = dev->media_dev; +#endif + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); + if (retval) { + pr_err("%s() v4l2_device_register failed\n", + __func__); + mutex_unlock(&dev->lock); + kfree(dev); + return retval; + } + + dev->v4l2_dev.release = au0828_usb_v4l2_release; + + /* This control handler will inherit the controls from au8522 */ + retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); + if (retval) { + pr_err("%s() v4l2_ctrl_handler_init failed\n", + __func__); + mutex_unlock(&dev->lock); + kfree(dev); + return retval; + } + dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; + + return 0; +} + static int au0828_enable_analog_tuner(struct au0828_dev *dev) { #ifdef CONFIG_MEDIA_CONTROLLER @@ -949,13 +1087,23 @@ static struct vb2_ops au0828_video_qops = { * au0828_analog_unregister * unregister v4l2 devices */ -void au0828_analog_unregister(struct au0828_dev *dev) +int au0828_analog_unregister(struct au0828_dev *dev) { dprintk(1, "au0828_analog_unregister called\n"); + + /* No analog TV */ + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + mutex_lock(&au0828_sysfs_lock); video_unregister_device(&dev->vdev); video_unregister_device(&dev->vbi_dev); mutex_unlock(&au0828_sysfs_lock); + + v4l2_device_disconnect(&dev->v4l2_dev); + v4l2_device_put(&dev->v4l2_dev); + + return 1; } /* This function ensures that video frames continue to be delivered even if @@ -1871,6 +2019,10 @@ int au0828_analog_register(struct au0828_dev *dev, dprintk(1, "au0828_analog_register called for intf#%d!\n", interface->cur_altsetting->desc.bInterfaceNumber); + /* No analog TV */ + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + /* set au0828 usb interface0 to as5 */ retval = usb_set_interface(dev->usbdev, interface->cur_altsetting->desc.bInterfaceNumber, 5); @@ -1976,6 +2128,14 @@ int au0828_analog_register(struct au0828_dev *dev, ret = -ENODEV; goto err_reg_vbi_dev; } + retval = au0828_create_media_graph(dev); + if (retval) { + pr_err("%s() au0282_dev_register failed to create graph\n", + __func__); + ret = -ENODEV; + goto err_reg_vbi_dev; + } + dprintk(1, "%s completed!\n", __func__); diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 8276072bc55a..19fd6a841988 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -301,6 +301,7 @@ struct au0828_dev { /* au0828-core.c */ extern u32 au0828_read(struct au0828_dev *dev, u16 reg); extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); +extern void au0828_usb_release(struct au0828_dev *dev); extern int au0828_debug; /* ----------------------------------------------------------- */ @@ -319,16 +320,29 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev); /* ----------------------------------------------------------- */ /* au0828-video.c */ -extern int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface); -extern void au0828_analog_unregister(struct au0828_dev *dev); extern int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count); extern void au0828_stop_vbi_streaming(struct vb2_queue *vq); #ifdef CONFIG_VIDEO_AU0828_V4L2 +extern int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev); + +extern int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface); +extern int au0828_analog_unregister(struct au0828_dev *dev); +extern void au0828_usb_v4l2_media_release(struct au0828_dev *dev); extern void au0828_v4l2_suspend(struct au0828_dev *dev); extern void au0828_v4l2_resume(struct au0828_dev *dev); #else +static inline int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev) +{ return 0; }; +static inline int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface) +{ return 0; }; +static inline int au0828_analog_unregister(struct au0828_dev *dev) +{ return 0; }; +static inline void au0828_usb_v4l2_media_release(struct au0828_dev *dev) { }; static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { }; static inline void au0828_v4l2_resume(struct au0828_dev *dev) { }; #endif -- cgit v1.2.3 From 4f388a9210e2a2c1cd83a5580b74aa13876dbf14 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 5 Feb 2016 11:52:00 -0200 Subject: [media] media: davinci_vpfe: fix missing unlock on error in vpfe_prepare_pipeline() Add the missing unlock before return from function vpfe_prepare_pipeline() in the error handling case. video->lock is lock/unlock in function vpfe_open(), and no need to unlock it here, so remove unlock video->lock. Signed-off-by: Wei Yongjun Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 3ec7e65a3ffa..db49af90217e 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -147,7 +147,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) mutex_lock(&mdev->graph_mutex); ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); if (ret) { - mutex_unlock(&video->lock); + mutex_unlock(&mdev->graph_mutex); return -ENOMEM; } media_entity_graph_walk_start(&graph, entity); -- cgit v1.2.3 From b888d232142c0ac111c7e82d1731c6fbd56fc1fe Mon Sep 17 00:00:00 2001 From: Anton Protopopov Date: Sun, 7 Feb 2016 02:27:32 -0200 Subject: [media] media: i2c/adp1653: probe: fix erroneous return value The adp1653_probe() function may return positive value EINVAL which is obviously wrong. Signed-off-by: Anton Protopopov Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adp1653.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index 7e9cbf757e95..fb7ed730d932 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -497,7 +497,7 @@ static int adp1653_probe(struct i2c_client *client, if (!client->dev.platform_data) { dev_err(&client->dev, "Neither DT not platform data provided\n"); - return EINVAL; + return -EINVAL; } flash->platform_data = client->dev.platform_data; } -- cgit v1.2.3 From e295b3d603fb02aaf602e5edc846647688df8301 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Jan 2016 09:12:48 -0200 Subject: [media] V4L: ov9650: fix control clusters Auto-gain and auto-exposure clusters in the ov9650 driver have both a size of 2, not 3 controls. Fix this. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov9650.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index a0b3c9bde53d..be5a7fd4f076 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1046,8 +1046,8 @@ static int ov965x_initialize_controls(struct ov965x *ov965x) ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false); - v4l2_ctrl_auto_cluster(3, &ctrls->auto_gain, 0, true); - v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 1, true); + v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true); + v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true); v4l2_ctrl_cluster(2, &ctrls->hflip); ov965x->sd.ctrl_handler = hdl; -- cgit v1.2.3 From b292394d4f1909ecad42150bf8782c3000d101b7 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 26 Jan 2016 16:39:14 -0200 Subject: [media] media: platform: vivid: vivid-osd: Remove unnecessary cast to kfree Remove an unnecassary cast in the argument to kfree. Found using Coccinelle. The semantic patch used to find this is as follows: // @@ type T; expression *f; @@ - kfree((T *)(f)); + kfree(f); // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-osd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c index e15eef6a94e5..bdc380b14e0c 100644 --- a/drivers/media/platform/vivid/vivid-osd.c +++ b/drivers/media/platform/vivid/vivid-osd.c @@ -360,7 +360,7 @@ void vivid_fb_release_buffers(struct vivid_dev *dev) /* Release pseudo palette */ kfree(dev->fb_info.pseudo_palette); - kfree((void *)dev->video_vbase); + kfree(dev->video_vbase); } /* Initialize the specified card */ -- cgit v1.2.3 From bd3e275f3ec095eccc3b3c655b83e1b577848f92 Mon Sep 17 00:00:00 2001 From: Jean-Michel Hautbois Date: Wed, 27 Jan 2016 09:04:50 -0200 Subject: [media] media: i2c: adv7604: Use v4l2-dv-timings helpers Use the helper to enumerate and set DV timings instead of a custom code. This will ease debugging too, as it is consistent with other drivers. Signed-off-by: Jean-Michel Hautbois Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 178 ++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 113 deletions(-) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 801a9b09d5e5..e427cacde527 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -207,71 +207,22 @@ static bool adv76xx_has_afe(struct adv76xx_state *state) return state->info->has_afe; } -/* Supported CEA and DMT timings */ -static const struct v4l2_dv_timings adv76xx_timings[] = { - V4L2_DV_BT_CEA_720X480P59_94, - V4L2_DV_BT_CEA_720X576P50, - V4L2_DV_BT_CEA_1280X720P24, - V4L2_DV_BT_CEA_1280X720P25, - V4L2_DV_BT_CEA_1280X720P50, - V4L2_DV_BT_CEA_1280X720P60, - V4L2_DV_BT_CEA_1920X1080P24, - V4L2_DV_BT_CEA_1920X1080P25, - V4L2_DV_BT_CEA_1920X1080P30, - V4L2_DV_BT_CEA_1920X1080P50, - V4L2_DV_BT_CEA_1920X1080P60, - - /* sorted by DMT ID */ - V4L2_DV_BT_DMT_640X350P85, - V4L2_DV_BT_DMT_640X400P85, - V4L2_DV_BT_DMT_720X400P85, - V4L2_DV_BT_DMT_640X480P60, - V4L2_DV_BT_DMT_640X480P72, - V4L2_DV_BT_DMT_640X480P75, - V4L2_DV_BT_DMT_640X480P85, - V4L2_DV_BT_DMT_800X600P56, - V4L2_DV_BT_DMT_800X600P60, - V4L2_DV_BT_DMT_800X600P72, - V4L2_DV_BT_DMT_800X600P75, - V4L2_DV_BT_DMT_800X600P85, - V4L2_DV_BT_DMT_848X480P60, - V4L2_DV_BT_DMT_1024X768P60, - V4L2_DV_BT_DMT_1024X768P70, - V4L2_DV_BT_DMT_1024X768P75, - V4L2_DV_BT_DMT_1024X768P85, - V4L2_DV_BT_DMT_1152X864P75, - V4L2_DV_BT_DMT_1280X768P60_RB, - V4L2_DV_BT_DMT_1280X768P60, - V4L2_DV_BT_DMT_1280X768P75, - V4L2_DV_BT_DMT_1280X768P85, - V4L2_DV_BT_DMT_1280X800P60_RB, - V4L2_DV_BT_DMT_1280X800P60, - V4L2_DV_BT_DMT_1280X800P75, - V4L2_DV_BT_DMT_1280X800P85, - V4L2_DV_BT_DMT_1280X960P60, - V4L2_DV_BT_DMT_1280X960P85, - V4L2_DV_BT_DMT_1280X1024P60, - V4L2_DV_BT_DMT_1280X1024P75, - V4L2_DV_BT_DMT_1280X1024P85, - V4L2_DV_BT_DMT_1360X768P60, - V4L2_DV_BT_DMT_1400X1050P60_RB, - V4L2_DV_BT_DMT_1400X1050P60, - V4L2_DV_BT_DMT_1400X1050P75, - V4L2_DV_BT_DMT_1400X1050P85, - V4L2_DV_BT_DMT_1440X900P60_RB, - V4L2_DV_BT_DMT_1440X900P60, - V4L2_DV_BT_DMT_1600X1200P60, - V4L2_DV_BT_DMT_1680X1050P60_RB, - V4L2_DV_BT_DMT_1680X1050P60, - V4L2_DV_BT_DMT_1792X1344P60, - V4L2_DV_BT_DMT_1856X1392P60, - V4L2_DV_BT_DMT_1920X1200P60_RB, - V4L2_DV_BT_DMT_1366X768P60_RB, - V4L2_DV_BT_DMT_1366X768P60, - V4L2_DV_BT_DMT_1920X1080P60, - { }, +/* Unsupported timings. This device cannot support 720p30. */ +static const struct v4l2_dv_timings adv76xx_timings_exceptions[] = { + V4L2_DV_BT_CEA_1280X720P30, + { } }; +static bool adv76xx_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl) +{ + int i; + + for (i = 0; adv76xx_timings_exceptions[i].bt.width; i++) + if (v4l2_match_dv_timings(t, adv76xx_timings_exceptions + i, 0, false)) + return false; + return true; +} + struct adv76xx_video_standards { struct v4l2_dv_timings timings; u8 vid_std; @@ -806,6 +757,36 @@ static inline bool is_digital_input(struct v4l2_subdev *sd) state->selected_input == ADV7604_PAD_HDMI_PORT_D; } +static const struct v4l2_dv_timings_cap adv7604_timings_cap_analog = { + .type = V4L2_DV_BT_656_1120, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) +}; + +static const struct v4l2_dv_timings_cap adv76xx_timings_cap_digital = { + .type = V4L2_DV_BT_656_1120, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) +}; + +static inline const struct v4l2_dv_timings_cap * +adv76xx_get_dv_timings_cap(struct v4l2_subdev *sd) +{ + return is_digital_input(sd) ? &adv76xx_timings_cap_digital : + &adv7604_timings_cap_analog; +} + + /* ----------------------------------------------------------------------- */ #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1330,17 +1311,23 @@ static int stdi2dv_timings(struct v4l2_subdev *sd, u32 pix_clk; int i; - for (i = 0; adv76xx_timings[i].bt.height; i++) { - if (vtotal(&adv76xx_timings[i].bt) != stdi->lcf + 1) + for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { + const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; + + if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], + adv76xx_get_dv_timings_cap(sd), + adv76xx_check_dv_timings, NULL)) + continue; + if (vtotal(bt) != stdi->lcf + 1) continue; - if (adv76xx_timings[i].bt.vsync != stdi->lcvs) + if (bt->vsync != stdi->lcvs) continue; - pix_clk = hfreq * htotal(&adv76xx_timings[i].bt); + pix_clk = hfreq * htotal(bt); - if ((pix_clk < adv76xx_timings[i].bt.pixelclock + 1000000) && - (pix_clk > adv76xx_timings[i].bt.pixelclock - 1000000)) { - *timings = adv76xx_timings[i]; + if ((pix_clk < bt->pixelclock + 1000000) && + (pix_clk > bt->pixelclock - 1000000)) { + *timings = v4l2_dv_timings_presets[i]; return 0; } } @@ -1425,15 +1412,11 @@ static int adv76xx_enum_dv_timings(struct v4l2_subdev *sd, { struct adv76xx_state *state = to_state(sd); - if (timings->index >= ARRAY_SIZE(adv76xx_timings) - 1) - return -EINVAL; - if (timings->pad >= state->source_pad) return -EINVAL; - memset(timings->reserved, 0, sizeof(timings->reserved)); - timings->timings = adv76xx_timings[timings->index]; - return 0; + return v4l2_enum_dv_timings_cap(timings, + adv76xx_get_dv_timings_cap(sd), adv76xx_check_dv_timings, NULL); } static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, @@ -1444,29 +1427,7 @@ static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, if (cap->pad >= state->source_pad) return -EINVAL; - cap->type = V4L2_DV_BT_656_1120; - cap->bt.max_width = 1920; - cap->bt.max_height = 1200; - cap->bt.min_pixelclock = 25000000; - - switch (cap->pad) { - case ADV76XX_PAD_HDMI_PORT_A: - case ADV7604_PAD_HDMI_PORT_B: - case ADV7604_PAD_HDMI_PORT_C: - case ADV7604_PAD_HDMI_PORT_D: - cap->bt.max_pixelclock = 225000000; - break; - case ADV7604_PAD_VGA_RGB: - case ADV7604_PAD_VGA_COMP: - default: - cap->bt.max_pixelclock = 170000000; - break; - } - - cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | - V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; - cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; + *cap = *adv76xx_get_dv_timings_cap(sd); return 0; } @@ -1475,15 +1436,9 @@ static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, struct v4l2_dv_timings *timings) { - int i; - - for (i = 0; adv76xx_timings[i].bt.width; i++) { - if (v4l2_match_dv_timings(timings, &adv76xx_timings[i], - is_digital_input(sd) ? 250000 : 1000000, false)) { - *timings = adv76xx_timings[i]; - break; - } - } + v4l2_find_dv_timings_cap(timings, adv76xx_get_dv_timings_cap(sd), + is_digital_input(sd) ? 250000 : 1000000, + adv76xx_check_dv_timings, NULL); } static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd) @@ -1651,12 +1606,9 @@ static int adv76xx_s_dv_timings(struct v4l2_subdev *sd, bt = &timings->bt; - if ((is_analog_input(sd) && bt->pixelclock > 170000000) || - (is_digital_input(sd) && bt->pixelclock > 225000000)) { - v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n", - __func__, (u32)bt->pixelclock); + if (!v4l2_valid_dv_timings(timings, adv76xx_get_dv_timings_cap(sd), + adv76xx_check_dv_timings, NULL)) return -ERANGE; - } adv76xx_fill_optional_dv_timings_fields(sd, timings); -- cgit v1.2.3 From 45cc29afb47f229014257068a3153276b2fb4c38 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:39 -0200 Subject: [media] v4l2-ctrls: add V4L2_CID_DV_RX/TX_IT_CONTENT_TYPE controls HDMI and DisplayPort both support IT Content Type information that tells the receiver what type of material the video is, graphics such as from a PC desktop, Photo, Cinema or Game (low-latency). This patch adds controls for receivers and transmitters to get/set this information. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 16 ++++++++++++++++ include/uapi/linux/v4l2-controls.h | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index c9d5537b6af7..bed04b1fdd0a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -462,6 +462,14 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "RGB full range (0-255)", NULL, }; + static const char * const dv_it_content_type[] = { + "Graphics", + "Photo", + "Cinema", + "Game", + "No IT Content", + NULL, + }; static const char * const detect_md_mode[] = { "Disabled", "Global", @@ -560,6 +568,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: return dv_rgb_range; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: + return dv_it_content_type; case V4L2_CID_DETECT_MD_MODE: return detect_md_mode; @@ -881,8 +892,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_TX_EDID_PRESENT: return "EDID Present"; case V4L2_CID_DV_TX_MODE: return "Transmit Mode"; case V4L2_CID_DV_TX_RGB_RANGE: return "Tx RGB Quantization Range"; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: return "Tx IT Content Type"; case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: return "Rx IT Content Type"; case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; @@ -1038,7 +1051,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_SCENE_MODE: case V4L2_CID_DV_TX_MODE: case V4L2_CID_DV_TX_RGB_RANGE: + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: case V4L2_CID_DV_RX_RGB_RANGE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_TEST_PATTERN: case V4L2_CID_TUNE_DEEMPHASIS: case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: @@ -1185,6 +1200,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RXSENSE: case V4L2_CID_DV_TX_EDID_PRESENT: case V4L2_CID_DV_RX_POWER_PRESENT: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_RDS_RX_PTY: case V4L2_CID_RDS_RX_PS_NAME: case V4L2_CID_RDS_RX_RADIO_TEXT: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 2d225bcdb831..2ae5c3ea179b 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -912,8 +912,18 @@ enum v4l2_dv_rgb_range { V4L2_DV_RGB_RANGE_FULL = 2, }; +#define V4L2_CID_DV_TX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 6) +enum v4l2_dv_it_content_type { + V4L2_DV_IT_CONTENT_TYPE_GRAPHICS = 0, + V4L2_DV_IT_CONTENT_TYPE_PHOTO = 1, + V4L2_DV_IT_CONTENT_TYPE_CINEMA = 2, + V4L2_DV_IT_CONTENT_TYPE_GAME = 3, + V4L2_DV_IT_CONTENT_TYPE_NO_ITC = 4, +}; + #define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_DV_RX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 102) #define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) #define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) -- cgit v1.2.3 From ed679b8a19bea7b1d64c49c0e369b65b2dfce135 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:40 -0200 Subject: [media] DocBook media: document the new V4L2_CID_DV_RX/TX_IT_CONTENT_TYPE controls Document these new controls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/controls.xml | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index f13a429093f1..7a771492f2a5 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -5069,6 +5069,46 @@ interface and may change in the future. This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors. + + V4L2_CID_DV_TX_IT_CONTENT_TYPE + enum v4l2_dv_it_content_type + + Configures the IT Content Type + of the transmitted video. This information is sent over HDMI and DisplayPort connectors + as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates + from a computer as opposed to content from a TV broadcast or an analog source. The + enum v4l2_dv_it_content_type defines the possible content types: + + + + + + V4L2_DV_IT_CONTENT_TYPE_GRAPHICS  + Graphics content. Pixel data should be passed unfiltered and without + analog reconstruction. + + + V4L2_DV_IT_CONTENT_TYPE_PHOTO  + Photo content. The content is derived from digital still pictures. + The content should be passed through with minimal scaling and picture + enhancements. + + + V4L2_DV_IT_CONTENT_TYPE_CINEMA  + Cinema content. + + + V4L2_DV_IT_CONTENT_TYPE_GAME  + Game content. Audio and video latency should be minimized. + + + V4L2_DV_IT_CONTENT_TYPE_NO_ITC  + No IT Content information is available and the ITC bit in the AVI + InfoFrame is set to 0. + + + + V4L2_CID_DV_RX_POWER_PRESENT bitmask @@ -5098,6 +5138,16 @@ interface and may change in the future. This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors. + + V4L2_CID_DV_RX_IT_CONTENT_TYPE + enum v4l2_dv_it_content_type + + Reads the IT Content Type + of the received video. This information is sent over HDMI and DisplayPort connectors + as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates + from a computer as opposed to content from a TV broadcast or an analog source. See + V4L2_CID_DV_TX_IT_CONTENT_TYPE for the available content types. + -- cgit v1.2.3 From 297a41448a006def6b87aef5383837c3130a41e4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:41 -0200 Subject: [media] adv7604: add support to for the content type control This receiver now supports reading the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index e427cacde527..d35e0ba8b269 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1197,6 +1197,20 @@ static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } +static int adv76xx_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = + &container_of(ctrl->handler, struct adv76xx_state, hdl)->sd; + + if (ctrl->id == V4L2_CID_DV_RX_IT_CONTENT_TYPE) { + ctrl->val = V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + if ((io_read(sd, 0x60) & 1) && (infoframe_read(sd, 0x03) & 0x80)) + ctrl->val = (infoframe_read(sd, 0x05) >> 4) & 3; + return 0; + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ static inline bool no_power(struct v4l2_subdev *sd) @@ -2353,6 +2367,7 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd, static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = { .s_ctrl = adv76xx_s_ctrl, + .g_volatile_ctrl = adv76xx_g_volatile_ctrl, }; static const struct v4l2_subdev_core_ops adv76xx_core_ops = { @@ -2988,6 +3003,7 @@ static int adv76xx_probe(struct i2c_client *client, V4L2_DV_BT_CEA_640X480P59_94; struct adv76xx_state *state; struct v4l2_ctrl_handler *hdl; + struct v4l2_ctrl *ctrl; struct v4l2_subdev *sd; unsigned int i; unsigned int val, val2; @@ -3119,6 +3135,11 @@ static int adv76xx_probe(struct i2c_client *client, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops, V4L2_CID_HUE, 0, 128, 1, 0); + ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops, + V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, -- cgit v1.2.3 From e89792740d769cd30cc296289b00fb9ff7a762e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:42 -0200 Subject: [media] adv7842: add support to for the content type control This receiver now supports reading the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7842.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 5fbb788e7b59..7ccb85d45224 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -1359,6 +1359,19 @@ static int adv7842_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } +static int adv7842_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + + if (ctrl->id == V4L2_CID_DV_RX_IT_CONTENT_TYPE) { + ctrl->val = V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + if ((io_read(sd, 0x60) & 1) && (infoframe_read(sd, 0x03) & 0x80)) + ctrl->val = (infoframe_read(sd, 0x05) >> 4) & 3; + return 0; + } + return -EINVAL; +} + static inline bool no_power(struct v4l2_subdev *sd) { return io_read(sd, 0x0c) & 0x24; @@ -3022,6 +3035,7 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd, static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { .s_ctrl = adv7842_s_ctrl, + .g_volatile_ctrl = adv7842_g_volatile_ctrl, }; static const struct v4l2_subdev_core_ops adv7842_core_ops = { @@ -3196,6 +3210,7 @@ static int adv7842_probe(struct i2c_client *client, V4L2_DV_BT_CEA_640X480P59_94; struct adv7842_platform_data *pdata = client->dev.platform_data; struct v4l2_ctrl_handler *hdl; + struct v4l2_ctrl *ctrl; struct v4l2_subdev *sd; u16 rev; int err; @@ -3261,6 +3276,11 @@ static int adv7842_probe(struct i2c_client *client, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, V4L2_CID_HUE, 0, 128, 1, 0); + ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7842_ctrl_ops, + V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; /* custom controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, -- cgit v1.2.3 From df0e57754e29493bf9c53333ece7df172dd18a10 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:43 -0200 Subject: [media] adv7511: add support to for the content type control This transmitter now supports configuring the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 471fd23b5c5c..a9ed5337df2d 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -103,12 +103,14 @@ struct adv7511_state { u32 ycbcr_enc; u32 quantization; u32 xfer_func; + u32 content_type; /* controls */ struct v4l2_ctrl *hdmi_mode_ctrl; struct v4l2_ctrl *hotplug_ctrl; struct v4l2_ctrl *rx_sense_ctrl; struct v4l2_ctrl *have_edid0_ctrl; struct v4l2_ctrl *rgb_quantization_range_ctrl; + struct v4l2_ctrl *content_type_ctrl; struct i2c_client *i2c_edid; struct i2c_client *i2c_pktmem; struct adv7511_state_edid edid; @@ -400,6 +402,16 @@ static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) } if (state->rgb_quantization_range_ctrl == ctrl) return adv7511_set_rgb_quantization_mode(sd, ctrl); + if (state->content_type_ctrl == ctrl) { + u8 itc, cn; + + state->content_type = ctrl->val; + itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; + adv7511_wr_and_or(sd, 0x57, 0x7f, itc << 7); + adv7511_wr_and_or(sd, 0x59, 0xcf, cn << 4); + return 0; + } return -EINVAL; } @@ -1002,6 +1014,8 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, u8 y = HDMI_COLORSPACE_RGB; u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT; u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; + u8 itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + u8 cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; if (format->pad != 0) return -EINVAL; @@ -1115,8 +1129,8 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, adv7511_wr_and_or(sd, 0x4a, 0xbf, 0); adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5); adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6); - adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2)); - adv7511_wr_and_or(sd, 0x59, 0x3f, yq << 6); + adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2) | (itc << 7)); + adv7511_wr_and_or(sd, 0x59, 0x0f, (yq << 6) | (cn << 4)); adv7511_wr_and_or(sd, 0x4a, 0xff, 1); return 0; @@ -1470,6 +1484,10 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, 0, V4L2_DV_RGB_RANGE_AUTO); + state->content_type_ctrl = + v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, + V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); sd->ctrl_handler = hdl; if (hdl->error) { err = hdl->error; -- cgit v1.2.3 From 8ddc2dd0832e062bbb36e965e5a202a7d0b584a0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 3 Nov 2015 21:50:23 -0200 Subject: [media] v4l2-ctrls: remove unclaimed v4l2_ctrl_add_ctrl() interface v4l2_ctrl_add_ctrl() interface has no users since its introduction in commit 0996517cf8ea ("V4L/DVB: v4l2: Add new control handling framework") and its functionality is covered by v4l2_ctrl_new() and derivative interfaces, so it is safe to remove the interface from the kernel. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-controls.txt | 1 - drivers/media/v4l2-core/v4l2-ctrls.c | 16 ---------------- include/media/v4l2-ctrls.h | 12 ------------ 3 files changed, 29 deletions(-) diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt index 5517db602f37..5e759cab4538 100644 --- a/Documentation/video4linux/v4l2-controls.txt +++ b/Documentation/video4linux/v4l2-controls.txt @@ -647,7 +647,6 @@ Or you can add specific controls to a handler: volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); - v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume); What you should not do is make two identical controls for two handlers. For example: diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index bed04b1fdd0a..130e5badd599 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2227,22 +2227,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, } EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); -/* Add a control from another handler to this handler */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl) -{ - if (hdl == NULL || hdl->error) - return NULL; - if (ctrl == NULL) { - handler_set_err(hdl, -EINVAL); - return NULL; - } - if (ctrl->handler == hdl) - return ctrl; - return handler_new_ref(hdl, ctrl) ? NULL : ctrl; -} -EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); - /* Add the controls from another handler to our own. */ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *add, diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index da6fe9802fee..0bc9b35b8f3e 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -534,18 +534,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u8 def, const s64 *qmenu_int); -/** - * v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler. - * @hdl: The control handler. - * @ctrl: The control to add. - * - * It will return NULL if it was unable to add the control reference. - * If the control already belonged to the handler, then it will do - * nothing and just return @ctrl. - */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl); - /** * v4l2_ctrl_add_handler() - Add all controls from handler @add to * handler @hdl. -- cgit v1.2.3 From 0e2a706b04c1d117c77ee47a41fd978afa25d67e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Dec 2015 18:32:00 -0200 Subject: [media] tea575x: convert to library The module is used only as a library for now. Remove module init and exit routines to show this. While here, remove FSF snail address and attach EXPORT_SYMBOL() macros to corresponding functions. Signed-off-by: Andy Shevchenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/tea575x.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index 3e08475af579..4dc2067bce14 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -14,10 +14,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include @@ -226,6 +222,7 @@ void snd_tea575x_set_freq(struct snd_tea575x *tea) snd_tea575x_write(tea, tea->val); tea->freq = snd_tea575x_val_to_freq(tea, tea->val); } +EXPORT_SYMBOL(snd_tea575x_set_freq); /* * Linux Video interface @@ -582,25 +579,11 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) return 0; } +EXPORT_SYMBOL(snd_tea575x_init); void snd_tea575x_exit(struct snd_tea575x *tea) { video_unregister_device(&tea->vd); v4l2_ctrl_handler_free(tea->vd.ctrl_handler); } - -static int __init alsa_tea575x_module_init(void) -{ - return 0; -} - -static void __exit alsa_tea575x_module_exit(void) -{ -} - -module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit) - -EXPORT_SYMBOL(snd_tea575x_init); EXPORT_SYMBOL(snd_tea575x_exit); -EXPORT_SYMBOL(snd_tea575x_set_freq); -- cgit v1.2.3 From 798bd945f0606dfe615142e1157e8ab5c7d29e2b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:51 -0200 Subject: [media] v4l2-subdev: add registered_async subdev core operation V4L2 sub-devices that are registered asynchronously have no way to know when they have been registration with a V4L2 device but they might need to take some action after this. So let's add a callback that can be executed by the V4L2 async core to allow sub-devices drivers to do any needed initialization that depends on the registration. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b273cf9ac047..11e2dfec0198 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -179,6 +179,8 @@ struct v4l2_subdev_io_pin_config { * for it to be warned when the value of a control changes. * * @unsubscribe_event: remove event subscription from the control framework. + * + * @registered_async: the subdevice has been registered async. */ struct v4l2_subdev_core_ops { int (*log_status)(struct v4l2_subdev *sd); @@ -211,6 +213,7 @@ struct v4l2_subdev_core_ops { struct v4l2_event_subscription *sub); int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub); + int (*registered_async)(struct v4l2_subdev *sd); }; /** -- cgit v1.2.3 From 7c3e1ec1f772c1f740fce3180bf419018582977f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:52 -0200 Subject: [media] v4l2-async: call registered_async after subdev registration V4L2 sub-devices might need to do initialization that depends on being registered with a V4L2 device. As an example, sub-devices with Media Controller support may need to register entities and create pad links. Execute the registered_async callback after the sub-device has been registered with the V4L2 device so the driver can do any needed init. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 5bada202b2d3..716bfd47daab 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -119,6 +119,13 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, return ret; } + ret = v4l2_subdev_call(sd, core, registered_async); + if (ret < 0) { + if (notifier->unbind) + notifier->unbind(notifier, sd, asd); + return ret; + } + if (list_empty(¬ifier->waiting) && notifier->complete) return notifier->complete(notifier); -- cgit v1.2.3 From 2bd5e4375aec8731c9818b2ac86ac035d3aebe86 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:53 -0200 Subject: [media] tvp5150: put endpoint node on error If the parallel mbus configuration is not correct, the endpoint device node isn't currently put again in the error path. Fix it. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 19b52736b24e..c7eeb59a999b 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1268,8 +1268,10 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && - flags & V4L2_MBUS_FIELD_EVEN_LOW)) - return -EINVAL; + flags & V4L2_MBUS_FIELD_EVEN_LOW)) { + ret = -EINVAL; + goto err; + } decoder->mbus_type = bus_cfg.bus_type; -- cgit v1.2.3 From 82275133cc52e201e44de08a9471357fa2823b0c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:54 -0200 Subject: [media] tvp5150: store dev id and rom version Not all tvp5150 variants support the same, for example some have an internal signal generator that can output a black screen. So the device id and rom version have to be stored in the driver's state to know what variant is a given device. While being there, remove some redundant comments about the device version since there is already calls to v4l2_info() with that info. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index c7eeb59a999b..093ff80f944c 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -49,6 +49,9 @@ struct tvp5150 { u32 output; int enable; + u16 dev_id; + u16 rom_ver; + enum v4l2_mbus_type mbus_type; }; @@ -1180,8 +1183,6 @@ static int tvp5150_detect_version(struct tvp5150 *core) struct v4l2_subdev *sd = &core->sd; struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned int i; - u16 dev_id; - u16 rom_ver; u8 regs[4]; int res; @@ -1196,23 +1197,25 @@ static int tvp5150_detect_version(struct tvp5150 *core) regs[i] = res; } - dev_id = (regs[0] << 8) | regs[1]; - rom_ver = (regs[2] << 8) | regs[3]; + core->dev_id = (regs[0] << 8) | regs[1]; + core->rom_ver = (regs[2] << 8) | regs[3]; v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n", - dev_id, regs[2], regs[3], c->addr << 1, c->adapter->name); + core->dev_id, regs[2], regs[3], c->addr << 1, + c->adapter->name); - if (dev_id == 0x5150 && rom_ver == 0x0321) { /* TVP51510A */ + if (core->dev_id == 0x5150 && core->rom_ver == 0x0321) { v4l2_info(sd, "tvp5150a detected.\n"); - } else if (dev_id == 0x5150 && rom_ver == 0x0400) { /* TVP5150AM1 */ + } else if (core->dev_id == 0x5150 && core->rom_ver == 0x0400) { v4l2_info(sd, "tvp5150am1 detected.\n"); /* ITU-T BT.656.4 timing */ tvp5150_write(sd, TVP5150_REV_SELECT, 0); - } else if (dev_id == 0x5151 && rom_ver == 0x0100) { /* TVP5151 */ + } else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) { v4l2_info(sd, "tvp5151 detected.\n"); } else { - v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); + v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", + core->dev_id); } return 0; -- cgit v1.2.3 From f38f2622f876609c3dc2865bbd937be22bad5a42 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:55 -0200 Subject: [media] tvp5150: add internal signal generator to HW input list Some tvp5150 variants, have an internal generator that can generate a black screen output. Since this is a HW block, it should be in the HW inputs list. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- include/media/i2c/tvp5150.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/media/i2c/tvp5150.h b/include/media/i2c/tvp5150.h index 649908a25605..685a1e718531 100644 --- a/include/media/i2c/tvp5150.h +++ b/include/media/i2c/tvp5150.h @@ -25,6 +25,7 @@ #define TVP5150_COMPOSITE0 0 #define TVP5150_COMPOSITE1 1 #define TVP5150_SVIDEO 2 +#define TVP5150_GENERATOR 3 /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 -- cgit v1.2.3 From b802fb99ae964681d1754428f67970911e0476e9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:56 -0200 Subject: [media] tvp5150: move input definition header to dt-bindings Add a header file for the tvp5150 input connectors constants that can be shared between the driver and Device Tree source files. [mchehab@osg.samsung.com: rename tvp5150.h also at em28xx-cards.c] Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 +- drivers/media/usb/em28xx/em28xx-cards.c | 2 +- include/dt-bindings/media/tvp5150.h | 34 +++++++++++++++++++++++++++++++++ include/media/i2c/tvp5150.h | 34 --------------------------------- 4 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 include/dt-bindings/media/tvp5150.h delete mode 100644 include/media/i2c/tvp5150.h diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 093ff80f944c..3a32fd1df805 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -5,6 +5,7 @@ * This code is placed under the terms of the GNU General Public License v2 */ +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ba442c967415..06a09b4e4a83 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h new file mode 100644 index 000000000000..dc347569854f --- /dev/null +++ b/include/dt-bindings/media/tvp5150.h @@ -0,0 +1,34 @@ +/* + tvp5150.h - definition for tvp5150 inputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _DT_BINDINGS_MEDIA_TVP5150_H +#define _DT_BINDINGS_MEDIA_TVP5150_H + +/* TVP5150 HW inputs */ +#define TVP5150_COMPOSITE0 0 +#define TVP5150_COMPOSITE1 1 +#define TVP5150_SVIDEO 2 +#define TVP5150_GENERATOR 3 + +/* TVP5150 HW outputs */ +#define TVP5150_NORMAL 0 +#define TVP5150_BLACK_SCREEN 1 + +#endif /* _DT_BINDINGS_MEDIA_TVP5150_H */ diff --git a/include/media/i2c/tvp5150.h b/include/media/i2c/tvp5150.h deleted file mode 100644 index 685a1e718531..000000000000 --- a/include/media/i2c/tvp5150.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - tvp5150.h - definition for tvp5150 inputs - - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TVP5150_H_ -#define _TVP5150_H_ - -/* TVP5150 HW inputs */ -#define TVP5150_COMPOSITE0 0 -#define TVP5150_COMPOSITE1 1 -#define TVP5150_SVIDEO 2 -#define TVP5150_GENERATOR 3 - -/* TVP5150 HW outputs */ -#define TVP5150_NORMAL 0 -#define TVP5150_BLACK_SCREEN 1 - -#endif -- cgit v1.2.3 From 82c2ffeb217a024084f3ad0bf3705f5661365804 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:57 -0200 Subject: [media] tvp5150: document input connectors DT bindings The tvp5150 decoder has different input connectors so extend the device tree binding to allow device tree source files to define the connectors that are available on a given board. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/tvp5150.txt | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt index 8c0fc1a26bf0..daa20e43a8e3 100644 --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt @@ -12,6 +12,32 @@ Optional Properties: - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any. - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any. +Optional nodes: +- connectors: The input connectors of tvp5150 have to be defined under + a subnode name "connectors" using the following format: + + input-connector-name { + input connector properties + }; + +Each input connector must contain the following properties: + + - label: a name for the connector. + - input: the input connector. + +The possible values for the "input" property are: + 0: Composite0 + 1: Composite1 + 2: S-Video + +and on a tvp5150am1 and tvp5151 there is another: + 4: Signal generator + +The list of valid input connectors are defined in dt-bindings/media/tvp5150.h +header file and can be included by device tree source files. + +Each input connector can be defined only once. + The device node must contain one 'port' child node for its digital output video port, in accordance with the video interface bindings defined in Documentation/devicetree/bindings/media/video-interfaces.txt. @@ -36,6 +62,23 @@ Example: pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>; + connectors { + composite0 { + label = "Composite0"; + input = ; + }; + + composite1 { + label = "Composite1"; + input = ; + }; + + s-video { + label = "S-Video"; + input = ; + }; + }; + port { tvp5150_1: endpoint { remote-endpoint = <&ccdc_ep>; -- cgit v1.2.3 From f7b4b54e63643b740c598e044874c4bffa0f04f2 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:58 -0200 Subject: [media] tvp5150: add HW input connectors support The tvp5150 decoder has different input connectors. The actual list of HW inputs depends on the device version but all have at least these 3: 1) Composite0 2) Composite1 3) S-Video and some variants have a 4th possible input connector: 4) Signal generator The driver currently uses the .s_routing callback to switch the input connector but since these are separate HW blocks, it's better to use media entities to represent the input connectors and their source pads linked with the decoder's sink pad. This allows user-space to use the MEDIA_IOC_SETUP_LINK ioctl to choose the input connector. For example using the media-ctl user-space tool: $ media-ctl -r -l '"Composite0":0->"tvp5150 1-005c":0[1]' Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 150 ++++++++++++++++++++++++++++++++++++ include/dt-bindings/media/tvp5150.h | 2 + 2 files changed, 152 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 3a32fd1df805..b8976028fc82 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -40,6 +40,8 @@ struct tvp5150 { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_pad pads[DEMOD_NUM_PADS]; + struct media_entity input_ent[TVP5150_INPUT_NUM]; + struct media_pad input_pad[TVP5150_INPUT_NUM]; #endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -996,6 +998,49 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + Media entity ops + ****************************************************************************/ + +static int tvp5150_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct tvp5150 *decoder = to_tvp5150(sd); + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + if (remote->entity == &decoder->input_ent[i]) + break; + } + + /* Do nothing for entities that are not input connectors */ + if (i == TVP5150_INPUT_NUM) + return 0; + + decoder->input = i; + + /* Only tvp5150am1 and tvp5151 have signal generator support */ + if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || + (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { + decoder->output = (i == TVP5150_GENERATOR ? + TVP5150_BLACK_SCREEN : TVP5150_NORMAL); + } else { + decoder->output = TVP5150_NORMAL; + } + + tvp5150_selmux(sd); +#endif + + return 0; +} + +static const struct media_entity_operations tvp5150_sd_media_ops = { + .link_setup = tvp5150_link_setup, +}; + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1122,6 +1167,42 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } +static int tvp5150_registered_async(struct v4l2_subdev *sd) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct tvp5150 *decoder = to_tvp5150(sd); + int ret = 0; + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + struct media_entity *input = &decoder->input_ent[i]; + struct media_pad *pad = &decoder->input_pad[i]; + + if (!input->name) + continue; + + decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(input, 1, pad); + if (ret < 0) + return ret; + + ret = media_device_register_entity(sd->v4l2_dev->mdev, input); + if (ret < 0) + return ret; + + ret = media_create_pad_link(input, 0, &sd->entity, + DEMOD_PAD_IF_INPUT, 0); + if (ret < 0) { + media_device_unregister_entity(input); + return ret; + } + } +#endif + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1135,6 +1216,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, #endif + .registered_async = tvp5150_registered_async, }; static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { @@ -1255,6 +1337,12 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { struct v4l2_of_endpoint bus_cfg; struct device_node *ep; +#ifdef CONFIG_MEDIA_CONTROLLER + struct device_node *connectors, *child; + struct media_entity *input; + const char *name; + u32 input_type; +#endif unsigned int flags; int ret = 0; @@ -1278,6 +1366,66 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) decoder->mbus_type = bus_cfg.bus_type; +#ifdef CONFIG_MEDIA_CONTROLLER + connectors = of_get_child_by_name(np, "connectors"); + + if (!connectors) + goto err; + + for_each_available_child_of_node(connectors, child) { + ret = of_property_read_u32(child, "input", &input_type); + if (ret) { + v4l2_err(&decoder->sd, + "missing type property in node %s\n", + child->name); + goto err_connector; + } + + if (input_type > TVP5150_INPUT_NUM) { + ret = -EINVAL; + goto err_connector; + } + + input = &decoder->input_ent[input_type]; + + /* Each input connector can only be defined once */ + if (input->name) { + v4l2_err(&decoder->sd, + "input %s with same type already exists\n", + input->name); + ret = -EINVAL; + goto err_connector; + } + + switch (input_type) { + case TVP5150_COMPOSITE0: + case TVP5150_COMPOSITE1: + input->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case TVP5150_SVIDEO: + input->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + case TVP5150_GENERATOR: + input->function = MEDIA_ENT_F_CONN_TEST; + break; + } + + input->flags = MEDIA_ENT_FL_CONNECTOR; + + ret = of_property_read_string(child, "label", &name); + if (ret < 0) { + v4l2_err(&decoder->sd, + "missing label property in node %s\n", + child->name); + goto err_connector; + } + + input->name = name; + } + +err_connector: + of_node_put(connectors); +#endif err: of_node_put(ep); return ret; @@ -1330,6 +1478,8 @@ static int tvp5150_probe(struct i2c_client *c, res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; + + sd->entity.ops = &tvp5150_sd_media_ops; #endif res = tvp5150_detect_version(core); diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index dc347569854f..d30865222082 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -27,6 +27,8 @@ #define TVP5150_SVIDEO 2 #define TVP5150_GENERATOR 3 +#define TVP5150_INPUT_NUM 4 + /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 #define TVP5150_BLACK_SCREEN 1 -- cgit v1.2.3 From db152276ce720baadcbd6bccebbeb17da001d312 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 07:35:44 -0200 Subject: [media] v4l2-mc.h: prevent it for being included twice Don't let it be included twice, to avoid compiler issues. Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 6fad97277a0b..20f1ee285947 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -14,6 +14,9 @@ * GNU General Public License for more details. */ +#ifndef _V4L2_MC_H +#define _V4L2_MC_H + #include /** @@ -136,3 +139,5 @@ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, } #endif + +#endif -- cgit v1.2.3 From eee7d353a19032b48c0f71504081de84a0ee79d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 15:21:46 -0200 Subject: [media] v4l2-mc: add a routine to create USB media_device Instead of copying exactly the same code on all USB devices, add an ancillary routine that will create and fill the struct media_device with the values imported from the USB device. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 41 ++++++++++++++++++++++++++++++++++++++- include/media/v4l2-mc.h | 39 ++++++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index b6cf6dbd4cd5..97b2e1e64d2e 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -16,12 +16,13 @@ #include #include +#include #include #include struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name) + const char *name) { #ifdef CONFIG_PCI struct media_device *mdev; @@ -53,6 +54,44 @@ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, } EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + const char *board_name, + const char *driver_name) +{ +#ifdef CONFIG_USB + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &udev->dev; + + if (driver_name) + strlcpy(mdev->driver_name, driver_name, + sizeof(mdev->driver_name)); + + if (board_name) + strlcpy(mdev->model, board_name, sizeof(mdev->model)); + else if (udev->product) + strlcpy(mdev->model, udev->product, sizeof(mdev->model)); + else + strlcpy(mdev->model, "unknown model", sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info)); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(__v4l2_mc_usb_media_device_init); + int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 20f1ee285947..79d84bb3573c 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -95,8 +95,9 @@ enum demod_pad_index { DEMOD_NUM_PADS }; - -struct pci_dev; /* We don't need to include pci.h here */ +/* We don't need to include pci.h or usb.h here */ +struct pci_dev; +struct usb_device; #ifdef CONFIG_MEDIA_CONTROLLER /** @@ -124,8 +125,24 @@ int v4l2_mc_create_media_graph(struct media_device *mdev); * name for the pci device, given by pci_name() macro. */ struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name); - + const char *name); +/** + * __v4l2_mc_usb_media_device_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @udev: pointer to struct usb_device + * @board_name: media device name. If %NULL, the routine will use the usb + * product name, if available. + * @driver_name: name of the driver. if %NULL, the routine will use the name + * given by udev->dev->driver->name, with is usually the wrong + * thing to do. + * + * NOTE: It is better to call v4l2_mc_usb_media_device_init() instead, as + * such macro fills driver_name with %KBUILD_MODNAME. + */ +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + const char *board_name, + const char *driver_name); #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) @@ -133,11 +150,23 @@ static inline int v4l2_mc_create_media_graph(struct media_device *mdev) return 0; } +static inline struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, - char *name) { + char *name) +{ return NULL; } +static inline +struct media_device *__v4l2_mc_usb_media_device_init(struct usb_device *udev, + char *board_name, + char *driver_name) +{ + return NULL; +} #endif +#define v4l2_mc_usb_media_device_init(udev, name) \ + __v4l2_mc_usb_media_device_init(udev, name, KBUILD_MODNAME) + #endif -- cgit v1.2.3 From c73bbaa4ec3eb225ffe468f80d45724d0496bf03 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 10:33:31 -0200 Subject: [media] rc-core: don't lock device at rc_register_device() The mutex lock at rc_register_device() was added by commit 08aeb7c9a42a ("[media] rc: add locking to fix register/show race"). It is meant to avoid race issues when trying to open a sysfs file while the RC register didn't complete. Adding a lock there causes troubles, as detected by the Kernel lock debug instrumentation at the Kernel: ====================================================== [ INFO: possible circular locking dependency detected ] 4.5.0-rc3+ #46 Not tainted ------------------------------------------------------- systemd-udevd/2681 is trying to acquire lock: (s_active#171){++++.+}, at: [] kernfs_remove_by_name_ns+0x45/0xa0 but task is already holding lock: (&dev->lock){+.+.+.}, at: [] rc_register_device+0xb2f/0x1450 [rc_core] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&dev->lock){+.+.+.}: [] lock_acquire+0x13d/0x320 [] mutex_lock_nested+0xb6/0x860 [] show_protocols+0x3b/0x3f0 [rc_core] [] dev_attr_show+0x45/0xc0 [] sysfs_kf_seq_show+0x203/0x3c0 [] kernfs_seq_show+0x121/0x1b0 [] seq_read+0x2f1/0x1160 [] kernfs_fop_read+0x321/0x460 [] __vfs_read+0xe0/0x3d0 [] vfs_read+0xde/0x2d0 [] SyS_read+0x111/0x230 [] entry_SYSCALL_64_fastpath+0x16/0x76 -> #0 (s_active#171){++++.+}: [] __lock_acquire+0x4304/0x5990 [] lock_acquire+0x13d/0x320 [] __kernfs_remove+0x58a/0x810 [] kernfs_remove_by_name_ns+0x45/0xa0 [] remove_files.isra.0+0x72/0x190 [] sysfs_remove_group+0x9b/0x150 [] sysfs_remove_groups+0x54/0xa0 [] device_remove_attrs+0xb0/0x140 [] device_del+0x38c/0x6b0 [] rc_register_device+0x8cb/0x1450 [rc_core] [] dvb_usb_remote_init+0x66b/0x14d0 [dvb_usb] [] dvb_usb_device_init+0xf21/0x1860 [dvb_usb] [] dib0700_probe+0x14c/0x410 [dvb_usb_dib0700] [] usb_probe_interface+0x45d/0x940 [] driver_probe_device+0x21a/0xc30 [] __driver_attach+0x121/0x160 [] bus_for_each_dev+0x11f/0x1a0 [] driver_attach+0x3d/0x50 [] bus_add_driver+0x4c9/0x770 [] driver_register+0x18c/0x3b0 [] usb_register_driver+0x1f8/0x440 [] dib0700_driver_init+0x1e/0x1000 [dvb_usb_dib0700] [] do_one_initcall+0x141/0x300 [] do_init_module+0x1d0/0x5ad [] load_module+0x6666/0x9ba0 [] SyS_finit_module+0x108/0x130 [] entry_SYSCALL_64_fastpath+0x16/0x76 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&dev->lock); lock(s_active#171); lock(&dev->lock); lock(s_active#171); *** DEADLOCK *** 3 locks held by systemd-udevd/2681: #0: (&dev->mutex){......}, at: [] __driver_attach+0xa3/0x160 #1: (&dev->mutex){......}, at: [] __driver_attach+0xb1/0x160 #2: (&dev->lock){+.+.+.}, at: [] rc_register_device+0xb2f/0x1450 [rc_core] In this specific case, some error happened during device init, causing IR to be disabled. Let's fix it by adding a var that will tell when the device is initialized. Any calls before that will return a -EINVAL. That should prevent the race issues. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 45 ++++++++++++++++++++++++++------------------- include/media/rc-core.h | 2 ++ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1042fa331a07..dcf20d9cbe09 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -723,12 +723,18 @@ int rc_open(struct rc_dev *rdev) return -EINVAL; mutex_lock(&rdev->lock); + if (!rdev->initialized) { + rval = -EINVAL; + goto unlock; + } + if (!rdev->users++ && rdev->open != NULL) rval = rdev->open(rdev); if (rval) rdev->users--; +unlock: mutex_unlock(&rdev->lock); return rval; @@ -874,6 +880,10 @@ static ssize_t show_protocols(struct device *device, return -EINVAL; mutex_lock(&dev->lock); + if (!dev->initialized) { + mutex_unlock(&dev->lock); + return -EINVAL; + } if (fattr->type == RC_FILTER_NORMAL) { enabled = dev->enabled_protocols; @@ -1074,6 +1084,10 @@ static ssize_t store_protocols(struct device *device, } mutex_lock(&dev->lock); + if (!dev->initialized) { + rc = -EINVAL; + goto out; + } old_protocols = *current_protocols; new_protocols = old_protocols; @@ -1154,12 +1168,17 @@ static ssize_t show_filter(struct device *device, if (!dev) return -EINVAL; + mutex_lock(&dev->lock); + if (!dev->initialized) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + if (fattr->type == RC_FILTER_NORMAL) filter = &dev->scancode_filter; else filter = &dev->scancode_wakeup_filter; - mutex_lock(&dev->lock); if (fattr->mask) val = filter->mask; else @@ -1222,6 +1241,10 @@ static ssize_t store_filter(struct device *device, return -EINVAL; mutex_lock(&dev->lock); + if (!dev->initialized) { + ret = -EINVAL; + goto unlock; + } new_filter = *filter; if (fattr->mask) @@ -1419,14 +1442,6 @@ int rc_register_device(struct rc_dev *dev) dev->sysfs_groups[attr++] = &rc_dev_wakeup_protocol_attr_grp; dev->sysfs_groups[attr++] = NULL; - /* - * Take the lock here, as the device sysfs node will appear - * when device_add() is called, which may trigger an ir-keytable udev - * rule, which will in turn call show_protocols and access - * dev->enabled_protocols before it has been initialized. - */ - mutex_lock(&dev->lock); - rc = device_add(&dev->dev); if (rc) goto out_unlock; @@ -1440,13 +1455,7 @@ int rc_register_device(struct rc_dev *dev) dev->input_dev->phys = dev->input_phys; dev->input_dev->name = dev->input_name; - /* input_register_device can call ir_open, so unlock mutex here */ - mutex_unlock(&dev->lock); - rc = input_register_device(dev->input_dev); - - mutex_lock(&dev->lock); - if (rc) goto out_table; @@ -1475,10 +1484,7 @@ int rc_register_device(struct rc_dev *dev) request_module_nowait("ir-lirc-codec"); raw_init = true; } - /* calls ir_register_device so unlock mutex here*/ - mutex_unlock(&dev->lock); rc = ir_raw_event_register(dev); - mutex_lock(&dev->lock); if (rc < 0) goto out_input; } @@ -1491,6 +1497,8 @@ int rc_register_device(struct rc_dev *dev) dev->enabled_protocols = rc_type; } + mutex_lock(&dev->lock); + dev->initialized = true; mutex_unlock(&dev->lock); IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n", @@ -1512,7 +1520,6 @@ out_table: out_dev: device_del(&dev->dev); out_unlock: - mutex_unlock(&dev->lock); ida_simple_remove(&rc_ida, minor); return rc; } diff --git a/include/media/rc-core.h b/include/media/rc-core.h index f6494709e230..c41dd7018fa8 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -60,6 +60,7 @@ enum rc_filter_type { /** * struct rc_dev - represents a remote control device * @dev: driver model's view of this device + * @initialized: true if the device init has completed * @sysfs_groups: sysfs attribute groups * @input_name: name of the input child device * @input_phys: physical path to the input child device @@ -121,6 +122,7 @@ enum rc_filter_type { */ struct rc_dev { struct device dev; + bool initialized; const struct attribute_group *sysfs_groups[5]; const char *input_name; const char *input_phys; -- cgit v1.2.3 From bb07bd6b6851120ac9b25bb315d62d9782d2c345 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 14:24:23 -0200 Subject: [media] allow overriding the driver name On USB drivers, the dev struct is usually filled with the USB device. That would mean that the name of the driver specified by media_device.dev.driver.name would be "usb", instead of the name of the actual driver that created the media entity. Add an optional field at the internal struct to allow drivers to override the driver name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 6 +++++- include/media/media-device.h | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 4d1c13de494b..5ebb3cd31345 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -55,7 +55,11 @@ static int media_device_get_info(struct media_device *dev, memset(&info, 0, sizeof(info)); - strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); + if (dev->driver_name[0]) + strlcpy(info.driver, dev->driver_name, sizeof(info.driver)); + else + strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); + strlcpy(info.model, dev->model, sizeof(info.model)); strlcpy(info.serial, dev->serial, sizeof(info.serial)); strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info)); diff --git a/include/media/media-device.h b/include/media/media-device.h index d3855898c3fc..165451bc3985 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -268,6 +268,10 @@ struct device; * struct media_device - Media device * @dev: Parent device * @devnode: Media device node + * @driver_name: Optional device driver name. If not set, calls to + * %MEDIA_IOC_DEVICE_INFO will return dev->driver->name. + * This is needed for USB drivers for example, as otherwise + * they'll all appear as if the driver name was "usb". * @model: Device model name * @serial: Device serial number (optional) * @bus_info: Unique and stable device location identifier @@ -303,6 +307,7 @@ struct media_device { struct media_devnode devnode; char model[32]; + char driver_name[32]; char serial[40]; char bus_info[32]; u32 hw_revision; -- cgit v1.2.3 From 67873d4e751e400149df7ab61ba04cbb4cc0d449 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 15:35:07 -0200 Subject: [media] use v4l2_mc_usb_media_device_init() on most USB devices Except for the usbuvc driver (with has an embedded media_device struct on it), the other drivers have a pointer to media_device. On those drivers, replace their own implementation for the core one. That warrants that those subdev drivers will fill the media_device info the same way. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 19 ++++--------------- drivers/media/usb/cx231xx/cx231xx-cards.c | 12 +----------- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 13 ++----------- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 15 ++------------- drivers/media/usb/em28xx/em28xx-cards.c | 23 ++++++++--------------- 5 files changed, 17 insertions(+), 65 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index f23da7e7984b..7cafe4dd5fd1 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -191,23 +191,12 @@ static int au0828_media_device_init(struct au0828_dev *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return -ENOMEM; - - mdev->dev = &udev->dev; - if (!dev->board.name) - strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model)); + mdev = v4l2_mc_usb_media_device_init(udev, "unknown au0828"); else - strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); + mdev = v4l2_mc_usb_media_device_init(udev, dev->board.name); + if (!mdev) + return -ENOMEM; dev->media_dev = mdev; #endif diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 54e43fe13e6d..a8d0655f7250 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1212,20 +1212,10 @@ static int cx231xx_media_device_init(struct cx231xx *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + mdev = v4l2_mc_usb_media_device_init(udev, dev->board.name); if (!mdev) return -ENOMEM; - mdev->dev = dev->dev; - strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - dev->media_dev = mdev; #endif return 0; diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 5ec159f22399..4a8769781cea 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -20,6 +20,7 @@ */ #include "dvb_usb_common.h" +#include static int dvb_usbv2_disable_rc_polling; module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); @@ -407,20 +408,10 @@ static int dvb_usbv2_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap_to_d(adap); struct usb_device *udev = d->udev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + mdev = v4l2_mc_usb_media_device_init(udev, d->name); if (!mdev) return -ENOMEM; - mdev->dev = &udev->dev; - strlcpy(mdev->model, d->name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - dvb_register_media_controller(&adap->dvb_adap, mdev); dev_info(&d->udev->dev, "media controller created\n"); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 71de19ba0e01..513b0c14e4f0 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -7,6 +7,7 @@ * linux-dvb API. */ #include "dvb-usb-common.h" +#include /* does the complete input transfer handling */ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) @@ -102,19 +103,7 @@ static int dvb_usb_media_device_init(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap->dev; struct usb_device *udev = d->udev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return -ENOMEM; - - mdev->dev = &udev->dev; - strlcpy(mdev->model, d->desc->name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); + mdev = v4l2_mc_usb_media_device_init(udev, d->desc->name); dvb_register_media_controller(&adap->dvb_adap, mdev); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 06a09b4e4a83..389e95fb0211 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3019,24 +3019,17 @@ static int em28xx_media_device_init(struct em28xx *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (udev->product) { + mdev = v4l2_mc_usb_media_device_init(udev, udev->product); + } else if (udev->manufacturer) { + mdev = v4l2_mc_usb_media_device_init(udev, udev->manufacturer); + } else { + mdev = v4l2_mc_usb_media_device_init(udev, dev->name); + } + if (!mdev) return -ENOMEM; - mdev->dev = &udev->dev; - - if (!dev->name) - strlcpy(mdev->model, "unknown em28xx", sizeof(mdev->model)); - else - strlcpy(mdev->model, dev->name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - dev->media_dev = mdev; #endif return 0; -- cgit v1.2.3 From e9ef88bd161b9147a18844668e6aa202fcfdab8e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 17:17:30 -0200 Subject: [media] em28xx-dvb: create RF connector on DVB-only mode When in analog mode, the RF connector will be created by em28xx-video. However, when the device is in digital mode only, the RF connector is not shown. In this case, let the DVB core to create it for us. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 7 ++++++- drivers/media/usb/em28xx/em28xx-video.c | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index ea80541d58f0..7ca2fbd3b14a 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -905,6 +905,7 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, struct em28xx *dev, struct device *device) { int result; + bool create_rf_connector = false; mutex_init(&dvb->lock); @@ -998,7 +999,11 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - result = dvb_create_media_graph(&dvb->adapter, false); + /* If the analog part won't create RF connectors, DVB will do it */ + if (!dev->has_video || (dev->tuner_type == TUNER_ABSENT)) + create_rf_connector = true; + + result = dvb_create_media_graph(&dvb->adapter, create_rf_connector); if (result < 0) goto fail_create_graph; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index e7fd0bac4a08..f772e2612608 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -990,7 +990,8 @@ static void em28xx_v4l2_create_entities(struct em28xx *dev) ent->function = MEDIA_ENT_F_CONN_SVIDEO; break; default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ - ent->function = MEDIA_ENT_F_CONN_RF; + if (dev->tuner_type != TUNER_ABSENT) + ent->function = MEDIA_ENT_F_CONN_RF; break; } -- cgit v1.2.3 From 08f49200513ca7e42c24ab6f43233ae0a7b8b190 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 17:31:48 -0200 Subject: [media] cx231xx: use v4l2 core function to create the MC graph Instead of having its own routine, use the one defined at the core, as it is generic enough to handle the cx231xx usecases. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-cards.c | 55 ++----------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index a8d0655f7250..91bf671d2959 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1221,51 +1221,6 @@ static int cx231xx_media_device_init(struct cx231xx *dev, return 0; } -static int cx231xx_create_media_graph(struct cx231xx *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct media_device *mdev = dev->media_dev; - struct media_entity *entity; - struct media_entity *tuner = NULL, *decoder = NULL; - int ret; - - if (!mdev) - return 0; - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_TUNER: - tuner = entity; - break; - case MEDIA_ENT_F_ATV_DECODER: - decoder = entity; - break; - } - } - - /* Analog setup, using tuner as a link */ - - if (!decoder) - return 0; - - if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, - MEDIA_LNK_FL_ENABLED); - if (ret < 0) - return ret; - } - ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret < 0) - return ret; - ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret < 0) - return ret; -#endif - return 0; -} - /* * cx231xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device @@ -1729,15 +1684,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* load other modules required */ request_modules(dev); - retval = cx231xx_create_media_graph(dev); - if (retval < 0) - goto done; - #ifdef CONFIG_MEDIA_CONTROLLER - retval = media_device_register(dev->media_dev); + retval = v4l2_mc_create_media_graph(dev->media_dev); + if (!retval) + retval = media_device_register(dev->media_dev); #endif - -done: if (retval < 0) cx231xx_release_resources(dev); return retval; -- cgit v1.2.3 From 8b0a81c73326af2defaa0d8a4494c7def83928bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 18:06:36 -0200 Subject: [media] si2157: register as a tuner entity As this tuner doesn't use the usual subdev interface, we need to register it manually. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 32 +++++++++++++++++++++++++++++++- drivers/media/tuners/si2157.h | 5 +++++ drivers/media/tuners/si2157_priv.h | 8 ++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 3450dfb7c427..243ac3816028 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -403,7 +403,7 @@ err: } static int si2157_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct si2157_config *cfg = client->dev.platform_data; struct dvb_frontend *fe = cfg->fe; @@ -438,6 +438,31 @@ static int si2157_probe(struct i2c_client *client, memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = client; +#ifdef CONFIG_MEDIA_CONTROLLER + if (cfg->mdev) { + dev->mdev = cfg->mdev; + + dev->ent.name = KBUILD_MODNAME; + dev->ent.function = MEDIA_ENT_F_TUNER; + + dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS, + &dev->pad[0]); + + if (ret) + goto err_kfree; + + ret = media_device_register_entity(cfg->mdev, &dev->ent); + if (ret) { + media_entity_cleanup(&dev->ent); + goto err_kfree; + } + } +#endif + dev_info(&client->dev, "Silicon Labs %s successfully attached\n", dev->chiptype == SI2157_CHIPTYPE_SI2146 ? "Si2146" : "Si2147/2148/2157/2158"); @@ -461,6 +486,11 @@ static int si2157_remove(struct i2c_client *client) /* stop statistics polling */ cancel_delayed_work_sync(&dev->stat_work); +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + if (dev->mdev) + media_device_unregister_entity(&dev->ent); +#endif + memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = NULL; kfree(dev); diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h index 4db97ab744d6..5f1a60bf7ced 100644 --- a/drivers/media/tuners/si2157.h +++ b/drivers/media/tuners/si2157.h @@ -18,6 +18,7 @@ #define SI2157_H #include +#include #include "dvb_frontend.h" /* @@ -30,6 +31,10 @@ struct si2157_config { */ struct dvb_frontend *fe; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_device *mdev; +#endif + /* * Spectral Inversion */ diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index ecc463db8f69..589d558d381c 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -18,6 +18,7 @@ #define SI2157_PRIV_H #include +#include #include "si2157.h" /* state struct */ @@ -31,6 +32,13 @@ struct si2157_dev { u8 if_port; u32 if_frequency; struct delayed_work stat_work; + +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_device *mdev; + struct media_entity ent; + struct media_pad pad[TUNER_NUM_PADS]; +#endif + }; #define SI2157_CHIPTYPE_SI2157 0 -- cgit v1.2.3 From 133bc4e4a3cdbead6ad17d5acfc2997026d8ca79 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 22:18:36 -0200 Subject: [media] cx231xx, em28xx: pass media_device to si2157 As si2157 doesn't use the subdev, but has instead a binding logic that doesn't have any core framework, we need to manually pass the media_device struct via platform data on every place it is called. This fixes support for HVR-955Q when MC is enabled. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-dvb.c | 6 ++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index b8d5b2be9293..efac745fa559 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -801,6 +801,9 @@ static int dvb_init(struct cx231xx *dev) /* attach tuner */ memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dev->dvb->frontend; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif si2157_config.if_port = 1; si2157_config.inversion = true; strlcpy(info.type, "si2157", I2C_NAME_SIZE); @@ -857,6 +860,9 @@ static int dvb_init(struct cx231xx *dev) /* attach tuner */ memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dev->dvb->frontend; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif si2157_config.if_port = 1; si2157_config.inversion = true; strlcpy(info.type, "si2157", I2C_NAME_SIZE); diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 7ca2fbd3b14a..5d209c7c54d5 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1671,6 +1671,9 @@ static int em28xx_dvb_init(struct em28xx *dev) memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dvb->fe[0]; si2157_config.if_port = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; @@ -1732,6 +1735,9 @@ static int em28xx_dvb_init(struct em28xx *dev) memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dvb->fe[0]; si2157_config.if_port = 0; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "si2146", I2C_NAME_SIZE); info.addr = 0x60; -- cgit v1.2.3 From 6168309acd6afe420108dba20a66e6781b933f89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Feb 2016 22:39:52 -0200 Subject: [media] cx231xx: create connectors at the media graph We need to add connectors to the cx231xx graph. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-cards.c | 3 ++ drivers/media/usb/cx231xx/cx231xx-dvb.c | 4 ++- drivers/media/usb/cx231xx/cx231xx-video.c | 46 +++++++++++++++++++++++++++++++ drivers/media/usb/cx231xx/cx231xx.h | 3 ++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 91bf671d2959..9e3a5d2038c2 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1685,6 +1685,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface, request_modules(dev); #ifdef CONFIG_MEDIA_CONTROLLER + /* Init entities at the Media Controller */ + cx231xx_v4l2_create_entities(dev); + retval = v4l2_mc_create_media_graph(dev->media_dev); if (!retval) retval = media_device_register(dev->media_dev); diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index efac745fa559..ab2fb9fa0cd1 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -25,6 +25,7 @@ #include #include +#include #include "xc5000.h" #include "s5h1432.h" @@ -551,7 +552,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - result = dvb_create_media_graph(&dvb->adapter, false); + result = dvb_create_media_graph(&dvb->adapter, + dev->tuner_type == TUNER_ABSENT); if (result < 0) goto fail_create_graph; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 9b88cd8127ac..7222b1c27d40 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1106,6 +1106,52 @@ static const char *iname[] = { [CX231XX_VMUX_DEBUG] = "for debug only", }; +void cx231xx_v4l2_create_entities(struct cx231xx *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret, i; + + /* Create entities for each input connector */ + for (i = 0; i < MAX_CX231XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + ent->name = iname[INPUT(i)->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (INPUT(i)->type) { + case CX231XX_VMUX_COMPOSITE1: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case CX231XX_VMUX_SVIDEO: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + case CX231XX_VMUX_DVB: + /* The DVB core will handle it */ + if (dev->tuner_type == TUNER_ABSENT) + continue; + /* fall though */ + default: /* CX231XX_VMUX_DEBUG */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + int cx231xx_enum_input(struct file *file, void *priv, struct v4l2_input *i) { diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index ec6d3f5bc36d..60e14776a6cd 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -663,6 +663,8 @@ struct cx231xx { #if defined(CONFIG_MEDIA_CONTROLLER) struct media_device *media_dev; struct media_pad video_pad, vbi_pad; + struct media_entity input_ent[MAX_CX231XX_INPUT]; + struct media_pad input_pad[MAX_CX231XX_INPUT]; #endif unsigned char eedata[256]; @@ -943,6 +945,7 @@ int cx231xx_register_extension(struct cx231xx_ops *dev); void cx231xx_unregister_extension(struct cx231xx_ops *dev); void cx231xx_init_extension(struct cx231xx *dev); void cx231xx_close_extension(struct cx231xx *dev); +void cx231xx_v4l2_create_entities(struct cx231xx *dev); int cx231xx_querycap(struct file *file, void *priv, struct v4l2_capability *cap); int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); -- cgit v1.2.3 From 153d41a1d0a47dfd4d773d8b9db192a62f92355e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 08:07:59 -0200 Subject: [media] v4l2-mc: remove the unused sensor var This fixes this warning: v4l2-mc.c: In function 'v4l2_mc_create_media_graph': v4l2-mc.c:60:69: warning: variable 'sensor' set but not used [-Wunused-but-set-variable] We could solve it the other way: don't do the second loop for webcams. However, that would fail if a chip would have two sensors plugged. This is not the current case, but it doesn't hurt to be future-safe here, specially since this code runs only once during device probe. So, performance is not an issue here. Reported-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 97b2e1e64d2e..9d79d599d979 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -96,7 +96,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) { struct media_entity *entity; - struct media_entity *if_vid = NULL, *if_aud = NULL, *sensor = NULL; + struct media_entity *if_vid = NULL, *if_aud = NULL; struct media_entity *tuner = NULL, *decoder = NULL; struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; bool is_webcam = false; @@ -130,7 +130,6 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) io_swradio = entity; break; case MEDIA_ENT_F_CAM_SENSOR: - sensor = entity; is_webcam = true; break; } -- cgit v1.2.3 From 34ac25320357e7ff81c001538e786f3b027fa3b1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 09:15:41 -0200 Subject: [media] au0828: get rid of AU0828_VMUX_DEBUG This is not used on the driver. remove it. Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 12 +++--------- drivers/media/usb/au0828/au0828.h | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 4164302dd8ac..2fc2b29d2dd9 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -698,10 +698,9 @@ static int au0828_create_media_graph(struct au0828_dev *dev) for (i = 0; i < AU0828_MAX_INPUT; i++) { struct media_entity *ent = &dev->input_ent[i]; - if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) - break; - switch (AUVI_INPUT(i).type) { + case AU0828_VMUX_UNDEFINED: + break; case AU0828_VMUX_CABLE: case AU0828_VMUX_TELEVISION: case AU0828_VMUX_DVB: @@ -716,7 +715,6 @@ static int au0828_create_media_graph(struct au0828_dev *dev) break; case AU0828_VMUX_COMPOSITE: case AU0828_VMUX_SVIDEO: - default: /* AU0828_VMUX_DEBUG */ /* FIXME: fix the decoder PAD */ ret = media_create_pad_link(ent, 0, decoder, 0, 0); if (ret) @@ -1460,7 +1458,6 @@ static int vidioc_enum_input(struct file *file, void *priv, [AU0828_VMUX_CABLE] = "Cable TV", [AU0828_VMUX_TELEVISION] = "Television", [AU0828_VMUX_DVB] = "DVB", - [AU0828_VMUX_DEBUG] = "tv debug" }; dprintk(1, "%s called std_set %d dev_state %d\n", __func__, @@ -1952,7 +1949,6 @@ static void au0828_analog_create_entities(struct au0828_dev *dev) [AU0828_VMUX_CABLE] = "Cable TV", [AU0828_VMUX_TELEVISION] = "Television", [AU0828_VMUX_DVB] = "DVB", - [AU0828_VMUX_DEBUG] = "tv debug" }; int ret, i; @@ -1988,11 +1984,9 @@ static void au0828_analog_create_entities(struct au0828_dev *dev) case AU0828_VMUX_CABLE: case AU0828_VMUX_TELEVISION: case AU0828_VMUX_DVB: + default: /* Just to shut up a warning */ ent->function = MEDIA_ENT_F_CONN_RF; break; - default: /* AU0828_VMUX_DEBUG */ - ent->function = MEDIA_ENT_F_CONN_TEST; - break; } ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 19fd6a841988..23f869cf11da 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -76,7 +76,6 @@ enum au0828_itype { AU0828_VMUX_CABLE, AU0828_VMUX_TELEVISION, AU0828_VMUX_DVB, - AU0828_VMUX_DEBUG }; struct au0828_input { -- cgit v1.2.3 From 22d50e9a48032893c0259bc134c5373e9d3d13ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 09:17:14 -0200 Subject: [media] cx231xx: get rid of CX231XX_VMUX_DEBUG This macro is not used inside the driver. get rid of it. Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-video.c | 3 +-- drivers/media/usb/cx231xx/cx231xx.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 7222b1c27d40..6414188ffdfa 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1103,7 +1103,6 @@ static const char *iname[] = { [CX231XX_VMUX_TELEVISION] = "Television", [CX231XX_VMUX_CABLE] = "Cable TV", [CX231XX_VMUX_DVB] = "DVB", - [CX231XX_VMUX_DEBUG] = "for debug only", }; void cx231xx_v4l2_create_entities(struct cx231xx *dev) @@ -1136,7 +1135,7 @@ void cx231xx_v4l2_create_entities(struct cx231xx *dev) if (dev->tuner_type == TUNER_ABSENT) continue; /* fall though */ - default: /* CX231XX_VMUX_DEBUG */ + default: /* just to shut up a gcc warning */ ent->function = MEDIA_ENT_F_CONN_RF; break; } diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 60e14776a6cd..69f6d20870f5 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -281,7 +281,6 @@ enum cx231xx_itype { CX231XX_VMUX_CABLE, CX231XX_RADIO, CX231XX_VMUX_DVB, - CX231XX_VMUX_DEBUG }; enum cx231xx_v_input { -- cgit v1.2.3 From c43875f66140f5457f90fc5f6f6840c74b2762cd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 15:42:02 -0200 Subject: [media] tvp5150: replace MEDIA_ENT_F_CONN_TEST by a control MEDIA_ENT_F_CONN_TEST is not really a connector, it is actually a signal generator. Also, as other drivers use the V4L2_CID_TEST_PATTERN control for signal generators, let's change the driver accordingly. Tested with Terratec Grabster AV350. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 45 +++++++++++++++++++++++-------------- include/dt-bindings/media/tvp5150.h | 3 +-- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index b8976028fc82..ef393f5daf2a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1,5 +1,5 @@ /* - * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver + * tvp5150 - Texas Instruments TVP5150A/AM1 and TVP5151 video decoder driver * * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 @@ -27,7 +27,7 @@ #define TVP5150_MAX_CROP_TOP 127 #define TVP5150_CROP_SHIFT 2 -MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); +MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); @@ -259,8 +259,12 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) int input = 0; int val; - if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable) - input = 8; + /* Only tvp5150am1 and tvp5151 have signal generator support */ + if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || + (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { + if (!decoder->enable) + input = 8; + } switch (decoder->input) { case TVP5150_COMPOSITE1: @@ -795,6 +799,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); + struct tvp5150 *decoder = to_tvp5150(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -808,6 +813,9 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) return 0; case V4L2_CID_HUE: tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val); + case V4L2_CID_TEST_PATTERN: + decoder->enable = ctrl->val ? false : true; + tvp5150_selmux(sd); return 0; } return -EINVAL; @@ -1022,15 +1030,6 @@ static int tvp5150_link_setup(struct media_entity *entity, decoder->input = i; - /* Only tvp5150am1 and tvp5151 have signal generator support */ - if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || - (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { - decoder->output = (i == TVP5150_GENERATOR ? - TVP5150_BLACK_SCREEN : TVP5150_NORMAL); - } else { - decoder->output = TVP5150_NORMAL; - } - tvp5150_selmux(sd); #endif @@ -1074,6 +1073,12 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd, decoder->input = input; decoder->output = output; + + if (output == TVP5150_BLACK_SCREEN) + decoder->enable = false; + else + decoder->enable = true; + tvp5150_selmux(sd); return 0; } @@ -1405,9 +1410,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) case TVP5150_SVIDEO: input->function = MEDIA_ENT_F_CONN_SVIDEO; break; - case TVP5150_GENERATOR: - input->function = MEDIA_ENT_F_CONN_TEST; - break; } input->flags = MEDIA_ENT_FL_CONNECTOR; @@ -1431,6 +1433,11 @@ err: return ret; } +static const char * const tvp5150_test_patterns[2] = { + "Disabled", + "Black screen" +}; + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { @@ -1488,7 +1495,7 @@ static int tvp5150_probe(struct i2c_client *c, core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = TVP5150_COMPOSITE1; - core->enable = 1; + core->enable = true; v4l2_ctrl_handler_init(&core->hdl, 5); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, @@ -1502,6 +1509,10 @@ static int tvp5150_probe(struct i2c_client *c, v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_PIXEL_RATE, 27000000, 27000000, 1, 27000000); + v4l2_ctrl_new_std_menu_items(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(tvp5150_test_patterns), + 0, 0, tvp5150_test_patterns); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index d30865222082..c852a35e916e 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -25,9 +25,8 @@ #define TVP5150_COMPOSITE0 0 #define TVP5150_COMPOSITE1 1 #define TVP5150_SVIDEO 2 -#define TVP5150_GENERATOR 3 -#define TVP5150_INPUT_NUM 4 +#define TVP5150_INPUT_NUM 3 /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 -- cgit v1.2.3 From 1f4522400e7e49464da5e584a463bd315283790f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 11 Feb 2016 12:28:55 -0200 Subject: [media] [for,v4.5] media.h: increase the spacing between function ranges Each function range is quite narrow and especially for connectors this will pose a problem. Increase the function ranges while we still can and move the connector range to the end so that range is practically limitless. [mchehab@osg.samsung.com: Rebased to apply at Linus tree] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..8b87bddecf1c 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -72,21 +72,21 @@ struct media_device_info { #define MEDIA_ENT_F_DTV_NET_DECAP (MEDIA_ENT_F_BASE + 4) /* - * Connectors + * I/O entities */ -/* It is a responsibility of the entity drivers to add connectors and links */ -#define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 21) -#define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 22) -#define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 23) -/* For internal test signal generators and other debug connectors */ -#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 24) +#define MEDIA_ENT_F_IO_DTV (MEDIA_ENT_F_BASE + 1001) +#define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 1002) +#define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 1003) /* - * I/O entities + * Connectors */ -#define MEDIA_ENT_F_IO_DTV (MEDIA_ENT_F_BASE + 31) -#define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) -#define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) +/* It is a responsibility of the entity drivers to add connectors and links */ +#define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 10001) +#define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 10002) +#define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 10003) +/* For internal test signal generators and other debug connectors */ +#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 10004) /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and -- cgit v1.2.3 From 9727a9545adec59f4bccb83d1a709711f4acf242 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 15:44:31 -0200 Subject: [media] media.h: get rid of MEDIA_ENT_F_CONN_TEST Defining it as a connector was a bad idea. Remove it while it is not too late. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 4 ---- drivers/media/usb/au0828/au0828-video.c | 3 +-- include/uapi/linux/media.h | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 1af384250910..0ee0f3386cdf 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -56,10 +56,6 @@ MEDIA_ENT_F_CONN_COMPOSITE Connector for a RGB composite signal. - - MEDIA_ENT_F_CONN_TEST - Connector for a test generator. - MEDIA_ENT_F_CAM_SENSOR Camera video sensor entity. diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 8c54fd21022e..a13625722848 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1843,8 +1843,7 @@ static void au0828_analog_create_entities(struct au0828_dev *dev) ent->function = MEDIA_ENT_F_CONN_RF; break; default: /* AU0828_VMUX_DEBUG */ - ent->function = MEDIA_ENT_F_CONN_TEST; - break; + continue; } ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 8b87bddecf1c..f0328524be6e 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -85,8 +85,6 @@ struct media_device_info { #define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 10001) #define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 10002) #define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 10003) -/* For internal test signal generators and other debug connectors */ -#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 10004) /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and -- cgit v1.2.3 From 360104e3b8485f4923ffc202c1c2b36841de673c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Feb 2016 15:44:31 -0200 Subject: [media] media.h: get rid of MEDIA_ENT_F_CONN_TEST Defining it as a connector was a bad idea. Remove it while it is not too late. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 4 ---- drivers/media/v4l2-core/v4l2-mc.c | 1 - include/uapi/linux/media.h | 2 -- 3 files changed, 7 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 751c3d027103..8b4fa39cf611 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -56,10 +56,6 @@ MEDIA_ENT_F_CONN_COMPOSITE Connector for a RGB composite signal. - - MEDIA_ENT_F_CONN_TEST - Connector for a test generator. - MEDIA_ENT_F_CAM_SENSOR Camera video sensor entity. diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 9d79d599d979..a7f41b323522 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -241,7 +241,6 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) break; case MEDIA_ENT_F_CONN_SVIDEO: case MEDIA_ENT_F_CONN_COMPOSITE: - case MEDIA_ENT_F_CONN_TEST: ret = media_create_pad_link(entity, 0, decoder, DEMOD_PAD_IF_INPUT, flags); diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index c9eb42a6c021..7113b1a8cb4e 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -78,8 +78,6 @@ struct media_device_info { #define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 21) #define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 22) #define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 23) -/* For internal test signal generators and other debug connectors */ -#define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 24) /* * I/O entities -- cgit v1.2.3 From 21cf734c79e6c741dcdf383dbaef3b551b931568 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Feb 2016 13:56:26 -0200 Subject: [media] siano: firmware buffer is too small As pointed by KASAN: BUG: KASAN: slab-out-of-bounds in memcpy+0x1d/0x40 at addr ffff880000038d8c Read of size 128 by task systemd-udevd/2536 page:ffffea0000000800 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0 flags: 0xffff8000004000(head) page dumped because: kasan: bad access detected CPU: 1 PID: 2536 Comm: systemd-udevd Not tainted 4.5.0-rc3+ #47 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 ffff880000038d8c ffff8803b0f1f1e8 ffffffff81933901 0000000000000080 ffff8803b0f1f280 ffff8803b0f1f270 ffffffff815602c5 ffffffff8284cf93 ffffffff822ddc00 0000000000000282 0000000000000001 ffff88009c7c6000 Call Trace: [] dump_stack+0x85/0xc4 [] kasan_report_error+0x525/0x550 [] kasan_report+0x39/0x40 [] memcpy+0x1d/0x40 [] smscore_set_device_mode+0xee0/0x2560 [smsmdtv] Such error happens at the memcpy code below: 0x4bc0 is in smscore_set_device_mode (drivers/media/common/siano/smscoreapi.c:975). 970 sizeof(u32) + payload_size)); 971 972 data_msg->mem_addr = mem_address; 973 memcpy(data_msg->payload, payload, payload_size); 974 975 rc = smscore_sendrequest_and_wait(coredev, data_msg, 976 data_msg->x_msg_header.msg_length, 977 &coredev->data_download_done); 978 979 payload += payload_size; The problem is that the Siano driver uses a header to store the firmware, with requires a few more bytes than allocated. Tested with: PCTV 77e (2013:0257) Hauppauge WinTV MiniStick (2040:5510) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smscoreapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 2a8d9a36d6f0..f3a42834d7d6 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -1167,8 +1167,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, return rc; } pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size); - fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), - GFP_KERNEL | GFP_DMA); + fw_buf = kmalloc(ALIGN(fw->size + sizeof(struct sms_firmware), + SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA); if (!fw_buf) { pr_err("failed to allocate firmware buffer\n"); rc = -ENOMEM; -- cgit v1.2.3 From dd47fbd40e6ea6884e295e13a2e50b0894258fdf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Feb 2016 07:22:27 -0200 Subject: [media] smsusb: don't sleep while atomic smscore_getbuffer() calls internally wait_event(), with can sleep. As smsusb_onresponse() is called on interrupt context, this causes the following warning: BUG: sleeping function called from invalid context at drivers/media/common/siano/smscoreapi.c:1653 in_atomic(): 1, irqs_disabled(): 1, pid: 11084, name: systemd-udevd INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [< (null)>] (null) hardirqs last disabled at (0): [] copy_process.part.7+0x10e7/0x56d0 softirqs last enabled at (0): [] copy_process.part.7+0x1183/0x56d0 softirqs last disabled at (0): [< (null)>] (null) CPU: 2 PID: 11084 Comm: systemd-udevd Tainted: G B W 4.5.0-rc3+ #47 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 0000000000000000 ffff8803c6907a80 ffffffff81933901 ffff8802bd916000 ffff8802bd9165c8 ffff8803c6907aa8 ffffffff811c6af5 ffff8802bd916000 ffffffffa0ce9b60 0000000000000675 ffff8803c6907ae8 ffffffff811c6ce5 Call Trace: [] dump_stack+0x85/0xc4 [] ___might_sleep+0x245/0x3a0 [] __might_sleep+0x95/0x1a0 [] ? list_add_locked+0xca/0x140 [smsmdtv] [] smscore_getbuffer+0x7d/0x120 [smsmdtv] [] ? trace_hardirqs_off+0xd/0x10 [] ? smscore_sendrequest_and_wait.isra.5+0x120/0x120 [smsmdtv] [] ? list_add_locked+0xca/0x140 [smsmdtv] [] ? smscore_putbuffer+0x3a/0x40 [smsmdtv] [] smsusb_submit_urb+0x2ec/0x4f0 [smsusb] [] smsusb_onresponse+0x476/0x720 [smsusb] Let's add a work queue to handle the bottom half, preventing this problem. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/siano/smsusb.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 8abbd3cc8eba..9fac9779f616 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -51,6 +51,9 @@ struct smsusb_urb_t { struct smsusb_device_t *dev; struct urb urb; + + /* For the bottom half */ + struct work_struct wq; }; struct smsusb_device_t { @@ -70,6 +73,18 @@ struct smsusb_device_t { static int smsusb_submit_urb(struct smsusb_device_t *dev, struct smsusb_urb_t *surb); +/** + * Completing URB's callback handler - bottom half (proccess context) + * submits the URB prepared on smsusb_onresponse() + */ +static void do_submit_urb(struct work_struct *work) +{ + struct smsusb_urb_t *surb = container_of(work, struct smsusb_urb_t, wq); + struct smsusb_device_t *dev = surb->dev; + + smsusb_submit_urb(dev, surb); +} + /** * Completing URB's callback handler - top half (interrupt context) * adds completing sms urb to the global surbs list and activtes the worker @@ -138,13 +153,15 @@ static void smsusb_onresponse(struct urb *urb) exit_and_resubmit: - smsusb_submit_urb(dev, surb); + INIT_WORK(&surb->wq, do_submit_urb); + schedule_work(&surb->wq); } static int smsusb_submit_urb(struct smsusb_device_t *dev, struct smsusb_urb_t *surb) { if (!surb->cb) { + /* This function can sleep */ surb->cb = smscore_getbuffer(dev->coredev); if (!surb->cb) { pr_err("smscore_getbuffer(...) returned NULL\n"); -- cgit v1.2.3 From 3d0ccad0dbbd51b64d307c64cc163002334afbfa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Feb 2016 08:07:43 -0200 Subject: [media] siano: use generic function to create MC device Currently, it is initializing the driver name using the wrong name ("usb"). Use the generic function, as its logic works best, and avoids repeating the very same code everywhere. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/siano/smsusb.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 9fac9779f616..4dac499ed28e 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -27,6 +27,7 @@ along with this program. If not, see . #include #include #include +#include #include "sms-cards.h" #include "smsendian.h" @@ -366,20 +367,10 @@ static void *siano_media_device_register(struct smsusb_device_t *dev, struct sms_board *board = sms_get_board(board_id); int ret; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + mdev = v4l2_mc_usb_media_device_init(udev, board->name); if (!mdev) return NULL; - mdev->dev = &udev->dev; - strlcpy(mdev->model, board->name, sizeof(mdev->model)); - if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); - strcpy(mdev->bus_info, udev->devpath); - mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - mdev->driver_version = LINUX_VERSION_CODE; - - media_device_init(mdev); - ret = media_device_register(mdev); if (ret) { media_device_cleanup(mdev); -- cgit v1.2.3 From c574b759138474d2fbe7e437c529010b7f4db2f1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 16 Feb 2016 18:03:21 -0200 Subject: [media] v4l2-async: Don't fail if registered_async isn't implemented After sub-dev registration in v4l2_async_test_notify(), the v4l2-async core calls the registered_async callback but if a sub-dev driver does not implement it, v4l2_subdev_call() will return a -ENOIOCTLCMD which should not be considered an error. Reported-by: Benoit Parrot Signed-off-by: Javier Martinez Canillas Tested-by: Benoit Parrot Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 716bfd47daab..a4b224d92572 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -120,7 +120,7 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, } ret = v4l2_subdev_call(sd, core, registered_async); - if (ret < 0) { + if (ret < 0 && ret != -ENOIOCTLCMD) { if (notifier->unbind) notifier->unbind(notifier, sd, asd); return ret; -- cgit v1.2.3 From bb07df8ae18b42a8c5aea715fae82938b467ff9d Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Thu, 4 Feb 2016 21:09:23 -0200 Subject: [media] pvrusb2: correctly handling failed thread run Since kthread_run returns -ENOMEM if failed, it needs to be checked whether it is error, not whether it is null. Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c index fd888a604462..c45f30715dcd 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-context.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c @@ -196,7 +196,7 @@ int pvr2_context_global_init(void) pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func, NULL, "pvrusb2-context"); - return (pvr2_context_thread_ptr ? 0 : -ENOMEM); + return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0; } -- cgit v1.2.3 From 76880b4015f7bdbe73bf2c07e42ef0ba7a343d3e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Feb 2016 09:14:12 -0200 Subject: [media] usb/cpia2_core: clean up a min_t() cast It makes sense to make the min_t() cast unsigned here since we don't really want negative sizes. Making it signed causes a static checker warning in Smatch. Smatch knows "fw->size - i" is positive but it doesn't know that fw->size is less than INT_MAX so in theory casting it to int might lead to a negative. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cpia2/cpia2_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index 187012ce444b..0310fd6ed103 100644 --- a/drivers/media/usb/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -923,7 +923,7 @@ static int apply_vp_patch(struct camera_data *cam) /* ... followed by the data payload */ for (i = 2; i < fw->size; i += 64) { cmd.start = 0x0C; /* Data */ - cmd.reg_count = min_t(int, 64, fw->size - i); + cmd.reg_count = min_t(uint, 64, fw->size - i); memcpy(cmd.buffer.block_data, &fw->data[i], cmd.reg_count); cpia2_send_command(cam, &cmd); } -- cgit v1.2.3 From b339a72e04a62f0b1882c43492fc712f1176b3e6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Feb 2016 09:32:25 -0200 Subject: [media] adv7511: TX_EDID_PRESENT is still 1 after a disconnect The V4L2_CID_TX_EDID_PRESENT control reports if an EDID is present. The adv7511 however still reported the EDID present after disconnecting the HDMI cable. Fix the logic regarding this control. And when the EDID is disconnected also call ADV7511_EDID_DETECT to notify the bridge driver. This was also missing. Signed-off-by: Hans Verkuil Cc: # for v3.12 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index a9ed5337df2d..bd822f032b08 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1175,12 +1175,23 @@ static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, in } } +static void adv7511_notify_no_edid(struct v4l2_subdev *sd) +{ + struct adv7511_state *state = get_adv7511_state(sd); + struct adv7511_edid_detect ed; + + /* We failed to read the EDID, so send an event for this. */ + ed.present = false; + ed.segment = adv7511_rd(sd, 0xc4); + v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0); +} + static void adv7511_edid_handler(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); struct v4l2_subdev *sd = &state->sd; - struct adv7511_edid_detect ed; v4l2_dbg(1, debug, sd, "%s:\n", __func__); @@ -1205,9 +1216,7 @@ static void adv7511_edid_handler(struct work_struct *work) } /* We failed to read the EDID, so send an event for this. */ - ed.present = false; - ed.segment = adv7511_rd(sd, 0xc4); - v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); + adv7511_notify_no_edid(sd); v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); } @@ -1278,7 +1287,6 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) /* update read only ctrls */ v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); - v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); @@ -1308,6 +1316,7 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) } adv7511_s_power(sd, false); memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); + adv7511_notify_no_edid(sd); } } @@ -1384,6 +1393,7 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) } /* one more segment read ok */ state->edid.segments = segment + 1; + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1); if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { /* Request next EDID segment */ v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); @@ -1403,7 +1413,6 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) ed.present = true; ed.segment = 0; state->edid_detect_counter++; - v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); return ed.present; } -- cgit v1.2.3 From 9322fe0f92385eba582b8679edd89558114dd855 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Feb 2016 05:40:56 -0200 Subject: [media] timblogiw: move to staging in preparation for removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Timberdale FPGA video driver has not seen any real development since 2011 (and very little before that). One of the problems with the timblogiw driver is that it uses videobuf instead of the newer vb2 framework. The long term goal is to either convert or remove any driver still using videobuf. Since none of the core v4l developers has the hardware, we cannot convert it ourselves. As far as I can tell it was only used in an Intel demo board in 2009 using Meego: http://www.chinait.com/intelcontent/intelprc/admin/PDFFile/20106411545.pdf which has since been superseded. Moving this driver to staging is the first step towards removal. After 2 or 3 kernel cycles it will be removed altogether unless someone steps up to clean up this driver. Signed-off-by: Hans Verkuil Acked-by: Richard Röjfors Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 9 - drivers/media/platform/Makefile | 1 - drivers/media/platform/timblogiw.c | 870 --------------------------------- drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/timb/Kconfig | 11 + drivers/staging/media/timb/Makefile | 1 + drivers/staging/media/timb/timblogiw.c | 870 +++++++++++++++++++++++++++++++++ 8 files changed, 885 insertions(+), 880 deletions(-) delete mode 100644 drivers/media/platform/timblogiw.c create mode 100644 drivers/staging/media/timb/Kconfig create mode 100644 drivers/staging/media/timb/Makefile create mode 100644 drivers/staging/media/timb/timblogiw.c diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index fd4fcd5a7184..625ea4f81747 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -54,15 +54,6 @@ config VIDEO_VIU Say Y here if you want to enable VIU device on MPC5121e Rev2+. In doubt, say N. -config VIDEO_TIMBERDALE - tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && HAS_DMA - depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST - select VIDEO_ADV7180 - select VIDEOBUF_DMA_CONTIG - ---help--- - Add support for the Video In peripherial of the timberdale FPGA. - config VIDEO_M32R_AR tristate "AR devices" depends on VIDEO_V4L2 diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 028a7233096b..bbb7bd1eb268 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -2,7 +2,6 @@ # Makefile for the video capture/playback device drivers. # -obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c deleted file mode 100644 index 113c9f3c0b3e..000000000000 --- a/drivers/media/platform/timblogiw.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * timblogiw.c timberdale FPGA LogiWin Video In driver - * Copyright (c) 2009-2010 Intel Corporation - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Timberdale FPGA LogiWin Video In - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "timb-video" - -#define TIMBLOGIWIN_NAME "Timberdale Video-In" -#define TIMBLOGIW_VERSION_CODE 0x04 - -#define TIMBLOGIW_LINES_PER_DESC 44 -#define TIMBLOGIW_MAX_VIDEO_MEM 16 - -#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name) - - -struct timblogiw { - struct video_device video_dev; - struct v4l2_device v4l2_dev; /* mutual exclusion */ - struct mutex lock; - struct device *dev; - struct timb_video_platform_data pdata; - struct v4l2_subdev *sd_enc; /* encoder */ - bool opened; -}; - -struct timblogiw_tvnorm { - v4l2_std_id std; - u16 width; - u16 height; - u8 fps; -}; - -struct timblogiw_fh { - struct videobuf_queue vb_vidq; - struct timblogiw_tvnorm const *cur_norm; - struct list_head capture; - struct dma_chan *chan; - spinlock_t queue_lock; /* mutual exclusion */ - unsigned int frame_count; -}; - -struct timblogiw_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - struct scatterlist sg[16]; - dma_cookie_t cookie; - struct timblogiw_fh *fh; -}; - -static const struct timblogiw_tvnorm timblogiw_tvnorms[] = { - { - .std = V4L2_STD_PAL, - .width = 720, - .height = 576, - .fps = 25 - }, - { - .std = V4L2_STD_NTSC, - .width = 720, - .height = 480, - .fps = 30 - } -}; - -static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) -{ - return norm->width * 2; -} - - -static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) -{ - return norm->height * timblogiw_bytes_per_line(norm); -} - -static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std) -{ - int i; - for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) - if (timblogiw_tvnorms[i].std & std) - return timblogiw_tvnorms + i; - - /* default to first element */ - return timblogiw_tvnorms; -} - -static void timblogiw_dma_cb(void *data) -{ - struct timblogiw_buffer *buf = data; - struct timblogiw_fh *fh = buf->fh; - struct videobuf_buffer *vb = &buf->vb; - - spin_lock(&fh->queue_lock); - - /* mark the transfer done */ - buf->cookie = -1; - - fh->frame_count++; - - if (vb->state != VIDEOBUF_ERROR) { - list_del(&vb->queue); - v4l2_get_timestamp(&vb->ts); - vb->field_count = fh->frame_count * 2; - vb->state = VIDEOBUF_DONE; - - wake_up(&vb->done); - } - - if (!list_empty(&fh->capture)) { - vb = list_entry(fh->capture.next, struct videobuf_buffer, - queue); - vb->state = VIDEOBUF_ACTIVE; - } - - spin_unlock(&fh->queue_lock); -} - -static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) -{ - return chan->chan_id == (uintptr_t)filter_param; -} - -/* IOCTL functions */ - -static int timblogiw_g_fmt(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s entry\n", __func__); - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - mutex_lock(&lw->lock); - - format->fmt.pix.width = fh->cur_norm->width; - format->fmt.pix.height = fh->cur_norm->height; - format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm); - format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm); - format->fmt.pix.field = V4L2_FIELD_NONE; - - mutex_unlock(&lw->lock); - - return 0; -} - -static int timblogiw_try_fmt(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct video_device *vdev = video_devdata(file); - struct v4l2_pix_format *pix = &format->fmt.pix; - - dev_dbg(&vdev->dev, - "%s - width=%d, height=%d, pixelformat=%d, field=%d\n" - "bytes per line %d, size image: %d, colorspace: %d\n", - __func__, - pix->width, pix->height, pix->pixelformat, pix->field, - pix->bytesperline, pix->sizeimage, pix->colorspace); - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (pix->field != V4L2_FIELD_NONE) - return -EINVAL; - - if (pix->pixelformat != V4L2_PIX_FMT_UYVY) - return -EINVAL; - - return 0; -} - -static int timblogiw_s_fmt(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh = priv; - struct v4l2_pix_format *pix = &format->fmt.pix; - int err; - - mutex_lock(&lw->lock); - - err = timblogiw_try_fmt(file, priv, format); - if (err) - goto out; - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - dev_err(&vdev->dev, "%s queue busy\n", __func__); - err = -EBUSY; - goto out; - } - - pix->width = fh->cur_norm->width; - pix->height = fh->cur_norm->height; - -out: - mutex_unlock(&lw->lock); - return err; -} - -static int timblogiw_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct video_device *vdev = video_devdata(file); - - dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); - strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); - snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - - return 0; -} - -static int timblogiw_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct video_device *vdev = video_devdata(file); - - dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index); - - if (fmt->index != 0) - return -EINVAL; - memset(fmt, 0, sizeof(*fmt)); - fmt->index = 0; - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strncpy(fmt->description, "4:2:2, packed, YUYV", - sizeof(fmt->description)-1); - fmt->pixelformat = V4L2_PIX_FMT_UYVY; - - return 0; -} - -static int timblogiw_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *sp) -{ - struct timblogiw_fh *fh = priv; - struct v4l2_captureparm *cp = &sp->parm.capture; - - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = 1; - cp->timeperframe.denominator = fh->cur_norm->fps; - - return 0; -} - -static int timblogiw_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_reqbufs(&fh->vb_vidq, rb); -} - -static int timblogiw_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_querybuf(&fh->vb_vidq, b); -} - -static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_qbuf(&fh->vb_vidq, b); -} - -static int timblogiw_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); -} - -static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - *std = fh->cur_norm->std; - return 0; -} - -static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh = priv; - int err = 0; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - mutex_lock(&lw->lock); - - if (TIMBLOGIW_HAS_DECODER(lw)) - err = v4l2_subdev_call(lw->sd_enc, video, s_std, std); - - if (!err) - fh->cur_norm = timblogiw_get_norm(std); - - mutex_unlock(&lw->lock); - - return err; -} - -static int timblogiw_enuminput(struct file *file, void *priv, - struct v4l2_input *inp) -{ - struct video_device *vdev = video_devdata(file); - int i; - - dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - - if (inp->index != 0) - return -EINVAL; - - inp->index = 0; - - strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1); - inp->type = V4L2_INPUT_TYPE_CAMERA; - - inp->std = 0; - for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) - inp->std |= timblogiw_tvnorms[i].std; - - return 0; -} - -static int timblogiw_g_input(struct file *file, void *priv, - unsigned int *input) -{ - struct video_device *vdev = video_devdata(file); - - dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - - *input = 0; - - return 0; -} - -static int timblogiw_s_input(struct file *file, void *priv, unsigned int input) -{ - struct video_device *vdev = video_devdata(file); - - dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - - if (input != 0) - return -EINVAL; - return 0; -} - -static int timblogiw_streamon(struct file *file, void *priv, enum v4l2_buf_type type) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dev_dbg(&vdev->dev, "%s - No capture device\n", __func__); - return -EINVAL; - } - - fh->frame_count = 0; - return videobuf_streamon(&fh->vb_vidq); -} - -static int timblogiw_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s entry\n", __func__); - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - return videobuf_streamoff(&fh->vb_vidq); -} - -static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s entry\n", __func__); - - if (TIMBLOGIW_HAS_DECODER(lw)) - return v4l2_subdev_call(lw->sd_enc, video, querystd, std); - else { - *std = fh->cur_norm->std; - return 0; - } -} - -static int timblogiw_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = priv; - - dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__, - fsize->index, fsize->pixel_format); - - if ((fsize->index != 0) || - (fsize->pixel_format != V4L2_PIX_FMT_UYVY)) - return -EINVAL; - - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = fh->cur_norm->width; - fsize->discrete.height = fh->cur_norm->height; - - return 0; -} - -/* Video buffer functions */ - -static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct timblogiw_fh *fh = vq->priv_data; - - *size = timblogiw_frame_size(fh->cur_norm); - - if (!*count) - *count = 32; - - while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024) - (*count)--; - - return 0; -} - -static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct timblogiw_fh *fh = vq->priv_data; - struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, - vb); - unsigned int data_size = timblogiw_frame_size(fh->cur_norm); - int err = 0; - - if (vb->baddr && vb->bsize < data_size) - /* User provided buffer, but it is too small */ - return -ENOMEM; - - vb->size = data_size; - vb->width = fh->cur_norm->width; - vb->height = fh->cur_norm->height; - vb->field = field; - - if (vb->state == VIDEOBUF_NEEDS_INIT) { - int i; - unsigned int size; - unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * - timblogiw_bytes_per_line(fh->cur_norm); - dma_addr_t addr; - - sg_init_table(buf->sg, ARRAY_SIZE(buf->sg)); - - err = videobuf_iolock(vq, vb, NULL); - if (err) - goto err; - - addr = videobuf_to_dma_contig(vb); - for (i = 0, size = 0; size < data_size; i++) { - sg_dma_address(buf->sg + i) = addr + size; - size += bytes_per_desc; - sg_dma_len(buf->sg + i) = (size > data_size) ? - (bytes_per_desc - (size - data_size)) : - bytes_per_desc; - } - - vb->state = VIDEOBUF_PREPARED; - buf->cookie = -1; - buf->fh = fh; - } - - return 0; - -err: - videobuf_dma_contig_free(vq, vb); - vb->state = VIDEOBUF_NEEDS_INIT; - return err; -} - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct timblogiw_fh *fh = vq->priv_data; - struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, - vb); - struct dma_async_tx_descriptor *desc; - int sg_elems; - int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * - timblogiw_bytes_per_line(fh->cur_norm); - - sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc; - sg_elems += - (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0; - - if (list_empty(&fh->capture)) - vb->state = VIDEOBUF_ACTIVE; - else - vb->state = VIDEOBUF_QUEUED; - - list_add_tail(&vb->queue, &fh->capture); - - spin_unlock_irq(&fh->queue_lock); - - desc = dmaengine_prep_slave_sg(fh->chan, - buf->sg, sg_elems, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT); - if (!desc) { - spin_lock_irq(&fh->queue_lock); - list_del_init(&vb->queue); - vb->state = VIDEOBUF_PREPARED; - return; - } - - desc->callback_param = buf; - desc->callback = timblogiw_dma_cb; - - buf->cookie = desc->tx_submit(desc); - - spin_lock_irq(&fh->queue_lock); -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct timblogiw_fh *fh = vq->priv_data; - struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, - vb); - - videobuf_waiton(vq, vb, 0, 0); - if (buf->cookie >= 0) - dma_sync_wait(fh->chan, buf->cookie); - - videobuf_dma_contig_free(vq, vb); - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static struct videobuf_queue_ops timblogiw_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* Device Operations functions */ - -static int timblogiw_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh; - v4l2_std_id std; - dma_cap_mask_t mask; - int err = 0; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - mutex_lock(&lw->lock); - if (lw->opened) { - err = -EBUSY; - goto out; - } - - if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) { - struct i2c_adapter *adapt; - - /* find the video decoder */ - adapt = i2c_get_adapter(lw->pdata.i2c_adapter); - if (!adapt) { - dev_err(&vdev->dev, "No I2C bus #%d\n", - lw->pdata.i2c_adapter); - err = -ENODEV; - goto out; - } - - /* now find the encoder */ - lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt, - lw->pdata.encoder.info, NULL); - - i2c_put_adapter(adapt); - - if (!lw->sd_enc) { - dev_err(&vdev->dev, "Failed to get encoder: %s\n", - lw->pdata.encoder.module_name); - err = -ENODEV; - goto out; - } - } - - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (!fh) { - err = -ENOMEM; - goto out; - } - - fh->cur_norm = timblogiw_tvnorms; - timblogiw_querystd(file, fh, &std); - fh->cur_norm = timblogiw_get_norm(std); - - INIT_LIST_HEAD(&fh->capture); - spin_lock_init(&fh->queue_lock); - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_PRIVATE, mask); - - /* find the DMA channel */ - fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn, - (void *)(uintptr_t)lw->pdata.dma_channel); - if (!fh->chan) { - dev_err(&vdev->dev, "Failed to get DMA channel\n"); - kfree(fh); - err = -ENODEV; - goto out; - } - - file->private_data = fh; - videobuf_queue_dma_contig_init(&fh->vb_vidq, - &timblogiw_video_qops, lw->dev, &fh->queue_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct timblogiw_buffer), fh, NULL); - - lw->opened = true; -out: - mutex_unlock(&lw->lock); - - return err; -} - -static int timblogiw_close(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw *lw = video_get_drvdata(vdev); - struct timblogiw_fh *fh = file->private_data; - - dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - dma_release_channel(fh->chan); - - kfree(fh); - - mutex_lock(&lw->lock); - lw->opened = false; - mutex_unlock(&lw->lock); - return 0; -} - -static ssize_t timblogiw_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = file->private_data; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); -} - -static unsigned int timblogiw_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = file->private_data; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_poll_stream(file, &fh->vb_vidq, wait); -} - -static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *vdev = video_devdata(file); - struct timblogiw_fh *fh = file->private_data; - - dev_dbg(&vdev->dev, "%s: entry\n", __func__); - - return videobuf_mmap_mapper(&fh->vb_vidq, vma); -} - -/* Platform device functions */ - -static struct v4l2_ioctl_ops timblogiw_ioctl_ops = { - .vidioc_querycap = timblogiw_querycap, - .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt, - .vidioc_g_fmt_vid_cap = timblogiw_g_fmt, - .vidioc_try_fmt_vid_cap = timblogiw_try_fmt, - .vidioc_s_fmt_vid_cap = timblogiw_s_fmt, - .vidioc_g_parm = timblogiw_g_parm, - .vidioc_reqbufs = timblogiw_reqbufs, - .vidioc_querybuf = timblogiw_querybuf, - .vidioc_qbuf = timblogiw_qbuf, - .vidioc_dqbuf = timblogiw_dqbuf, - .vidioc_g_std = timblogiw_g_std, - .vidioc_s_std = timblogiw_s_std, - .vidioc_enum_input = timblogiw_enuminput, - .vidioc_g_input = timblogiw_g_input, - .vidioc_s_input = timblogiw_s_input, - .vidioc_streamon = timblogiw_streamon, - .vidioc_streamoff = timblogiw_streamoff, - .vidioc_querystd = timblogiw_querystd, - .vidioc_enum_framesizes = timblogiw_enum_framesizes, -}; - -static struct v4l2_file_operations timblogiw_fops = { - .owner = THIS_MODULE, - .open = timblogiw_open, - .release = timblogiw_close, - .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .mmap = timblogiw_mmap, - .read = timblogiw_read, - .poll = timblogiw_poll, -}; - -static struct video_device timblogiw_template = { - .name = TIMBLOGIWIN_NAME, - .fops = &timblogiw_fops, - .ioctl_ops = &timblogiw_ioctl_ops, - .release = video_device_release_empty, - .minor = -1, - .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC -}; - -static int timblogiw_probe(struct platform_device *pdev) -{ - int err; - struct timblogiw *lw = NULL; - struct timb_video_platform_data *pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "No platform data\n"); - err = -EINVAL; - goto err; - } - - if (!pdata->encoder.module_name) - dev_info(&pdev->dev, "Running without decoder\n"); - - lw = devm_kzalloc(&pdev->dev, sizeof(*lw), GFP_KERNEL); - if (!lw) { - err = -ENOMEM; - goto err; - } - - if (pdev->dev.parent) - lw->dev = pdev->dev.parent; - else - lw->dev = &pdev->dev; - - memcpy(&lw->pdata, pdata, sizeof(lw->pdata)); - - mutex_init(&lw->lock); - - lw->video_dev = timblogiw_template; - - strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name)); - err = v4l2_device_register(NULL, &lw->v4l2_dev); - if (err) - goto err; - - lw->video_dev.v4l2_dev = &lw->v4l2_dev; - - platform_set_drvdata(pdev, lw); - video_set_drvdata(&lw->video_dev, lw); - - err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0); - if (err) { - dev_err(&pdev->dev, "Error reg video: %d\n", err); - goto err_request; - } - - return 0; - -err_request: - v4l2_device_unregister(&lw->v4l2_dev); -err: - dev_err(&pdev->dev, "Failed to register: %d\n", err); - - return err; -} - -static int timblogiw_remove(struct platform_device *pdev) -{ - struct timblogiw *lw = platform_get_drvdata(pdev); - - video_unregister_device(&lw->video_dev); - - v4l2_device_unregister(&lw->v4l2_dev); - - return 0; -} - -static struct platform_driver timblogiw_platform_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = timblogiw_probe, - .remove = timblogiw_remove, -}; - -module_platform_driver(timblogiw_platform_driver); - -MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); -MODULE_AUTHOR("Pelagicore AB "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 14697686eea5..d48a5c29c417 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -31,6 +31,8 @@ source "drivers/staging/media/mn88473/Kconfig" source "drivers/staging/media/omap4iss/Kconfig" +source "drivers/staging/media/timb/Kconfig" + # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 34c557b4c6d6..fb94f045c40f 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_DVB_MN88473) += mn88473/ +obj-$(CONFIG_VIDEO_TIMBERDALE) += timb/ diff --git a/drivers/staging/media/timb/Kconfig b/drivers/staging/media/timb/Kconfig new file mode 100644 index 000000000000..e413fecc1e67 --- /dev/null +++ b/drivers/staging/media/timb/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_TIMBERDALE + tristate "Support for timberdale Video In/LogiWIN" + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && HAS_DMA + depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST + select VIDEO_ADV7180 + select VIDEOBUF_DMA_CONTIG + ---help--- + Add support for the Video In peripherial of the timberdale FPGA. + + This driver is deprecated and will be removed soon unless someone + will start the work to convert this driver to the vb2 framework. diff --git a/drivers/staging/media/timb/Makefile b/drivers/staging/media/timb/Makefile new file mode 100644 index 000000000000..4c989c23a0e0 --- /dev/null +++ b/drivers/staging/media/timb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o diff --git a/drivers/staging/media/timb/timblogiw.c b/drivers/staging/media/timb/timblogiw.c new file mode 100644 index 000000000000..113c9f3c0b3e --- /dev/null +++ b/drivers/staging/media/timb/timblogiw.c @@ -0,0 +1,870 @@ +/* + * timblogiw.c timberdale FPGA LogiWin Video In driver + * Copyright (c) 2009-2010 Intel Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * Timberdale FPGA LogiWin Video In + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "timb-video" + +#define TIMBLOGIWIN_NAME "Timberdale Video-In" +#define TIMBLOGIW_VERSION_CODE 0x04 + +#define TIMBLOGIW_LINES_PER_DESC 44 +#define TIMBLOGIW_MAX_VIDEO_MEM 16 + +#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name) + + +struct timblogiw { + struct video_device video_dev; + struct v4l2_device v4l2_dev; /* mutual exclusion */ + struct mutex lock; + struct device *dev; + struct timb_video_platform_data pdata; + struct v4l2_subdev *sd_enc; /* encoder */ + bool opened; +}; + +struct timblogiw_tvnorm { + v4l2_std_id std; + u16 width; + u16 height; + u8 fps; +}; + +struct timblogiw_fh { + struct videobuf_queue vb_vidq; + struct timblogiw_tvnorm const *cur_norm; + struct list_head capture; + struct dma_chan *chan; + spinlock_t queue_lock; /* mutual exclusion */ + unsigned int frame_count; +}; + +struct timblogiw_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + struct scatterlist sg[16]; + dma_cookie_t cookie; + struct timblogiw_fh *fh; +}; + +static const struct timblogiw_tvnorm timblogiw_tvnorms[] = { + { + .std = V4L2_STD_PAL, + .width = 720, + .height = 576, + .fps = 25 + }, + { + .std = V4L2_STD_NTSC, + .width = 720, + .height = 480, + .fps = 30 + } +}; + +static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) +{ + return norm->width * 2; +} + + +static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) +{ + return norm->height * timblogiw_bytes_per_line(norm); +} + +static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std) +{ + int i; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + if (timblogiw_tvnorms[i].std & std) + return timblogiw_tvnorms + i; + + /* default to first element */ + return timblogiw_tvnorms; +} + +static void timblogiw_dma_cb(void *data) +{ + struct timblogiw_buffer *buf = data; + struct timblogiw_fh *fh = buf->fh; + struct videobuf_buffer *vb = &buf->vb; + + spin_lock(&fh->queue_lock); + + /* mark the transfer done */ + buf->cookie = -1; + + fh->frame_count++; + + if (vb->state != VIDEOBUF_ERROR) { + list_del(&vb->queue); + v4l2_get_timestamp(&vb->ts); + vb->field_count = fh->frame_count * 2; + vb->state = VIDEOBUF_DONE; + + wake_up(&vb->done); + } + + if (!list_empty(&fh->capture)) { + vb = list_entry(fh->capture.next, struct videobuf_buffer, + queue); + vb->state = VIDEOBUF_ACTIVE; + } + + spin_unlock(&fh->queue_lock); +} + +static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) +{ + return chan->chan_id == (uintptr_t)filter_param; +} + +/* IOCTL functions */ + +static int timblogiw_g_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + mutex_lock(&lw->lock); + + format->fmt.pix.width = fh->cur_norm->width; + format->fmt.pix.height = fh->cur_norm->height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm); + format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm); + format->fmt.pix.field = V4L2_FIELD_NONE; + + mutex_unlock(&lw->lock); + + return 0; +} + +static int timblogiw_try_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_pix_format *pix = &format->fmt.pix; + + dev_dbg(&vdev->dev, + "%s - width=%d, height=%d, pixelformat=%d, field=%d\n" + "bytes per line %d, size image: %d, colorspace: %d\n", + __func__, + pix->width, pix->height, pix->pixelformat, pix->field, + pix->bytesperline, pix->sizeimage, pix->colorspace); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (pix->field != V4L2_FIELD_NONE) + return -EINVAL; + + if (pix->pixelformat != V4L2_PIX_FMT_UYVY) + return -EINVAL; + + return 0; +} + +static int timblogiw_s_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + struct v4l2_pix_format *pix = &format->fmt.pix; + int err; + + mutex_lock(&lw->lock); + + err = timblogiw_try_fmt(file, priv, format); + if (err) + goto out; + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dev_err(&vdev->dev, "%s queue busy\n", __func__); + err = -EBUSY; + goto out; + } + + pix->width = fh->cur_norm->width; + pix->height = fh->cur_norm->height; + +out: + mutex_unlock(&lw->lock); + return err; +} + +static int timblogiw_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); + strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int timblogiw_enum_fmt(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index); + + if (fmt->index != 0) + return -EINVAL; + memset(fmt, 0, sizeof(*fmt)); + fmt->index = 0; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strncpy(fmt->description, "4:2:2, packed, YUYV", + sizeof(fmt->description)-1); + fmt->pixelformat = V4L2_PIX_FMT_UYVY; + + return 0; +} + +static int timblogiw_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct timblogiw_fh *fh = priv; + struct v4l2_captureparm *cp = &sp->parm.capture; + + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; + cp->timeperframe.denominator = fh->cur_norm->fps; + + return 0; +} + +static int timblogiw_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_reqbufs(&fh->vb_vidq, rb); +} + +static int timblogiw_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_querybuf(&fh->vb_vidq, b); +} + +static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_qbuf(&fh->vb_vidq, b); +} + +static int timblogiw_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); +} + +static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + *std = fh->cur_norm->std; + return 0; +} + +static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + + if (TIMBLOGIW_HAS_DECODER(lw)) + err = v4l2_subdev_call(lw->sd_enc, video, s_std, std); + + if (!err) + fh->cur_norm = timblogiw_get_norm(std); + + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_enuminput(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct video_device *vdev = video_devdata(file); + int i; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (inp->index != 0) + return -EINVAL; + + inp->index = 0; + + strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1); + inp->type = V4L2_INPUT_TYPE_CAMERA; + + inp->std = 0; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + inp->std |= timblogiw_tvnorms[i].std; + + return 0; +} + +static int timblogiw_g_input(struct file *file, void *priv, + unsigned int *input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + *input = 0; + + return 0; +} + +static int timblogiw_s_input(struct file *file, void *priv, unsigned int input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (input != 0) + return -EINVAL; + return 0; +} + +static int timblogiw_streamon(struct file *file, void *priv, enum v4l2_buf_type type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_dbg(&vdev->dev, "%s - No capture device\n", __func__); + return -EINVAL; + } + + fh->frame_count = 0; + return videobuf_streamon(&fh->vb_vidq); +} + +static int timblogiw_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return videobuf_streamoff(&fh->vb_vidq); +} + +static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (TIMBLOGIW_HAS_DECODER(lw)) + return v4l2_subdev_call(lw->sd_enc, video, querystd, std); + else { + *std = fh->cur_norm->std; + return 0; + } +} + +static int timblogiw_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__, + fsize->index, fsize->pixel_format); + + if ((fsize->index != 0) || + (fsize->pixel_format != V4L2_PIX_FMT_UYVY)) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fh->cur_norm->width; + fsize->discrete.height = fh->cur_norm->height; + + return 0; +} + +/* Video buffer functions */ + +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct timblogiw_fh *fh = vq->priv_data; + + *size = timblogiw_frame_size(fh->cur_norm); + + if (!*count) + *count = 32; + + while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024) + (*count)--; + + return 0; +} + +static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + unsigned int data_size = timblogiw_frame_size(fh->cur_norm); + int err = 0; + + if (vb->baddr && vb->bsize < data_size) + /* User provided buffer, but it is too small */ + return -ENOMEM; + + vb->size = data_size; + vb->width = fh->cur_norm->width; + vb->height = fh->cur_norm->height; + vb->field = field; + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + int i; + unsigned int size; + unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + dma_addr_t addr; + + sg_init_table(buf->sg, ARRAY_SIZE(buf->sg)); + + err = videobuf_iolock(vq, vb, NULL); + if (err) + goto err; + + addr = videobuf_to_dma_contig(vb); + for (i = 0, size = 0; size < data_size; i++) { + sg_dma_address(buf->sg + i) = addr + size; + size += bytes_per_desc; + sg_dma_len(buf->sg + i) = (size > data_size) ? + (bytes_per_desc - (size - data_size)) : + bytes_per_desc; + } + + vb->state = VIDEOBUF_PREPARED; + buf->cookie = -1; + buf->fh = fh; + } + + return 0; + +err: + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; + return err; +} + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + struct dma_async_tx_descriptor *desc; + int sg_elems; + int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + + sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc; + sg_elems += + (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0; + + if (list_empty(&fh->capture)) + vb->state = VIDEOBUF_ACTIVE; + else + vb->state = VIDEOBUF_QUEUED; + + list_add_tail(&vb->queue, &fh->capture); + + spin_unlock_irq(&fh->queue_lock); + + desc = dmaengine_prep_slave_sg(fh->chan, + buf->sg, sg_elems, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!desc) { + spin_lock_irq(&fh->queue_lock); + list_del_init(&vb->queue); + vb->state = VIDEOBUF_PREPARED; + return; + } + + desc->callback_param = buf; + desc->callback = timblogiw_dma_cb; + + buf->cookie = desc->tx_submit(desc); + + spin_lock_irq(&fh->queue_lock); +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + + videobuf_waiton(vq, vb, 0, 0); + if (buf->cookie >= 0) + dma_sync_wait(fh->chan, buf->cookie); + + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static struct videobuf_queue_ops timblogiw_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/* Device Operations functions */ + +static int timblogiw_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh; + v4l2_std_id std; + dma_cap_mask_t mask; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + if (lw->opened) { + err = -EBUSY; + goto out; + } + + if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) { + struct i2c_adapter *adapt; + + /* find the video decoder */ + adapt = i2c_get_adapter(lw->pdata.i2c_adapter); + if (!adapt) { + dev_err(&vdev->dev, "No I2C bus #%d\n", + lw->pdata.i2c_adapter); + err = -ENODEV; + goto out; + } + + /* now find the encoder */ + lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt, + lw->pdata.encoder.info, NULL); + + i2c_put_adapter(adapt); + + if (!lw->sd_enc) { + dev_err(&vdev->dev, "Failed to get encoder: %s\n", + lw->pdata.encoder.module_name); + err = -ENODEV; + goto out; + } + } + + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) { + err = -ENOMEM; + goto out; + } + + fh->cur_norm = timblogiw_tvnorms; + timblogiw_querystd(file, fh, &std); + fh->cur_norm = timblogiw_get_norm(std); + + INIT_LIST_HEAD(&fh->capture); + spin_lock_init(&fh->queue_lock); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + /* find the DMA channel */ + fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn, + (void *)(uintptr_t)lw->pdata.dma_channel); + if (!fh->chan) { + dev_err(&vdev->dev, "Failed to get DMA channel\n"); + kfree(fh); + err = -ENODEV; + goto out; + } + + file->private_data = fh; + videobuf_queue_dma_contig_init(&fh->vb_vidq, + &timblogiw_video_qops, lw->dev, &fh->queue_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + sizeof(struct timblogiw_buffer), fh, NULL); + + lw->opened = true; +out: + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_close(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + dma_release_channel(fh->chan); + + kfree(fh); + + mutex_lock(&lw->lock); + lw->opened = false; + mutex_unlock(&lw->lock); + return 0; +} + +static ssize_t timblogiw_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); +} + +static unsigned int timblogiw_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_poll_stream(file, &fh->vb_vidq, wait); +} + +static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_mmap_mapper(&fh->vb_vidq, vma); +} + +/* Platform device functions */ + +static struct v4l2_ioctl_ops timblogiw_ioctl_ops = { + .vidioc_querycap = timblogiw_querycap, + .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt, + .vidioc_g_fmt_vid_cap = timblogiw_g_fmt, + .vidioc_try_fmt_vid_cap = timblogiw_try_fmt, + .vidioc_s_fmt_vid_cap = timblogiw_s_fmt, + .vidioc_g_parm = timblogiw_g_parm, + .vidioc_reqbufs = timblogiw_reqbufs, + .vidioc_querybuf = timblogiw_querybuf, + .vidioc_qbuf = timblogiw_qbuf, + .vidioc_dqbuf = timblogiw_dqbuf, + .vidioc_g_std = timblogiw_g_std, + .vidioc_s_std = timblogiw_s_std, + .vidioc_enum_input = timblogiw_enuminput, + .vidioc_g_input = timblogiw_g_input, + .vidioc_s_input = timblogiw_s_input, + .vidioc_streamon = timblogiw_streamon, + .vidioc_streamoff = timblogiw_streamoff, + .vidioc_querystd = timblogiw_querystd, + .vidioc_enum_framesizes = timblogiw_enum_framesizes, +}; + +static struct v4l2_file_operations timblogiw_fops = { + .owner = THIS_MODULE, + .open = timblogiw_open, + .release = timblogiw_close, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = timblogiw_mmap, + .read = timblogiw_read, + .poll = timblogiw_poll, +}; + +static struct video_device timblogiw_template = { + .name = TIMBLOGIWIN_NAME, + .fops = &timblogiw_fops, + .ioctl_ops = &timblogiw_ioctl_ops, + .release = video_device_release_empty, + .minor = -1, + .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC +}; + +static int timblogiw_probe(struct platform_device *pdev) +{ + int err; + struct timblogiw *lw = NULL; + struct timb_video_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data\n"); + err = -EINVAL; + goto err; + } + + if (!pdata->encoder.module_name) + dev_info(&pdev->dev, "Running without decoder\n"); + + lw = devm_kzalloc(&pdev->dev, sizeof(*lw), GFP_KERNEL); + if (!lw) { + err = -ENOMEM; + goto err; + } + + if (pdev->dev.parent) + lw->dev = pdev->dev.parent; + else + lw->dev = &pdev->dev; + + memcpy(&lw->pdata, pdata, sizeof(lw->pdata)); + + mutex_init(&lw->lock); + + lw->video_dev = timblogiw_template; + + strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name)); + err = v4l2_device_register(NULL, &lw->v4l2_dev); + if (err) + goto err; + + lw->video_dev.v4l2_dev = &lw->v4l2_dev; + + platform_set_drvdata(pdev, lw); + video_set_drvdata(&lw->video_dev, lw); + + err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0); + if (err) { + dev_err(&pdev->dev, "Error reg video: %d\n", err); + goto err_request; + } + + return 0; + +err_request: + v4l2_device_unregister(&lw->v4l2_dev); +err: + dev_err(&pdev->dev, "Failed to register: %d\n", err); + + return err; +} + +static int timblogiw_remove(struct platform_device *pdev) +{ + struct timblogiw *lw = platform_get_drvdata(pdev); + + video_unregister_device(&lw->video_dev); + + v4l2_device_unregister(&lw->v4l2_dev); + + return 0; +} + +static struct platform_driver timblogiw_platform_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = timblogiw_probe, + .remove = timblogiw_remove, +}; + +module_platform_driver(timblogiw_platform_driver); + +MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); +MODULE_AUTHOR("Pelagicore AB "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRIVER_NAME); -- cgit v1.2.3 From 8344622781163d9fe05bd7ab9eaa0af7d13a74ec Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 08:53:28 -0200 Subject: [media] media: ti-vpe: add dependency of HAS_DMA The build of m32r allmodconfig fails with the error: drivers/media/v4l2-core/videobuf2-dma-contig.c:492:28: error: implicit declaration of function 'dma_get_cache_alignment' The build of videobuf2-dma-contig.c depends on HAS_DMA and it is correctly mentioned in the Kconfig but the symbol VIDEO_TI_CAL also selects VIDEOBUF2_DMA_CONTIG, so it is trying to compile videobuf2-dma-contig.c even though HAS_DMA is not defined. Fixes: 343e89a792a5 ("[media] media: ti-vpe: Add CAL v4l2 camera capture driver") Cc: Benoit Parrot Signed-off-by: Sudip Mukherjee Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 625ea4f81747..201f5c296a95 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -115,6 +115,7 @@ config VIDEO_TI_CAL tristate "TI CAL (Camera Adaptation Layer) driver" depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on SOC_DRA7XX || COMPILE_TEST + depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG default n ---help--- -- cgit v1.2.3 From 3e71da19f9dc22e39a755d6ae9678661abb66adc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 Feb 2016 17:51:37 -0200 Subject: [media] saa7134: Fix bytesperline not being set correctly for planar formats bytesperline should be the bytesperline for the first plane for planar formats, not that of all planes combined. This fixes a crash in xawtv caused by the wrong bpl. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1305389 Reported-and-tested-by: Stas Sergeev Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 0403b34624c1..ffa39543eb65 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1279,10 +1279,13 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.height = dev->height; f->fmt.pix.field = dev->field; f->fmt.pix.pixelformat = dev->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * dev->fmt->depth) >> 3; + if (dev->fmt->planar) + f->fmt.pix.bytesperline = f->fmt.pix.width; + else + f->fmt.pix.bytesperline = + (f->fmt.pix.width * dev->fmt->depth) / 8; f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; + (f->fmt.pix.height * f->fmt.pix.width * dev->fmt->depth) / 8; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } @@ -1358,10 +1361,13 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; f->fmt.pix.width &= ~0x03; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; + if (fmt->planar) + f->fmt.pix.bytesperline = f->fmt.pix.width; + else + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) / 8; f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; + (f->fmt.pix.height * f->fmt.pix.width * fmt->depth) / 8; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; -- cgit v1.2.3 From cedc12108b55d0c571da883a4083977af612dcce Mon Sep 17 00:00:00 2001 From: Wu-Cheng Li Date: Tue, 19 Jan 2016 05:07:09 -0200 Subject: [media] v4l: add V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME Some drivers also need a control like V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE to force an encoder key frame. Add a general V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME so the new drivers and applications can use it. Signed-off-by: Wu-Cheng Li Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/controls.xml | 8 ++++++++ drivers/media/v4l2-core/v4l2-ctrls.c | 2 ++ include/uapi/linux/v4l2-controls.h | 1 + 3 files changed, 11 insertions(+) diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 7a771492f2a5..361040e6b0f4 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -2329,6 +2329,14 @@ to search and match for the present Macroblock (MB) in the reference picture. Th vertical search range for motion estimation module in video encoder. + + + V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME  + button + Force a key frame for the next queued buffer. Applicable to encoders. +This is a general, codec-agnostic keyframe control. + + V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE  diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 130e5badd599..8b321e0aae62 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -758,6 +758,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: return "Horizontal MV Search Range"; case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: return "Vertical MV Search Range"; case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame"; /* VPX controls */ case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; @@ -998,6 +999,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: *type = V4L2_CTRL_TYPE_INTEGER; break; + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: case V4L2_CID_PAN_RESET: case V4L2_CID_TILT_RESET: case V4L2_CID_FLASH_STROBE: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 2ae5c3ea179b..b6a357a5f053 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -390,6 +390,7 @@ enum v4l2_mpeg_video_multi_slice_mode { #define V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER (V4L2_CID_MPEG_BASE+226) #define V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE (V4L2_CID_MPEG_BASE+227) #define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_MPEG_BASE+228) +#define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_MPEG_BASE+229) #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) -- cgit v1.2.3 From 5a33287e6f94ec0e1bb583ee3e5d8f841fde971e Mon Sep 17 00:00:00 2001 From: Wu-Cheng Li Date: Tue, 19 Jan 2016 05:07:10 -0200 Subject: [media] s5p-mfc: add the support of V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME There is a new control V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME to force an encoder key frame. It is the same as requesting V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME. Signed-off-by: Wu-Cheng Li Acked-by: Sylwester Nawrocki Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 0434f02a7175..034b5c1d35a1 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -211,6 +211,14 @@ static struct mfc_control controls[] = { .default_value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED, .menu_skip_mask = 0, }, + { + .id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, + .type = V4L2_CTRL_TYPE_BUTTON, + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, { .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -1423,6 +1431,10 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE: ctx->force_frame_type = ctrl->val; break; + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: + ctx->force_frame_type = + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME; + break; case V4L2_CID_MPEG_VIDEO_VBV_SIZE: p->vbv_size = ctrl->val; break; -- cgit v1.2.3 From 9662111253f1613f4f9f2688bf2c73d6ec4f9bf6 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Mon, 15 Feb 2016 18:01:42 -0200 Subject: [media] media: ti-vpe: cal: Fix syntax check warnings Fix the following sparse warnings: ti-vpe/cal.c:387:26: warning: incorrect type in return expression (different address spaces) ti-vpe/cal.c:459:26: warning: incorrect type in return expression (different address spaces) ti-vpe/cal.c:503:27: warning: incorrect type in argument 6 (different address spaces) ti-vpe/cal.c:509:47: warning: incorrect type in argument 6 (different address spaces) ti-vpe/cal.c:518:47: warning: incorrect type in argument 6 (different address spaces) ti-vpe/cal.c:526:31: warning: incorrect type in argument 6 (different address spaces) ti-vpe/cal.c:1807:24: warning: Using plain integer as NULL pointer ti-vpe/cal.c:1844:16: warning: Using plain integer as NULL pointer Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/cal.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 69ec79ba49ee..35fa1071c5b2 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -384,7 +384,7 @@ static struct cm_data *cm_create(struct cal_dev *dev) cm->base = devm_ioremap_resource(&pdev->dev, cm->res); if (IS_ERR(cm->base)) { cal_err(dev, "failed to ioremap\n"); - return cm->base; + return ERR_CAST(cm->base); } cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", @@ -456,7 +456,7 @@ static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core) cc->base = devm_ioremap_resource(&pdev->dev, cc->res); if (IS_ERR(cc->base)) { cal_err(dev, "failed to ioremap\n"); - return cc->base; + return ERR_CAST(cc->base); } cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", @@ -500,13 +500,14 @@ static void cal_quickdump_regs(struct cal_dev *dev) { cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, - dev->base, resource_size(dev->res), false); + (__force const void *)dev->base, + resource_size(dev->res), false); if (dev->ctx[0]) { cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n", &dev->ctx[0]->cc->res->start); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, - dev->ctx[0]->cc->base, + (__force const void *)dev->ctx[0]->cc->base, resource_size(dev->ctx[0]->cc->res), false); } @@ -515,7 +516,7 @@ static void cal_quickdump_regs(struct cal_dev *dev) cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n", &dev->ctx[1]->cc->res->start); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, - dev->ctx[1]->cc->base, + (__force const void *)dev->ctx[1]->cc->base, resource_size(dev->ctx[1]->cc->res), false); } @@ -523,7 +524,7 @@ static void cal_quickdump_regs(struct cal_dev *dev) cal_info(dev, "CAMERRX_Control Registers @ %pa:\n", &dev->cm->res->start); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, - dev->cm->base, + (__force const void *)dev->cm->base, resource_size(dev->cm->res), false); } @@ -1804,7 +1805,7 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst) ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) - return 0; + return NULL; /* save the cal_dev * for future ref */ ctx->dev = dev; @@ -1841,7 +1842,7 @@ free_hdl: unreg_dev: v4l2_device_unregister(&ctx->v4l2_dev); err_exit: - return 0; + return NULL; } static int cal_probe(struct platform_device *pdev) -- cgit v1.2.3 From d65fae92f9a2862d73293cab6c427c40cff71f70 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Nov 2015 22:02:00 -0200 Subject: [media] v4l: Add YUV 4:2:2 and YUV 4:4:4 tri-planar non-contiguous formats The formats use three planes through the multiplanar API, allowing for non-contiguous planes in memory. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml | 166 +++++++++++++++++++ Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml | 177 +++++++++++++++++++++ Documentation/DocBook/media/v4l/pixfmt.xml | 2 + drivers/media/v4l2-core/v4l2-ioctl.c | 4 + include/uapi/linux/videodev2.h | 4 + 5 files changed, 353 insertions(+) create mode 100644 Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml create mode 100644 Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml new file mode 100644 index 000000000000..dd502802cb75 --- /dev/null +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml @@ -0,0 +1,166 @@ + + + V4L2_PIX_FMT_YUV422M ('YM16'), V4L2_PIX_FMT_YVU422M ('YM61') + &manvol; + + + V4L2_PIX_FMT_YUV422M + V4L2_PIX_FMT_YVU422M + Planar formats with ½ horizontal resolution, also + known as YUV and YVU 4:2:2 + + + + Description + + This is a multi-planar format, as opposed to a packed format. +The three components are separated into three sub-images or planes. + + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV422M the Cb data +constitutes the second plane which is half the width of the Y plane (and of the +image). Each Cb belongs to two pixels. For example, +Cb0 belongs to Y'00, +Y'01. The Cr data, just like the Cb plane, is +in the third plane. + + V4L2_PIX_FMT_YVU422M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + + + If the Y plane has pad bytes after each row, then the Cb +and Cr planes have half as many pad bytes after their rows. In other +words, two Cx rows (including padding) is exactly as long as one Y row +(including padding). + + V4L2_PIX_FMT_YUV422M and +V4L2_PIX_FMT_YVU422M are intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + + <constant>V4L2_PIX_FMT_YUV422M</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + start1 + 0: + Cb00 + Cb01 + + + start1 + 2: + Cb10 + Cb11 + + + start1 + 4: + Cb20 + Cb21 + + + start1 + 6: + Cb30 + Cb31 + + + + start2 + 0: + Cr00 + Cr01 + + + start2 + 2: + Cr10 + Cr11 + + + start2 + 4: + Cr20 + Cr21 + + + start2 + 6: + Cr30 + Cr31 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YCY + YCY + + + 1 + YCY + YCY + + + 2 + YCY + YCY + + + 3 + YCY + YCY + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml new file mode 100644 index 000000000000..1b7335940bc7 --- /dev/null +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml @@ -0,0 +1,177 @@ + + + V4L2_PIX_FMT_YUV444M ('YM24'), V4L2_PIX_FMT_YVU444M ('YM42') + &manvol; + + + V4L2_PIX_FMT_YUV444M + V4L2_PIX_FMT_YVU444M + Planar formats with full horizontal resolution, also + known as YUV and YVU 4:4:4 + + + + Description + + This is a multi-planar format, as opposed to a packed format. +The three components are separated into three sub-images or planes. + + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV444M the Cb data +constitutes the second plane which is the same width and height as the Y plane +(and as the image). The Cr data, just like the Cb plane, is in the third plane. + + + V4L2_PIX_FMT_YVU444M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + + If the Y plane has pad bytes after each row, then the Cb +and Cr planes have the same number of pad bytes after their rows. + + V4L2_PIX_FMT_YUV444M and +V4L2_PIX_FMT_YUV444M are intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + + <constant>V4L2_PIX_FMT_YUV444M</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + start1 + 0: + Cb00 + Cb01 + Cb02 + Cb03 + + + start1 + 4: + Cb10 + Cb11 + Cb12 + Cb13 + + + start1 + 8: + Cb20 + Cb21 + Cb22 + Cb23 + + + start1 + 12: + Cb20 + Cb21 + Cb32 + Cb33 + + + + start2 + 0: + Cr00 + Cr01 + Cr02 + Cr03 + + + start2 + 4: + Cr10 + Cr11 + Cr12 + Cr13 + + + start2 + 8: + Cr20 + Cr21 + Cr22 + Cr23 + + + start2 + 12: + Cr30 + Cr31 + Cr32 + Cr33 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YCYC + YCYC + + + 1 + YCYC + YCYC + + + 2 + YCYC + YCYC + + + 3 + YCYC + YCYC + + + + + + + + + diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index 9e77ff353feb..2f02f9441443 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -1628,6 +1628,8 @@ information. &sub-y41p; &sub-yuv420; &sub-yuv420m; + &sub-yuv422m; + &sub-yuv444m; &sub-yuv410; &sub-yuv422p; &sub-yuv411p; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8a018c6dd16a..14843090fd61 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1191,6 +1191,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break; + case V4L2_PIX_FMT_YVU422M: descr = "Planar YVU 4:2:2 (N-C)"; break; + case V4L2_PIX_FMT_YUV444M: descr = "Planar YUV 4:4:4 (N-C)"; break; + case V4L2_PIX_FMT_YVU444M: descr = "Planar YVU 4:4:4 (N-C)"; break; case V4L2_PIX_FMT_SBGGR8: descr = "8-bit Bayer BGBG/GRGR"; break; case V4L2_PIX_FMT_SGBRG8: descr = "8-bit Bayer GBGB/RGRG"; break; case V4L2_PIX_FMT_SGRBG8: descr = "8-bit Bayer GRGR/BGBG"; break; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 14cd5ebfee6d..466458422385 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -546,6 +546,10 @@ struct v4l2_pix_format { /* three non contiguous planes - Y, Cb, Cr */ #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */ #define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12 YVU420 planar */ +#define V4L2_PIX_FMT_YUV422M v4l2_fourcc('Y', 'M', '1', '6') /* 16 YUV422 planar */ +#define V4L2_PIX_FMT_YVU422M v4l2_fourcc('Y', 'M', '6', '1') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV444M v4l2_fourcc('Y', 'M', '2', '4') /* 24 YUV444 planar */ +#define V4L2_PIX_FMT_YVU444M v4l2_fourcc('Y', 'M', '4', '2') /* 24 YVU444 planar */ /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ -- cgit v1.2.3 From b915bd24a034e9af1860bcab397e777fabd8200e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Nov 2015 22:04:24 -0200 Subject: [media] v4l: vsp1: Add tri-planar memory formats support Tri-planar memory formats store the Y, U and V components in separate planes. The VSP hardware supports them, the driver now does too. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index b4dca57d1ae3..ac07dd8e4a81 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -130,6 +130,26 @@ static const struct vsp1_format_info vsp1_video_formats[] = { VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, 3, { 8, 8, 8 }, false, false, 2, 2, false }, + { V4L2_PIX_FMT_YVU420M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 2, 2, false }, + { V4L2_PIX_FMT_YUV422M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 2, 1, false }, + { V4L2_PIX_FMT_YVU422M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 2, 1, false }, + { V4L2_PIX_FMT_YUV444M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_YVU444M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 1, 1, false }, }; /* -- cgit v1.2.3 From 1ad3dfed3858dcfe79eef7c8ea8e8b5f2ef068a6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 31 Jan 2016 11:34:28 -0200 Subject: [media] v4l: vsp1: Group all link creation code in a single file There's no need to spread the code across multiple source files. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 50 +++++++++++++++++++++++---------- drivers/media/platform/vsp1/vsp1_rpf.c | 20 ------------- drivers/media/platform/vsp1/vsp1_rwpf.h | 5 ---- drivers/media/platform/vsp1/vsp1_wpf.c | 25 ----------------- 4 files changed, 35 insertions(+), 65 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 533bc796391e..d7f653123712 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -82,6 +82,19 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) unsigned int pad; int ret; + if (sink->type == VSP1_ENTITY_RPF) { + struct vsp1_rwpf *rpf = to_rwpf(&sink->subdev); + + /* RPFs have no source entities, just connect their source pad + * to their video device. + */ + return media_create_pad_link(&rpf->video.video.entity, 0, + &rpf->entity.subdev.entity, + RWPF_PAD_SINK, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + } + list_for_each_entry(source, &vsp1->entities, list_dev) { u32 flags; @@ -112,6 +125,23 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) } } + if (sink->type == VSP1_ENTITY_WPF) { + struct vsp1_rwpf *wpf = to_rwpf(&sink->subdev); + unsigned int flags = MEDIA_LNK_FL_ENABLED; + + /* Connect the video device to the WPF. All connections are + * immutable except for the WPF0 source link if a LIF is + * present. + */ + if (!(vsp1->pdata.features & VSP1_HAS_LIF) || sink->index != 0) + flags |= MEDIA_LNK_FL_IMMUTABLE; + + return media_create_pad_link(&wpf->entity.subdev.entity, + RWPF_PAD_SOURCE, + &wpf->video.video.entity, 0, + flags); + } + return 0; } @@ -256,22 +286,12 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) /* Create links. */ list_for_each_entry(entity, &vsp1->entities, list_dev) { - if (entity->type == VSP1_ENTITY_WPF) { - ret = vsp1_wpf_create_links(vsp1, entity); - if (ret < 0) - goto done; - } else if (entity->type == VSP1_ENTITY_RPF) { - ret = vsp1_rpf_create_links(vsp1, entity); - if (ret < 0) - goto done; - } + if (entity->type == VSP1_ENTITY_LIF) + continue; - if (entity->type != VSP1_ENTITY_LIF && - entity->type != VSP1_ENTITY_RPF) { - ret = vsp1_create_links(vsp1, entity); - if (ret < 0) - goto done; - } + ret = vsp1_create_links(vsp1, entity); + if (ret < 0) + goto done; } if (vsp1->pdata.features & VSP1_HAS_LIF) { diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 924538223d3e..b988e46818a5 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -283,23 +283,3 @@ error: vsp1_entity_destroy(&rpf->entity); return ERR_PTR(ret); } - -/* - * vsp1_rpf_create_links() - RPF pads links creation - * @vsp1: Pointer to VSP1 device - * @entity: Pointer to VSP1 entity - * - * return negative error code or zero on success - */ -int vsp1_rpf_create_links(struct vsp1_device *vsp1, - struct vsp1_entity *entity) -{ - struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); - - /* Connect the video device to the RPF. */ - return media_create_pad_link(&rpf->video.video.entity, 0, - &rpf->entity.subdev.entity, - RWPF_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); -} diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 731d36e5258d..f452dce1a931 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -50,11 +50,6 @@ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); -int vsp1_rpf_create_links(struct vsp1_device *vsp1, - struct vsp1_entity *entity); -int vsp1_wpf_create_links(struct vsp1_device *vsp1, - struct vsp1_entity *entity); - int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index cbf514a6582d..1d722f7e2407 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -283,28 +283,3 @@ error: vsp1_entity_destroy(&wpf->entity); return ERR_PTR(ret); } - -/* - * vsp1_wpf_create_links() - RPF pads links creation - * @vsp1: Pointer to VSP1 device - * @entity: Pointer to VSP1 entity - * - * return negative error code or zero on success - */ -int vsp1_wpf_create_links(struct vsp1_device *vsp1, - struct vsp1_entity *entity) -{ - struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); - unsigned int flags; - - /* Connect the video device to the WPF. All connections are immutable - * except for the WPF0 source link if a LIF is present. - */ - flags = MEDIA_LNK_FL_ENABLED; - if (!(vsp1->pdata.features & VSP1_HAS_LIF) || entity->index != 0) - flags |= MEDIA_LNK_FL_IMMUTABLE; - - return media_create_pad_link(&wpf->entity.subdev.entity, - RWPF_PAD_SOURCE, - &wpf->video.video.entity, 0, flags); -} -- cgit v1.2.3 From 8b4a0563df145b28da8d2af0bd82d08fd389ccf5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 13:54:03 -0300 Subject: [media] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video The rwpf field contains a pointer to the rpf or wpf associated with the video node. Instead of storing it as a vsp1_entity, store the corresponding vsp1_rwpf pointer to allow accessing the vsp1_rwpf fields directly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 2 +- drivers/media/platform/vsp1/vsp1_video.c | 4 ++-- drivers/media/platform/vsp1/vsp1_video.h | 5 +++-- drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index b988e46818a5..c7a4121bcd53 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -271,7 +271,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) video->vsp1 = vsp1; video->ops = &rpf_vdev_ops; - ret = vsp1_video_init(video, &rpf->entity); + ret = vsp1_video_init(video, rpf); if (ret < 0) goto error; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index ac07dd8e4a81..b5ebca5d2410 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1203,7 +1203,7 @@ static struct v4l2_file_operations vsp1_video_fops = { * Initialization and Cleanup */ -int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) +int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) { const char *direction; int ret; @@ -1258,7 +1258,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) video->video.v4l2_dev = &video->vsp1->v4l2_dev; video->video.fops = &vsp1_video_fops; snprintf(video->video.name, sizeof(video->video.name), "%s %s", - rwpf->subdev.name, direction); + rwpf->entity.subdev.name, direction); video->video.vfl_type = VFL_TYPE_GRABBER; video->video.release = video_device_release_empty; video->video.ioctl_ops = &vsp1_video_ioctl_ops; diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index a929aa81cdbf..c1d9771c55ed 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -20,6 +20,7 @@ #include #include +struct vsp1_rwpf; struct vsp1_video; /* @@ -113,7 +114,7 @@ struct vsp1_video_operations { struct vsp1_video { struct vsp1_device *vsp1; - struct vsp1_entity *rwpf; + struct vsp1_rwpf *rwpf; const struct vsp1_video_operations *ops; @@ -140,7 +141,7 @@ static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev) return container_of(vdev, struct vsp1_video, video); } -int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf); +int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf); void vsp1_video_cleanup(struct vsp1_video *video); void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 1d722f7e2407..01493fd207bf 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -270,7 +270,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) video->vsp1 = vsp1; video->ops = &wpf_vdev_ops; - ret = vsp1_video_init(video, &wpf->entity); + ret = vsp1_video_init(video, wpf); if (ret < 0) goto error; -- cgit v1.2.3 From 86960eec4d4b4557fe37021decdf4265213d3882 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 14:00:43 -0300 Subject: [media] v4l: vsp1: Store the memory format in struct vsp1_rwpf Move the format from struct vsp1_video to struct vsp1_rwpf to prepare for VSPD KMS support that will not instantiate V4L2 video device nodes. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 4 ++-- drivers/media/platform/vsp1/vsp1_rpf.c | 4 ++-- drivers/media/platform/vsp1/vsp1_rwpf.h | 2 ++ drivers/media/platform/vsp1/vsp1_video.c | 40 ++++++++++++++++---------------- drivers/media/platform/vsp1/vsp1_video.h | 2 -- drivers/media/platform/vsp1/vsp1_wpf.c | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 7dd763311c0f..1308dfef0f92 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -94,7 +94,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) /* Disable dithering and enable color data normalization unless the * format at the pipeline output is premultiplied. */ - flags = pipe->output ? pipe->output->video.format.flags : 0; + flags = pipe->output ? pipe->output->format.flags : 0; vsp1_bru_write(bru, VI6_BRU_INCTRL, flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? 0 : VI6_BRU_INCTRL_NRM); @@ -125,7 +125,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) if (bru->inputs[i].rpf) { ctrl |= VI6_BRU_CTRL_RBC; - premultiplied = bru->inputs[i].rpf->video.format.flags + premultiplied = bru->inputs[i].rpf->format.flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; } else { ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index c7a4121bcd53..0ba7c0788bff 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -75,8 +75,8 @@ static const struct v4l2_ctrl_ops rpf_ctrl_ops = { static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) { struct vsp1_rwpf *rpf = to_rwpf(subdev); - const struct vsp1_format_info *fmtinfo = rpf->video.fmtinfo; - const struct v4l2_pix_format_mplane *format = &rpf->video.format; + const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; + const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_rect *crop = &rpf->crop; u32 pstride; u32 infmt; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index f452dce1a931..8609c3d02679 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -32,6 +32,8 @@ struct vsp1_rwpf { unsigned int max_width; unsigned int max_height; + struct v4l2_pix_format_mplane format; + const struct vsp1_format_info *fmtinfo; struct { unsigned int left; unsigned int top; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index b5ebca5d2410..614498d49427 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -204,9 +204,9 @@ static int vsp1_video_verify_format(struct vsp1_video *video) if (ret < 0) return ret == -ENOIOCTLCMD ? -EINVAL : ret; - if (video->fmtinfo->mbus != fmt.format.code || - video->format.height != fmt.format.height || - video->format.width != fmt.format.width) + if (video->rwpf->fmtinfo->mbus != fmt.format.code || + video->rwpf->format.height != fmt.format.height || + video->rwpf->format.width != fmt.format.width) return -EINVAL; return 0; @@ -807,7 +807,7 @@ vsp1_video_queue_setup(struct vb2_queue *vq, unsigned int sizes[], void *alloc_ctxs[]) { struct vsp1_video *video = vb2_get_drv_priv(vq); - const struct v4l2_pix_format_mplane *format = &video->format; + const struct v4l2_pix_format_mplane *format = &video->rwpf->format; unsigned int i; if (*nplanes) { @@ -837,7 +837,7 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf); - const struct v4l2_pix_format_mplane *format = &video->format; + const struct v4l2_pix_format_mplane *format = &video->rwpf->format; unsigned int i; if (vb->num_planes < format->num_planes) @@ -920,7 +920,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) struct vsp1_rwpf *rpf = to_rwpf(&pipe->uds_input->subdev); - uds->scale_alpha = rpf->video.fmtinfo->alpha; + uds->scale_alpha = rpf->fmtinfo->alpha; } } @@ -1024,7 +1024,7 @@ vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) return -EINVAL; mutex_lock(&video->lock); - format->fmt.pix_mp = video->format; + format->fmt.pix_mp = video->rwpf->format; mutex_unlock(&video->lock); return 0; @@ -1064,8 +1064,8 @@ vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format) goto done; } - video->format = format->fmt.pix_mp; - video->fmtinfo = info; + video->rwpf->format = format->fmt.pix_mp; + video->rwpf->fmtinfo = info; done: mutex_unlock(&video->lock); @@ -1242,17 +1242,17 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) return ret; /* ... and the format ... */ - video->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); - video->format.pixelformat = video->fmtinfo->fourcc; - video->format.colorspace = V4L2_COLORSPACE_SRGB; - video->format.field = V4L2_FIELD_NONE; - video->format.width = VSP1_VIDEO_DEF_WIDTH; - video->format.height = VSP1_VIDEO_DEF_HEIGHT; - video->format.num_planes = 1; - video->format.plane_fmt[0].bytesperline = - video->format.width * video->fmtinfo->bpp[0] / 8; - video->format.plane_fmt[0].sizeimage = - video->format.plane_fmt[0].bytesperline * video->format.height; + rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); + rwpf->format.pixelformat = rwpf->fmtinfo->fourcc; + rwpf->format.colorspace = V4L2_COLORSPACE_SRGB; + rwpf->format.field = V4L2_FIELD_NONE; + rwpf->format.width = VSP1_VIDEO_DEF_WIDTH; + rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT; + rwpf->format.num_planes = 1; + rwpf->format.plane_fmt[0].bytesperline = + rwpf->format.width * rwpf->fmtinfo->bpp[0] / 8; + rwpf->format.plane_fmt[0].sizeimage = + rwpf->format.plane_fmt[0].bytesperline * rwpf->format.height; /* ... and the video node... */ video->video.v4l2_dev = &video->vsp1->v4l2_dev; diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index c1d9771c55ed..56d0e7bd4327 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -123,8 +123,6 @@ struct vsp1_video { struct media_pad pad; struct mutex lock; - struct v4l2_pix_format_mplane format; - const struct vsp1_format_info *fmtinfo; struct vsp1_pipeline pipe; unsigned int pipe_index; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 01493fd207bf..61fcda05d5eb 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -112,7 +112,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) /* Destination stride. */ if (!pipe->lif) { - struct v4l2_pix_format_mplane *format = &wpf->video.format; + struct v4l2_pix_format_mplane *format = &wpf->format; vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, format->plane_fmt[0].bytesperline); @@ -130,7 +130,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) /* Format */ if (!pipe->lif) { - const struct vsp1_format_info *fmtinfo = wpf->video.fmtinfo; + const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; -- cgit v1.2.3 From b6af10cdd6bffb457839e0892531ed14afb6a9a6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 14:05:56 -0300 Subject: [media] v4l: vsp1: Move video operations to vsp1_rwpf This removes the dependency of vsp1_rpf and vsp1_wpf on vsp1_video, making it possible to reuse the operations without a V4L2 video device node. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 11 +++++------ drivers/media/platform/vsp1/vsp1_rwpf.h | 9 +++++++++ drivers/media/platform/vsp1/vsp1_video.c | 4 ++-- drivers/media/platform/vsp1/vsp1_video.h | 6 ------ drivers/media/platform/vsp1/vsp1_wpf.c | 12 +++++------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 0ba7c0788bff..57d36a431b18 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -186,10 +186,8 @@ static struct v4l2_subdev_ops rpf_ops = { * Video Device Operations */ -static void rpf_vdev_queue(struct vsp1_video *video, - struct vsp1_video_buffer *buf) +static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_video_buffer *buf) { - struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video); unsigned int i; for (i = 0; i < 3; ++i) @@ -208,8 +206,8 @@ static void rpf_vdev_queue(struct vsp1_video *video, buf->addr[2] + rpf->offsets[1]); } -static const struct vsp1_video_operations rpf_vdev_ops = { - .queue = rpf_vdev_queue, +static const struct vsp1_rwpf_operations rpf_vdev_ops = { + .queue = rpf_buf_queue, }; /* ----------------------------------------------------------------------------- @@ -227,6 +225,8 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) if (rpf == NULL) return ERR_PTR(-ENOMEM); + rpf->ops = &rpf_vdev_ops; + rpf->max_width = RPF_MAX_WIDTH; rpf->max_height = RPF_MAX_HEIGHT; @@ -269,7 +269,6 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; video->vsp1 = vsp1; - video->ops = &rpf_vdev_ops; ret = vsp1_video_init(video, rpf); if (ret < 0) diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 8609c3d02679..3cc80be03524 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -24,11 +24,20 @@ #define RWPF_PAD_SINK 0 #define RWPF_PAD_SOURCE 1 +struct vsp1_rwpf; +struct vsp1_video_buffer; + +struct vsp1_rwpf_operations { + void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_video_buffer *buf); +}; + struct vsp1_rwpf { struct vsp1_entity entity; struct vsp1_video video; struct v4l2_ctrl_handler ctrls; + const struct vsp1_rwpf_operations *ops; + unsigned int max_width; unsigned int max_height; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 614498d49427..559be5a4a388 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -646,7 +646,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, spin_lock_irqsave(&pipe->irqlock, flags); - video->ops->queue(video, buf); + video->rwpf->ops->queue(video->rwpf, buf); pipe->buffers_ready |= 1 << video->pipe_index; spin_unlock_irqrestore(&pipe->irqlock, flags); @@ -873,7 +873,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&pipe->irqlock, flags); - video->ops->queue(video, buf); + video->rwpf->ops->queue(video->rwpf, buf); pipe->buffers_ready |= 1 << video->pipe_index; if (vb2_is_streaming(&video->queue) && diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 56d0e7bd4327..72be847f2df9 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -108,16 +108,10 @@ to_vsp1_video_buffer(struct vb2_v4l2_buffer *vbuf) return container_of(vbuf, struct vsp1_video_buffer, buf); } -struct vsp1_video_operations { - void (*queue)(struct vsp1_video *video, struct vsp1_video_buffer *buf); -}; - struct vsp1_video { struct vsp1_device *vsp1; struct vsp1_rwpf *rwpf; - const struct vsp1_video_operations *ops; - struct video_device video; enum v4l2_buf_type type; struct media_pad pad; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 61fcda05d5eb..031af723f754 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -195,11 +195,8 @@ static struct v4l2_subdev_ops wpf_ops = { * Video Device Operations */ -static void wpf_vdev_queue(struct vsp1_video *video, - struct vsp1_video_buffer *buf) +static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_video_buffer *buf) { - struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video); - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); if (buf->buf.vb2_buf.num_planes > 1) vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]); @@ -207,8 +204,8 @@ static void wpf_vdev_queue(struct vsp1_video *video, vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]); } -static const struct vsp1_video_operations wpf_vdev_ops = { - .queue = wpf_vdev_queue, +static const struct vsp1_rwpf_operations wpf_vdev_ops = { + .queue = wpf_buf_queue, }; /* ----------------------------------------------------------------------------- @@ -226,6 +223,8 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) if (wpf == NULL) return ERR_PTR(-ENOMEM); + wpf->ops = &wpf_vdev_ops; + wpf->max_width = WPF_MAX_WIDTH; wpf->max_height = WPF_MAX_HEIGHT; @@ -268,7 +267,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; video->vsp1 = vsp1; - video->ops = &wpf_vdev_ops; ret = vsp1_video_init(video, wpf); if (ret < 0) -- cgit v1.2.3 From f7ebf3ca09c5f3f5b5c17b03cd59b7aca1ed09d2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 14:17:07 -0300 Subject: [media] v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer The structure represent a vsp1 videobuf2 buffer, name it accordingly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 2 +- drivers/media/platform/vsp1/vsp1_rwpf.h | 4 ++-- drivers/media/platform/vsp1/vsp1_video.c | 20 ++++++++++---------- drivers/media/platform/vsp1/vsp1_video.h | 8 ++++---- drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 57d36a431b18..6f94471252c1 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -186,7 +186,7 @@ static struct v4l2_subdev_ops rpf_ops = { * Video Device Operations */ -static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_video_buffer *buf) +static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_vb2_buffer *buf) { unsigned int i; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 3cc80be03524..aa22cc062ff3 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -25,10 +25,10 @@ #define RWPF_PAD_SOURCE 1 struct vsp1_rwpf; -struct vsp1_video_buffer; +struct vsp1_vb2_buffer; struct vsp1_rwpf_operations { - void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_video_buffer *buf); + void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_vb2_buffer *buf); }; struct vsp1_rwpf { diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 559be5a4a388..c597c586a7b5 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -592,12 +592,12 @@ static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) * * Return the next queued buffer or NULL if the queue is empty. */ -static struct vsp1_video_buffer * +static struct vsp1_vb2_buffer * vsp1_video_complete_buffer(struct vsp1_video *video) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); - struct vsp1_video_buffer *next = NULL; - struct vsp1_video_buffer *done; + struct vsp1_vb2_buffer *next = NULL; + struct vsp1_vb2_buffer *done; unsigned long flags; unsigned int i; @@ -609,7 +609,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video) } done = list_first_entry(&video->irqqueue, - struct vsp1_video_buffer, queue); + struct vsp1_vb2_buffer, queue); /* In DU output mode reuse the buffer if the list is singular. */ if (pipe->lif && list_is_singular(&video->irqqueue)) { @@ -621,7 +621,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video) if (!list_empty(&video->irqqueue)) next = list_first_entry(&video->irqqueue, - struct vsp1_video_buffer, queue); + struct vsp1_vb2_buffer, queue); spin_unlock_irqrestore(&video->irqlock, flags); @@ -637,7 +637,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video) static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, struct vsp1_video *video) { - struct vsp1_video_buffer *buf; + struct vsp1_vb2_buffer *buf; unsigned long flags; buf = vsp1_video_complete_buffer(video); @@ -836,7 +836,7 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); - struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf); + struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf); const struct v4l2_pix_format_mplane *format = &video->rwpf->format; unsigned int i; @@ -859,7 +859,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); - struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vbuf); + struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf); unsigned long flags; bool empty; @@ -951,7 +951,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) { struct vsp1_video *video = vb2_get_drv_priv(vq); struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); - struct vsp1_video_buffer *buffer; + struct vsp1_vb2_buffer *buffer; unsigned long flags; int ret; @@ -1276,7 +1276,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; video->queue.lock = &video->lock; video->queue.drv_priv = video; - video->queue.buf_struct_size = sizeof(struct vsp1_video_buffer); + video->queue.buf_struct_size = sizeof(struct vsp1_vb2_buffer); video->queue.ops = &vsp1_video_queue_qops; video->queue.mem_ops = &vb2_dma_contig_memops; video->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 72be847f2df9..c7e143125ef7 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -94,7 +94,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) return NULL; } -struct vsp1_video_buffer { +struct vsp1_vb2_buffer { struct vb2_v4l2_buffer buf; struct list_head queue; @@ -102,10 +102,10 @@ struct vsp1_video_buffer { unsigned int length[3]; }; -static inline struct vsp1_video_buffer * -to_vsp1_video_buffer(struct vb2_v4l2_buffer *vbuf) +static inline struct vsp1_vb2_buffer * +to_vsp1_vb2_buffer(struct vb2_v4l2_buffer *vbuf) { - return container_of(vbuf, struct vsp1_video_buffer, buf); + return container_of(vbuf, struct vsp1_vb2_buffer, buf); } struct vsp1_video { diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 031af723f754..a8f121ba9e72 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -195,7 +195,7 @@ static struct v4l2_subdev_ops wpf_ops = { * Video Device Operations */ -static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_video_buffer *buf) +static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_vb2_buffer *buf) { vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); if (buf->buf.vb2_buf.num_planes > 1) -- cgit v1.2.3 From 9d40637a6e140902696fa8495aac913f5011a3bd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 15:46:00 -0300 Subject: [media] v4l: vsp1: Move video device out of struct vsp1_rwpf To make the video device nodes optional we need to decouple the [rw]pf instances from the video devices. Move video devices out of struct vsp1_rwpf and instantiate them dynamically in the core driver code. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 + drivers/media/platform/vsp1/vsp1_bru.c | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 40 ++++++++++++++++++++++----- drivers/media/platform/vsp1/vsp1_entity.c | 3 --- drivers/media/platform/vsp1/vsp1_rpf.c | 13 --------- drivers/media/platform/vsp1/vsp1_rwpf.h | 2 -- drivers/media/platform/vsp1/vsp1_video.c | 45 +++++++++++++++++-------------- drivers/media/platform/vsp1/vsp1_video.h | 4 ++- drivers/media/platform/vsp1/vsp1_wpf.c | 14 ---------- 9 files changed, 63 insertions(+), 60 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 989e96f7e360..b25032bd37a7 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -71,6 +71,7 @@ struct vsp1_device { struct vsp1_rwpf *wpf[VSP1_MAX_WPF]; struct list_head entities; + struct list_head videos; struct v4l2_device v4l2_dev; struct media_device media_dev; diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 1308dfef0f92..b4cc9bc478af 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -19,6 +19,7 @@ #include "vsp1.h" #include "vsp1_bru.h" #include "vsp1_rwpf.h" +#include "vsp1_video.h" #define BRU_MIN_SIZE 1U #define BRU_MAX_SIZE 8190U diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index d7f653123712..8a7b11153073 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -28,6 +28,7 @@ #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" +#include "vsp1_video.h" /* ----------------------------------------------------------------------------- * Interrupt Handling @@ -88,8 +89,8 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) /* RPFs have no source entities, just connect their source pad * to their video device. */ - return media_create_pad_link(&rpf->video.video.entity, 0, - &rpf->entity.subdev.entity, + return media_create_pad_link(&rpf->entity.video->video.entity, + 0, &rpf->entity.subdev.entity, RWPF_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); @@ -138,8 +139,8 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) return media_create_pad_link(&wpf->entity.subdev.entity, RWPF_PAD_SOURCE, - &wpf->video.video.entity, 0, - flags); + &wpf->entity.video->video.entity, + 0, flags); } return 0; @@ -147,14 +148,19 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) static void vsp1_destroy_entities(struct vsp1_device *vsp1) { - struct vsp1_entity *entity; - struct vsp1_entity *next; + struct vsp1_entity *entity, *_entity; + struct vsp1_video *video, *_video; - list_for_each_entry_safe(entity, next, &vsp1->entities, list_dev) { + list_for_each_entry_safe(entity, _entity, &vsp1->entities, list_dev) { list_del(&entity->list_dev); vsp1_entity_destroy(entity); } + list_for_each_entry_safe(video, _video, &vsp1->videos, list) { + list_del(&video->list); + vsp1_video_cleanup(video); + } + v4l2_device_unregister(&vsp1->v4l2_dev); media_device_unregister(&vsp1->media_dev); media_device_cleanup(&vsp1->media_dev); @@ -228,6 +234,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_video *video; struct vsp1_rwpf *rpf; rpf = vsp1_rpf_create(vsp1, i); @@ -238,6 +245,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->rpf[i] = rpf; list_add_tail(&rpf->entity.list_dev, &vsp1->entities); + + video = vsp1_video_create(vsp1, rpf); + if (IS_ERR(video)) { + ret = PTR_ERR(video); + goto done; + } + + list_add_tail(&video->list, &vsp1->videos); } if (vsp1->pdata.features & VSP1_HAS_SRU) { @@ -264,6 +279,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + struct vsp1_video *video; struct vsp1_rwpf *wpf; wpf = vsp1_wpf_create(vsp1, i); @@ -274,6 +290,15 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->wpf[i] = wpf; list_add_tail(&wpf->entity.list_dev, &vsp1->entities); + + video = vsp1_video_create(vsp1, wpf); + if (IS_ERR(video)) { + ret = PTR_ERR(video); + goto done; + } + + list_add_tail(&video->list, &vsp1->videos); + wpf->entity.sink = &video->video.entity; } /* Register all subdevs. */ @@ -515,6 +540,7 @@ static int vsp1_probe(struct platform_device *pdev) vsp1->dev = &pdev->dev; mutex_init(&vsp1->lock); INIT_LIST_HEAD(&vsp1->entities); + INIT_LIST_HEAD(&vsp1->videos); ret = vsp1_parse_dt(vsp1); if (ret < 0) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index d7308530952f..46832242a672 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -20,7 +20,6 @@ #include "vsp1.h" #include "vsp1_entity.h" -#include "vsp1_video.h" bool vsp1_entity_is_streaming(struct vsp1_entity *entity) { @@ -225,8 +224,6 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, void vsp1_entity_destroy(struct vsp1_entity *entity) { - if (entity->video) - vsp1_video_cleanup(entity->video); if (entity->subdev.ctrl_handler) v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); media_entity_cleanup(&entity->subdev.entity); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 6f94471252c1..085d10056297 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -217,7 +217,6 @@ static const struct vsp1_rwpf_operations rpf_vdev_ops = { struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; - struct vsp1_video *video; struct vsp1_rwpf *rpf; int ret; @@ -264,18 +263,6 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) goto error; } - /* Initialize the video device. */ - video = &rpf->video; - - video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - video->vsp1 = vsp1; - - ret = vsp1_video_init(video, rpf); - if (ret < 0) - goto error; - - rpf->entity.video = video; - return rpf; error: diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index aa22cc062ff3..ee2a8bf269fa 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -19,7 +19,6 @@ #include "vsp1.h" #include "vsp1_entity.h" -#include "vsp1_video.h" #define RWPF_PAD_SINK 0 #define RWPF_PAD_SOURCE 1 @@ -33,7 +32,6 @@ struct vsp1_rwpf_operations { struct vsp1_rwpf { struct vsp1_entity entity; - struct vsp1_video video; struct v4l2_ctrl_handler ctrls; const struct vsp1_rwpf_operations *ops; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index c597c586a7b5..2367a07d6149 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -448,11 +448,11 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, if (e->type == VSP1_ENTITY_RPF) { rwpf = to_rwpf(subdev); pipe->inputs[pipe->num_inputs++] = rwpf; - rwpf->video.pipe_index = pipe->num_inputs; + rwpf->entity.video->pipe_index = pipe->num_inputs; } else if (e->type == VSP1_ENTITY_WPF) { rwpf = to_rwpf(subdev); pipe->output = to_rwpf(subdev); - rwpf->video.pipe_index = 0; + rwpf->entity.video->pipe_index = 0; } else if (e->type == VSP1_ENTITY_LIF) { pipe->lif = e; } else if (e->type == VSP1_ENTITY_BRU) { @@ -663,10 +663,10 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) /* Complete buffers on all video nodes. */ for (i = 0; i < pipe->num_inputs; ++i) - vsp1_video_frame_end(pipe, &pipe->inputs[i]->video); + vsp1_video_frame_end(pipe, pipe->inputs[i]->entity.video); if (!pipe->lif) - vsp1_video_frame_end(pipe, &pipe->output->video); + vsp1_video_frame_end(pipe, pipe->output->entity.video); spin_lock_irqsave(&pipe->irqlock, flags); @@ -1203,29 +1203,34 @@ static struct v4l2_file_operations vsp1_video_fops = { * Initialization and Cleanup */ -int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) +struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, + struct vsp1_rwpf *rwpf) { + struct vsp1_video *video; const char *direction; int ret; - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - break; + video = devm_kzalloc(vsp1->dev, sizeof(*video), GFP_KERNEL); + if (!video) + return ERR_PTR(-ENOMEM); - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + rwpf->entity.video = video; + + video->vsp1 = vsp1; + video->rwpf = rwpf; + + if (rwpf->entity.type == VSP1_ENTITY_RPF) { direction = "input"; + video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; video->pad.flags = MEDIA_PAD_FL_SOURCE; video->video.vfl_dir = VFL_DIR_TX; - break; - - default: - return -EINVAL; + } else { + direction = "output"; + video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + video->pad.flags = MEDIA_PAD_FL_SINK; + video->video.vfl_dir = VFL_DIR_RX; } - video->rwpf = rwpf; - mutex_init(&video->lock); spin_lock_init(&video->irqlock); INIT_LIST_HEAD(&video->irqqueue); @@ -1239,7 +1244,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) /* Initialize the media entity... */ ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); if (ret < 0) - return ret; + return ERR_PTR(ret); /* ... and the format ... */ rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); @@ -1294,12 +1299,12 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf) goto error; } - return 0; + return video; error: vb2_dma_contig_cleanup_ctx(video->alloc_ctx); vsp1_video_cleanup(video); - return ret; + return ERR_PTR(ret); } void vsp1_video_cleanup(struct vsp1_video *video) diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index c7e143125ef7..cbd44c336169 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -109,6 +109,7 @@ to_vsp1_vb2_buffer(struct vb2_v4l2_buffer *vbuf) } struct vsp1_video { + struct list_head list; struct vsp1_device *vsp1; struct vsp1_rwpf *rwpf; @@ -133,7 +134,8 @@ static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev) return container_of(vdev, struct vsp1_video, video); } -int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf); +struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, + struct vsp1_rwpf *rwpf); void vsp1_video_cleanup(struct vsp1_video *video); void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index a8f121ba9e72..a4c0888a1b46 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -215,7 +215,6 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = { struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) { struct v4l2_subdev *subdev; - struct vsp1_video *video; struct vsp1_rwpf *wpf; int ret; @@ -262,19 +261,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) goto error; } - /* Initialize the video device. */ - video = &wpf->video; - - video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - video->vsp1 = vsp1; - - ret = vsp1_video_init(video, wpf); - if (ret < 0) - goto error; - - wpf->entity.video = video; - wpf->entity.sink = &wpf->video.video.entity; - return wpf; error: -- cgit v1.2.3 From b58faa95eae5d3cbdf9772399772730b1846dee9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 16:04:47 -0300 Subject: [media] v4l: vsp1: Make rwpf operations independent of video device The rwpf queue operation doesn't queue a buffer but sets the memory address for the next run. Rename it to set_memory and pass it a new structure independent of the video buffer than only contains memory information. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 16 ++++++++-------- drivers/media/platform/vsp1/vsp1_rwpf.h | 10 ++++++++-- drivers/media/platform/vsp1/vsp1_video.c | 15 +++++++++------ drivers/media/platform/vsp1/vsp1_video.h | 7 +++---- drivers/media/platform/vsp1/vsp1_wpf.c | 14 +++++++------- 5 files changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 085d10056297..c0b7f76cd0b5 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -186,28 +186,28 @@ static struct v4l2_subdev_ops rpf_ops = { * Video Device Operations */ -static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_vb2_buffer *buf) +static void rpf_set_memory(struct vsp1_rwpf *rpf, struct vsp1_rwpf_memory *mem) { unsigned int i; for (i = 0; i < 3; ++i) - rpf->buf_addr[i] = buf->addr[i]; + rpf->buf_addr[i] = mem->addr[i]; if (!vsp1_entity_is_streaming(&rpf->entity)) return; vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, - buf->addr[0] + rpf->offsets[0]); - if (buf->buf.vb2_buf.num_planes > 1) + mem->addr[0] + rpf->offsets[0]); + if (mem->num_planes > 1) vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, - buf->addr[1] + rpf->offsets[1]); - if (buf->buf.vb2_buf.num_planes > 2) + mem->addr[1] + rpf->offsets[1]); + if (mem->num_planes > 2) vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, - buf->addr[2] + rpf->offsets[1]); + mem->addr[2] + rpf->offsets[1]); } static const struct vsp1_rwpf_operations rpf_vdev_ops = { - .queue = rpf_buf_queue, + .set_memory = rpf_set_memory, }; /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index ee2a8bf269fa..0076920adb28 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -24,10 +24,16 @@ #define RWPF_PAD_SOURCE 1 struct vsp1_rwpf; -struct vsp1_vb2_buffer; + +struct vsp1_rwpf_memory { + unsigned int num_planes; + dma_addr_t addr[3]; + unsigned int length[3]; +}; struct vsp1_rwpf_operations { - void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_vb2_buffer *buf); + void (*set_memory)(struct vsp1_rwpf *rwpf, + struct vsp1_rwpf_memory *mem); }; struct vsp1_rwpf { diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 2367a07d6149..26e980da1ed9 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -628,7 +628,8 @@ vsp1_video_complete_buffer(struct vsp1_video *video) done->buf.sequence = video->sequence++; done->buf.vb2_buf.timestamp = ktime_get_ns(); for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) - vb2_set_plane_payload(&done->buf.vb2_buf, i, done->length[i]); + vb2_set_plane_payload(&done->buf.vb2_buf, i, + done->mem.length[i]); vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); return next; @@ -646,7 +647,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, spin_lock_irqsave(&pipe->irqlock, flags); - video->rwpf->ops->queue(video->rwpf, buf); + video->rwpf->ops->set_memory(video->rwpf, &buf->mem); pipe->buffers_ready |= 1 << video->pipe_index; spin_unlock_irqrestore(&pipe->irqlock, flags); @@ -843,11 +844,13 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) if (vb->num_planes < format->num_planes) return -EINVAL; + buf->mem.num_planes = vb->num_planes; + for (i = 0; i < vb->num_planes; ++i) { - buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); - buf->length[i] = vb2_plane_size(vb, i); + buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); + buf->mem.length[i] = vb2_plane_size(vb, i); - if (buf->length[i] < format->plane_fmt[i].sizeimage) + if (buf->mem.length[i] < format->plane_fmt[i].sizeimage) return -EINVAL; } @@ -873,7 +876,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&pipe->irqlock, flags); - video->rwpf->ops->queue(video->rwpf, buf); + video->rwpf->ops->set_memory(video->rwpf, &buf->mem); pipe->buffers_ready |= 1 << video->pipe_index; if (vb2_is_streaming(&video->queue) && diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index cbd44c336169..21096d82af05 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -20,7 +20,8 @@ #include #include -struct vsp1_rwpf; +#include "vsp1_rwpf.h" + struct vsp1_video; /* @@ -97,9 +98,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) struct vsp1_vb2_buffer { struct vb2_v4l2_buffer buf; struct list_head queue; - - dma_addr_t addr[3]; - unsigned int length[3]; + struct vsp1_rwpf_memory mem; }; static inline struct vsp1_vb2_buffer * diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index a4c0888a1b46..d2537b46fc46 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -195,17 +195,17 @@ static struct v4l2_subdev_ops wpf_ops = { * Video Device Operations */ -static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_vb2_buffer *buf) +static void wpf_set_memory(struct vsp1_rwpf *wpf, struct vsp1_rwpf_memory *mem) { - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); - if (buf->buf.vb2_buf.num_planes > 1) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]); - if (buf->buf.vb2_buf.num_planes > 2) - vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]); + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, mem->addr[0]); + if (mem->num_planes > 1) + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, mem->addr[1]); + if (mem->num_planes > 2) + vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, mem->addr[2]); } static const struct vsp1_rwpf_operations wpf_vdev_ops = { - .queue = wpf_buf_queue, + .set_memory = wpf_set_memory, }; /* ----------------------------------------------------------------------------- -- cgit v1.2.3 From 62a409034c62ae2b377fe631957e80262020ef17 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 16:13:27 -0300 Subject: [media] v4l: vsp1: Support VSP1 instances without any UDS Not all VSP1 instances include a UDS. Make the renesas,#uds DT property optional and accept a number of UDS equal to 0 as valid. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,vsp1.txt | 3 ++- drivers/media/platform/vsp1/vsp1_drv.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt index 87fe08abf36d..674c8c30d046 100644 --- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt +++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt @@ -13,12 +13,13 @@ Required properties: - clocks: A phandle + clock-specifier pair for the VSP1 functional clock. - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP1. - - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1. - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP1. Optional properties: + - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1. Defaults + to 0 if not present. - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is available. - renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 8a7b11153073..773c9f0b0971 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -511,7 +511,7 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1) return -EINVAL; } - if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) { + if (pdata->uds_count > VSP1_MAX_UDS) { dev_err(vsp1->dev, "invalid number of UDS (%u)\n", pdata->uds_count); return -EINVAL; -- cgit v1.2.3 From faf2644d8abf5ddaf68887d966f099eca4d5f504 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 14:58:43 -0300 Subject: [media] v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf Only RPFs and WPFs can be associated with video nodes, don't waste memory by storing the video pointer in all entities. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 6 +++--- drivers/media/platform/vsp1/vsp1_entity.h | 3 --- drivers/media/platform/vsp1/vsp1_rwpf.h | 3 +++ drivers/media/platform/vsp1/vsp1_video.c | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 773c9f0b0971..0fb654e72633 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -89,8 +89,8 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) /* RPFs have no source entities, just connect their source pad * to their video device. */ - return media_create_pad_link(&rpf->entity.video->video.entity, - 0, &rpf->entity.subdev.entity, + return media_create_pad_link(&rpf->video->video.entity, 0, + &rpf->entity.subdev.entity, RWPF_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); @@ -139,7 +139,7 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) return media_create_pad_link(&wpf->entity.subdev.entity, RWPF_PAD_SOURCE, - &wpf->entity.video->video.entity, + &wpf->video->video.entity, 0, flags); } diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 8867a5787c28..9c95507ec762 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -19,7 +19,6 @@ #include struct vsp1_device; -struct vsp1_video; enum vsp1_entity_type { VSP1_ENTITY_BRU, @@ -71,8 +70,6 @@ struct vsp1_entity { struct v4l2_subdev subdev; struct v4l2_mbus_framefmt *formats; - struct vsp1_video *video; - spinlock_t lock; /* Protects the streaming field */ bool streaming; }; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 0076920adb28..1a90c7c8e972 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -24,6 +24,7 @@ #define RWPF_PAD_SOURCE 1 struct vsp1_rwpf; +struct vsp1_video; struct vsp1_rwpf_memory { unsigned int num_planes; @@ -40,6 +41,8 @@ struct vsp1_rwpf { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; + struct vsp1_video *video; + const struct vsp1_rwpf_operations *ops; unsigned int max_width; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 26e980da1ed9..e9a6f9f90c90 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -448,11 +448,11 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, if (e->type == VSP1_ENTITY_RPF) { rwpf = to_rwpf(subdev); pipe->inputs[pipe->num_inputs++] = rwpf; - rwpf->entity.video->pipe_index = pipe->num_inputs; + rwpf->video->pipe_index = pipe->num_inputs; } else if (e->type == VSP1_ENTITY_WPF) { rwpf = to_rwpf(subdev); pipe->output = to_rwpf(subdev); - rwpf->entity.video->pipe_index = 0; + rwpf->video->pipe_index = 0; } else if (e->type == VSP1_ENTITY_LIF) { pipe->lif = e; } else if (e->type == VSP1_ENTITY_BRU) { @@ -664,10 +664,10 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) /* Complete buffers on all video nodes. */ for (i = 0; i < pipe->num_inputs; ++i) - vsp1_video_frame_end(pipe, pipe->inputs[i]->entity.video); + vsp1_video_frame_end(pipe, pipe->inputs[i]->video); if (!pipe->lif) - vsp1_video_frame_end(pipe, pipe->output->entity.video); + vsp1_video_frame_end(pipe, pipe->output->video); spin_lock_irqsave(&pipe->irqlock, flags); @@ -1217,7 +1217,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, if (!video) return ERR_PTR(-ENOMEM); - rwpf->entity.video = video; + rwpf->video = video; video->vsp1 = vsp1; video->rwpf = rwpf; -- cgit v1.2.3 From 2f2db2f2061a88e959e3cbfd0518b72761fd7b36 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 17:17:15 -0300 Subject: [media] v4l: vsp1: Remove struct vsp1_pipeline num_video field The field is always equal to the num_inputs field plus one, remove the duplicate. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 7 ++----- drivers/media/platform/vsp1/vsp1_video.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index e9a6f9f90c90..381447a4631a 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -403,7 +403,6 @@ static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) INIT_LIST_HEAD(&pipe->entities); pipe->state = VSP1_PIPELINE_STOPPED; pipe->buffers_ready = 0; - pipe->num_video = 0; pipe->num_inputs = 0; pipe->output = NULL; pipe->bru = NULL; @@ -436,10 +435,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, struct vsp1_rwpf *rwpf; struct vsp1_entity *e; - if (is_media_entity_v4l2_io(entity)) { - pipe->num_video++; + if (is_media_entity_v4l2_io(entity)) continue; - } subdev = media_entity_to_v4l2_subdev(entity); e = to_vsp1_entity(subdev); @@ -907,7 +904,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) int ret; mutex_lock(&pipe->lock); - if (pipe->stream_count == pipe->num_video - 1) { + if (pipe->stream_count == pipe->num_inputs) { if (pipe->uds) { struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 21096d82af05..e9d0e1ab9162 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -75,7 +75,6 @@ struct vsp1_pipeline { unsigned int stream_count; unsigned int buffers_ready; - unsigned int num_video; unsigned int num_inputs; struct vsp1_rwpf *inputs[VSP1_MAX_RPF]; struct vsp1_rwpf *output; -- cgit v1.2.3 From 3f725b7eee496d7d0e0daea94df23a8daafbec40 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 16:37:11 -0300 Subject: [media] v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video To make the pipeline structure and operations usable without video devices the frame end processing must be decoupled from struct vsp1_video. Implement this by calling the video frame end function indirectly through a function pointer in struct vsp1_pipeline. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 25 +++++++++++++++++-------- drivers/media/platform/vsp1/vsp1_video.h | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 381447a4631a..8f8ff443c8fb 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -633,8 +633,9 @@ vsp1_video_complete_buffer(struct vsp1_video *video) } static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, - struct vsp1_video *video) + struct vsp1_rwpf *rwpf) { + struct vsp1_video *video = rwpf->video; struct vsp1_vb2_buffer *buf; unsigned long flags; @@ -650,21 +651,28 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, spin_unlock_irqrestore(&pipe->irqlock, flags); } +static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + unsigned int i; + + /* Complete buffers on all video nodes. */ + for (i = 0; i < pipe->num_inputs; ++i) + vsp1_video_frame_end(pipe, pipe->inputs[i]); + + if (!pipe->lif) + vsp1_video_frame_end(pipe, pipe->output); +} + void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { enum vsp1_pipeline_state state; unsigned long flags; - unsigned int i; if (pipe == NULL) return; - /* Complete buffers on all video nodes. */ - for (i = 0; i < pipe->num_inputs; ++i) - vsp1_video_frame_end(pipe, pipe->inputs[i]->video); - - if (!pipe->lif) - vsp1_video_frame_end(pipe, pipe->output->video); + /* Signal frame end to the pipeline handler. */ + pipe->frame_end(pipe); spin_lock_irqsave(&pipe->irqlock, flags); @@ -1240,6 +1248,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, INIT_LIST_HEAD(&video->pipe.entities); init_waitqueue_head(&video->pipe.wq); video->pipe.state = VSP1_PIPELINE_STOPPED; + video->pipe.frame_end = vsp1_video_pipeline_frame_end; /* Initialize the media entity... */ ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index e9d0e1ab9162..b79fdaa7ebdc 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -70,6 +70,8 @@ struct vsp1_pipeline { enum vsp1_pipeline_state state; wait_queue_head_t wq; + void (*frame_end)(struct vsp1_pipeline *pipe); + struct mutex lock; unsigned int use_count; unsigned int stream_count; -- cgit v1.2.3 From dba4a18073c365a1f9f7529e22a3e1394ce798f2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 14:15:23 -0300 Subject: [media] v4l: vsp1: Split pipeline management code from vsp1_video.c The code will be used to control the vsp1 driver from the DU driver without using video nodes. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 3 +- drivers/media/platform/vsp1/vsp1_pipe.c | 248 +++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_pipe.h | 85 +++++++++++ drivers/media/platform/vsp1/vsp1_video.c | 225 +--------------------------- drivers/media/platform/vsp1/vsp1_video.h | 59 +------- 5 files changed, 340 insertions(+), 280 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.c create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.h diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 6a93f928dfde..0ef0b5384125 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,4 +1,5 @@ -vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o +vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_pipe.o +vsp1-y += vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c new file mode 100644 index 000000000000..cdc670b88fcc --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -0,0 +1,248 @@ +/* + * vsp1_pipe.c -- R-Car VSP1 Pipeline + * + * Copyright (C) 2013-2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 +#include +#include + +#include +#include + +#include "vsp1.h" +#include "vsp1_bru.h" +#include "vsp1_entity.h" +#include "vsp1_pipe.h" +#include "vsp1_rwpf.h" +#include "vsp1_uds.h" + +/* ----------------------------------------------------------------------------- + * Pipeline Management + */ + +void vsp1_pipeline_reset(struct vsp1_pipeline *pipe) +{ + if (pipe->bru) { + struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i) + bru->inputs[i].rpf = NULL; + } + + INIT_LIST_HEAD(&pipe->entities); + pipe->state = VSP1_PIPELINE_STOPPED; + pipe->buffers_ready = 0; + pipe->num_inputs = 0; + pipe->output = NULL; + pipe->bru = NULL; + pipe->lif = NULL; + pipe->uds = NULL; +} + +void vsp1_pipeline_run(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + + vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD); + pipe->state = VSP1_PIPELINE_RUNNING; + pipe->buffers_ready = 0; +} + +bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe) +{ + unsigned long flags; + bool stopped; + + spin_lock_irqsave(&pipe->irqlock, flags); + stopped = pipe->state == VSP1_PIPELINE_STOPPED; + spin_unlock_irqrestore(&pipe->irqlock, flags); + + return stopped; +} + +int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) +{ + struct vsp1_entity *entity; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pipe->irqlock, flags); + if (pipe->state == VSP1_PIPELINE_RUNNING) + pipe->state = VSP1_PIPELINE_STOPPING; + spin_unlock_irqrestore(&pipe->irqlock, flags); + + ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), + msecs_to_jiffies(500)); + ret = ret == 0 ? -ETIMEDOUT : 0; + + list_for_each_entry(entity, &pipe->entities, list_pipe) { + if (entity->route && entity->route->reg) + vsp1_write(entity->vsp1, entity->route->reg, + VI6_DPR_NODE_UNUSED); + + v4l2_subdev_call(&entity->subdev, video, s_stream, 0); + } + + return ret; +} + +bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) +{ + unsigned int mask; + + mask = ((1 << pipe->num_inputs) - 1) << 1; + if (!pipe->lif) + mask |= 1 << 0; + + return pipe->buffers_ready == mask; +} + +void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + enum vsp1_pipeline_state state; + unsigned long flags; + + if (pipe == NULL) + return; + + /* Signal frame end to the pipeline handler. */ + pipe->frame_end(pipe); + + spin_lock_irqsave(&pipe->irqlock, flags); + + state = pipe->state; + pipe->state = VSP1_PIPELINE_STOPPED; + + /* If a stop has been requested, mark the pipeline as stopped and + * return. + */ + if (state == VSP1_PIPELINE_STOPPING) { + wake_up(&pipe->wq); + goto done; + } + + /* Restart the pipeline if ready. */ + if (vsp1_pipeline_ready(pipe)) + vsp1_pipeline_run(pipe); + +done: + spin_unlock_irqrestore(&pipe->irqlock, flags); +} + +/* + * Propagate the alpha value through the pipeline. + * + * As the UDS has restricted scaling capabilities when the alpha component needs + * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha + * value. The UDS then outputs a fixed alpha value which needs to be programmed + * from the input RPF alpha. + */ +void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, + struct vsp1_entity *input, + unsigned int alpha) +{ + struct vsp1_entity *entity; + struct media_pad *pad; + + pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]); + + while (pad) { + if (!is_media_entity_v4l2_subdev(pad->entity)) + break; + + entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); + + /* The BRU background color has a fixed alpha value set to 255, + * the output alpha value is thus always equal to 255. + */ + if (entity->type == VSP1_ENTITY_BRU) + alpha = 255; + + if (entity->type == VSP1_ENTITY_UDS) { + struct vsp1_uds *uds = to_uds(&entity->subdev); + + vsp1_uds_set_alpha(uds, alpha); + break; + } + + pad = &entity->pads[entity->source_pad]; + pad = media_entity_remote_pad(pad); + } +} + +void vsp1_pipelines_suspend(struct vsp1_device *vsp1) +{ + unsigned long flags; + unsigned int i; + int ret; + + /* To avoid increasing the system suspend time needlessly, loop over the + * pipelines twice, first to set them all to the stopping state, and + * then to wait for the stop to complete. + */ + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + struct vsp1_rwpf *wpf = vsp1->wpf[i]; + struct vsp1_pipeline *pipe; + + if (wpf == NULL) + continue; + + pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + if (pipe == NULL) + continue; + + spin_lock_irqsave(&pipe->irqlock, flags); + if (pipe->state == VSP1_PIPELINE_RUNNING) + pipe->state = VSP1_PIPELINE_STOPPING; + spin_unlock_irqrestore(&pipe->irqlock, flags); + } + + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + struct vsp1_rwpf *wpf = vsp1->wpf[i]; + struct vsp1_pipeline *pipe; + + if (wpf == NULL) + continue; + + pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + if (pipe == NULL) + continue; + + ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), + msecs_to_jiffies(500)); + if (ret == 0) + dev_warn(vsp1->dev, "pipeline %u stop timeout\n", + wpf->entity.index); + } +} + +void vsp1_pipelines_resume(struct vsp1_device *vsp1) +{ + unsigned int i; + + /* Resume pipeline all running pipelines. */ + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + struct vsp1_rwpf *wpf = vsp1->wpf[i]; + struct vsp1_pipeline *pipe; + + if (wpf == NULL) + continue; + + pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + if (pipe == NULL) + continue; + + if (vsp1_pipeline_ready(pipe)) + vsp1_pipeline_run(pipe); + } +} diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h new file mode 100644 index 000000000000..f8a099fba973 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -0,0 +1,85 @@ +/* + * vsp1_pipe.h -- R-Car VSP1 Pipeline + * + * Copyright (C) 2013-2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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. + */ +#ifndef __VSP1_PIPE_H__ +#define __VSP1_PIPE_H__ + +#include +#include +#include + +#include + +struct vsp1_rwpf; + +enum vsp1_pipeline_state { + VSP1_PIPELINE_STOPPED, + VSP1_PIPELINE_RUNNING, + VSP1_PIPELINE_STOPPING, +}; + +/* + * struct vsp1_pipeline - A VSP1 hardware pipeline + * @media: the media pipeline + * @irqlock: protects the pipeline state + * @lock: protects the pipeline use count and stream count + */ +struct vsp1_pipeline { + struct media_pipeline pipe; + + spinlock_t irqlock; + enum vsp1_pipeline_state state; + wait_queue_head_t wq; + + void (*frame_end)(struct vsp1_pipeline *pipe); + + struct mutex lock; + unsigned int use_count; + unsigned int stream_count; + unsigned int buffers_ready; + + unsigned int num_inputs; + struct vsp1_rwpf *inputs[VSP1_MAX_RPF]; + struct vsp1_rwpf *output; + struct vsp1_entity *bru; + struct vsp1_entity *lif; + struct vsp1_entity *uds; + struct vsp1_entity *uds_input; + + struct list_head entities; +}; + +static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) +{ + if (likely(e->pipe)) + return container_of(e->pipe, struct vsp1_pipeline, pipe); + else + return NULL; +} + +void vsp1_pipeline_reset(struct vsp1_pipeline *pipe); + +void vsp1_pipeline_run(struct vsp1_pipeline *pipe); +bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe); +int vsp1_pipeline_stop(struct vsp1_pipeline *pipe); +bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe); + +void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); + +void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, + struct vsp1_entity *input, + unsigned int alpha); + +void vsp1_pipelines_suspend(struct vsp1_device *vsp1); +void vsp1_pipelines_resume(struct vsp1_device *vsp1); + +#endif /* __VSP1_PIPE_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 8f8ff443c8fb..6b9f115746b2 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -14,10 +14,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -30,6 +30,7 @@ #include "vsp1.h" #include "vsp1_bru.h" #include "vsp1_entity.h" +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" #include "vsp1_uds.h" #include "vsp1_video.h" @@ -390,26 +391,6 @@ out: return rval; } -static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) -{ - if (pipe->bru) { - struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i) - bru->inputs[i].rpf = NULL; - } - - INIT_LIST_HEAD(&pipe->entities); - pipe->state = VSP1_PIPELINE_STOPPED; - pipe->buffers_ready = 0; - pipe->num_inputs = 0; - pipe->output = NULL; - pipe->bru = NULL; - pipe->lif = NULL; - pipe->uds = NULL; -} - static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, struct vsp1_video *video) { @@ -480,7 +461,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, return 0; error: - __vsp1_pipeline_cleanup(pipe); + vsp1_pipeline_reset(pipe); return ret; } @@ -512,69 +493,11 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) /* If we're the last user clean up the pipeline. */ if (--pipe->use_count == 0) - __vsp1_pipeline_cleanup(pipe); + vsp1_pipeline_reset(pipe); mutex_unlock(&pipe->lock); } -static void vsp1_pipeline_run(struct vsp1_pipeline *pipe) -{ - struct vsp1_device *vsp1 = pipe->output->entity.vsp1; - - vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD); - pipe->state = VSP1_PIPELINE_RUNNING; - pipe->buffers_ready = 0; -} - -static bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe) -{ - unsigned long flags; - bool stopped; - - spin_lock_irqsave(&pipe->irqlock, flags); - stopped = pipe->state == VSP1_PIPELINE_STOPPED; - spin_unlock_irqrestore(&pipe->irqlock, flags); - - return stopped; -} - -static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) -{ - struct vsp1_entity *entity; - unsigned long flags; - int ret; - - spin_lock_irqsave(&pipe->irqlock, flags); - if (pipe->state == VSP1_PIPELINE_RUNNING) - pipe->state = VSP1_PIPELINE_STOPPING; - spin_unlock_irqrestore(&pipe->irqlock, flags); - - ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), - msecs_to_jiffies(500)); - ret = ret == 0 ? -ETIMEDOUT : 0; - - list_for_each_entry(entity, &pipe->entities, list_pipe) { - if (entity->route && entity->route->reg) - vsp1_write(entity->vsp1, entity->route->reg, - VI6_DPR_NODE_UNUSED); - - v4l2_subdev_call(&entity->subdev, video, s_stream, 0); - } - - return ret; -} - -static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) -{ - unsigned int mask; - - mask = ((1 << pipe->num_inputs) - 1) << 1; - if (!pipe->lif) - mask |= 1 << 0; - - return pipe->buffers_ready == mask; -} - /* * vsp1_video_complete_buffer - Complete the current buffer * @video: the video node @@ -663,146 +586,6 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) vsp1_video_frame_end(pipe, pipe->output); } -void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) -{ - enum vsp1_pipeline_state state; - unsigned long flags; - - if (pipe == NULL) - return; - - /* Signal frame end to the pipeline handler. */ - pipe->frame_end(pipe); - - spin_lock_irqsave(&pipe->irqlock, flags); - - state = pipe->state; - pipe->state = VSP1_PIPELINE_STOPPED; - - /* If a stop has been requested, mark the pipeline as stopped and - * return. - */ - if (state == VSP1_PIPELINE_STOPPING) { - wake_up(&pipe->wq); - goto done; - } - - /* Restart the pipeline if ready. */ - if (vsp1_pipeline_ready(pipe)) - vsp1_pipeline_run(pipe); - -done: - spin_unlock_irqrestore(&pipe->irqlock, flags); -} - -/* - * Propagate the alpha value through the pipeline. - * - * As the UDS has restricted scaling capabilities when the alpha component needs - * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha - * value. The UDS then outputs a fixed alpha value which needs to be programmed - * from the input RPF alpha. - */ -void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, - struct vsp1_entity *input, - unsigned int alpha) -{ - struct vsp1_entity *entity; - struct media_pad *pad; - - pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]); - - while (pad) { - if (!is_media_entity_v4l2_subdev(pad->entity)) - break; - - entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); - - /* The BRU background color has a fixed alpha value set to 255, - * the output alpha value is thus always equal to 255. - */ - if (entity->type == VSP1_ENTITY_BRU) - alpha = 255; - - if (entity->type == VSP1_ENTITY_UDS) { - struct vsp1_uds *uds = to_uds(&entity->subdev); - - vsp1_uds_set_alpha(uds, alpha); - break; - } - - pad = &entity->pads[entity->source_pad]; - pad = media_entity_remote_pad(pad); - } -} - -void vsp1_pipelines_suspend(struct vsp1_device *vsp1) -{ - unsigned long flags; - unsigned int i; - int ret; - - /* To avoid increasing the system suspend time needlessly, loop over the - * pipelines twice, first to set them all to the stopping state, and then - * to wait for the stop to complete. - */ - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { - struct vsp1_rwpf *wpf = vsp1->wpf[i]; - struct vsp1_pipeline *pipe; - - if (wpf == NULL) - continue; - - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); - if (pipe == NULL) - continue; - - spin_lock_irqsave(&pipe->irqlock, flags); - if (pipe->state == VSP1_PIPELINE_RUNNING) - pipe->state = VSP1_PIPELINE_STOPPING; - spin_unlock_irqrestore(&pipe->irqlock, flags); - } - - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { - struct vsp1_rwpf *wpf = vsp1->wpf[i]; - struct vsp1_pipeline *pipe; - - if (wpf == NULL) - continue; - - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); - if (pipe == NULL) - continue; - - ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), - msecs_to_jiffies(500)); - if (ret == 0) - dev_warn(vsp1->dev, "pipeline %u stop timeout\n", - wpf->entity.index); - } -} - -void vsp1_pipelines_resume(struct vsp1_device *vsp1) -{ - unsigned int i; - - /* Resume pipeline all running pipelines. */ - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { - struct vsp1_rwpf *wpf = vsp1->wpf[i]; - struct vsp1_pipeline *pipe; - - if (wpf == NULL) - continue; - - pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); - if (pipe == NULL) - continue; - - if (vsp1_pipeline_ready(pipe)) - vsp1_pipeline_run(pipe); - } -} - /* ----------------------------------------------------------------------------- * videobuf2 Queue Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index b79fdaa7ebdc..faccb2aede5c 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -15,15 +15,12 @@ #include #include -#include -#include #include +#include "vsp1_pipe.h" #include "vsp1_rwpf.h" -struct vsp1_video; - /* * struct vsp1_format_info - VSP1 video format description * @mbus: media bus format code @@ -51,51 +48,6 @@ struct vsp1_format_info { bool alpha; }; -enum vsp1_pipeline_state { - VSP1_PIPELINE_STOPPED, - VSP1_PIPELINE_RUNNING, - VSP1_PIPELINE_STOPPING, -}; - -/* - * struct vsp1_pipeline - A VSP1 hardware pipeline - * @media: the media pipeline - * @irqlock: protects the pipeline state - * @lock: protects the pipeline use count and stream count - */ -struct vsp1_pipeline { - struct media_pipeline pipe; - - spinlock_t irqlock; - enum vsp1_pipeline_state state; - wait_queue_head_t wq; - - void (*frame_end)(struct vsp1_pipeline *pipe); - - struct mutex lock; - unsigned int use_count; - unsigned int stream_count; - unsigned int buffers_ready; - - unsigned int num_inputs; - struct vsp1_rwpf *inputs[VSP1_MAX_RPF]; - struct vsp1_rwpf *output; - struct vsp1_entity *bru; - struct vsp1_entity *lif; - struct vsp1_entity *uds; - struct vsp1_entity *uds_input; - - struct list_head entities; -}; - -static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) -{ - if (likely(e->pipe)) - return container_of(e->pipe, struct vsp1_pipeline, pipe); - else - return NULL; -} - struct vsp1_vb2_buffer { struct vb2_v4l2_buffer buf; struct list_head queue; @@ -138,13 +90,4 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, struct vsp1_rwpf *rwpf); void vsp1_video_cleanup(struct vsp1_video *video); -void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); - -void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, - struct vsp1_entity *input, - unsigned int alpha); - -void vsp1_pipelines_suspend(struct vsp1_device *vsp1); -void vsp1_pipelines_resume(struct vsp1_device *vsp1); - #endif /* __VSP1_VIDEO_H__ */ -- cgit v1.2.3 From 945f127677a00cee5fb0c9118ab3c21fe4f8b245 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 17:29:03 -0300 Subject: [media] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix Those functions are specific to video nodes, rename them for consistency. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 6b9f115746b2..d616cbeb100a 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -298,9 +298,9 @@ static int __vsp1_video_try_format(struct vsp1_video *video, * Pipeline Management */ -static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe, - struct vsp1_rwpf *input, - struct vsp1_rwpf *output) +static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, + struct vsp1_rwpf *input, + struct vsp1_rwpf *output) { struct vsp1_entity *entity; struct media_entity_enum ent_enum; @@ -391,8 +391,8 @@ out: return rval; } -static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, - struct vsp1_video *video) +static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, + struct vsp1_video *video) { struct media_entity_graph graph; struct media_entity *entity = &video->video.entity; @@ -452,8 +452,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, * contains no loop and that all branches end at the output WPF. */ for (i = 0; i < pipe->num_inputs; ++i) { - ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i], - pipe->output); + ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i], + pipe->output); if (ret < 0) goto error; } @@ -465,8 +465,8 @@ error: return ret; } -static int vsp1_pipeline_init(struct vsp1_pipeline *pipe, - struct vsp1_video *video) +static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe, + struct vsp1_video *video) { int ret; @@ -474,7 +474,7 @@ static int vsp1_pipeline_init(struct vsp1_pipeline *pipe, /* If we're the first user validate and initialize the pipeline. */ if (pipe->use_count == 0) { - ret = vsp1_pipeline_validate(pipe, video); + ret = vsp1_video_pipeline_validate(pipe, video); if (ret < 0) goto done; } @@ -487,7 +487,7 @@ done: return ret; } -static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) +static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe) { mutex_lock(&pipe->lock); @@ -755,7 +755,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) } mutex_unlock(&pipe->lock); - vsp1_pipeline_cleanup(pipe); + vsp1_video_pipeline_cleanup(pipe); media_entity_pipeline_stop(&video->video.entity); /* Remove all buffers from the IRQ queue. */ @@ -896,7 +896,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_stop; - ret = vsp1_pipeline_init(pipe, video); + ret = vsp1_video_pipeline_init(pipe, video); if (ret < 0) goto err_stop; @@ -908,7 +908,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) return 0; err_cleanup: - vsp1_pipeline_cleanup(pipe); + vsp1_video_pipeline_cleanup(pipe); err_stop: media_entity_pipeline_stop(&video->video.entity); return ret; -- cgit v1.2.3 From f294c2f70e5951e0c2033b9dd50ba4d19a5405f1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 17:32:13 -0300 Subject: [media] v4l: vsp1: Extract pipeline initialization code into a function The code will be reused outside of vsp1_video.c. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 10 ++++++++++ drivers/media/platform/vsp1/vsp1_pipe.h | 1 + drivers/media/platform/vsp1/vsp1_video.c | 6 +----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index cdc670b88fcc..584a9d408144 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -49,6 +49,16 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe) pipe->uds = NULL; } +void vsp1_pipeline_init(struct vsp1_pipeline *pipe) +{ + mutex_init(&pipe->lock); + spin_lock_init(&pipe->irqlock); + init_waitqueue_head(&pipe->wq); + + INIT_LIST_HEAD(&pipe->entities); + pipe->state = VSP1_PIPELINE_STOPPED; +} + void vsp1_pipeline_run(struct vsp1_pipeline *pipe) { struct vsp1_device *vsp1 = pipe->output->entity.vsp1; diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index f8a099fba973..8553d5a03aa3 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -67,6 +67,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) } void vsp1_pipeline_reset(struct vsp1_pipeline *pipe); +void vsp1_pipeline_init(struct vsp1_pipeline *pipe); void vsp1_pipeline_run(struct vsp1_pipeline *pipe); bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe); diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index d616cbeb100a..3d5ea4a325ba 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1026,11 +1026,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, spin_lock_init(&video->irqlock); INIT_LIST_HEAD(&video->irqqueue); - mutex_init(&video->pipe.lock); - spin_lock_init(&video->pipe.irqlock); - INIT_LIST_HEAD(&video->pipe.entities); - init_waitqueue_head(&video->pipe.wq); - video->pipe.state = VSP1_PIPELINE_STOPPED; + vsp1_pipeline_init(&video->pipe); video->pipe.frame_end = vsp1_video_pipeline_frame_end; /* Initialize the media entity... */ -- cgit v1.2.3 From f8562f218b634871563260bf06ef33611167fc7a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 17:43:36 -0300 Subject: [media] v4l: vsp1: Reuse local variable instead of recomputing it No need to waste CPU cycles when the value we need is already available. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 3d5ea4a325ba..b1bb63d2a365 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -429,7 +429,7 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, rwpf->video->pipe_index = pipe->num_inputs; } else if (e->type == VSP1_ENTITY_WPF) { rwpf = to_rwpf(subdev); - pipe->output = to_rwpf(subdev); + pipe->output = rwpf; rwpf->video->pipe_index = 0; } else if (e->type == VSP1_ENTITY_LIF) { pipe->lif = e; -- cgit v1.2.3 From a07dcc53b1327064475a3c67be651a9c3ca70e37 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 18:21:12 -0300 Subject: [media] v4l: vsp1: Extract link creation to separate function Link creation will be handled differently for the DU pipeline. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 95 ++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 0fb654e72633..81c49bfdc8dd 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -67,7 +67,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) */ /* - * vsp1_create_links - Create links from all sources to the given sink + * vsp1_create_sink_links - Create links from all sources to the given sink * * This function creates media links from all valid sources to the given sink * pad. Links that would be invalid according to the VSP1 hardware capabilities @@ -76,26 +76,14 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) * - from a UDS to a UDS (UDS entities can't be chained) * - from an entity to itself (no loops are allowed) */ -static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) +static int vsp1_create_sink_links(struct vsp1_device *vsp1, + struct vsp1_entity *sink) { struct media_entity *entity = &sink->subdev.entity; struct vsp1_entity *source; unsigned int pad; int ret; - if (sink->type == VSP1_ENTITY_RPF) { - struct vsp1_rwpf *rpf = to_rwpf(&sink->subdev); - - /* RPFs have no source entities, just connect their source pad - * to their video device. - */ - return media_create_pad_link(&rpf->video->video.entity, 0, - &rpf->entity.subdev.entity, - RWPF_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - } - list_for_each_entry(source, &vsp1->entities, list_dev) { u32 flags; @@ -126,21 +114,63 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) } } - if (sink->type == VSP1_ENTITY_WPF) { - struct vsp1_rwpf *wpf = to_rwpf(&sink->subdev); - unsigned int flags = MEDIA_LNK_FL_ENABLED; + return 0; +} +static int vsp1_create_links(struct vsp1_device *vsp1) +{ + struct vsp1_entity *entity; + unsigned int i; + int ret; + + list_for_each_entry(entity, &vsp1->entities, list_dev) { + if (entity->type == VSP1_ENTITY_LIF || + entity->type == VSP1_ENTITY_RPF) + continue; + + ret = vsp1_create_sink_links(vsp1, entity); + if (ret < 0) + return ret; + } + + if (vsp1->pdata.features & VSP1_HAS_LIF) { + ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity, + RWPF_PAD_SOURCE, + &vsp1->lif->entity.subdev.entity, + LIF_PAD_SINK, 0); + if (ret < 0) + return ret; + } + + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_rwpf *rpf = vsp1->rpf[i]; + + ret = media_create_pad_link(&rpf->video->video.entity, 0, + &rpf->entity.subdev.entity, + RWPF_PAD_SINK, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret < 0) + return ret; + } + + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { /* Connect the video device to the WPF. All connections are * immutable except for the WPF0 source link if a LIF is * present. */ - if (!(vsp1->pdata.features & VSP1_HAS_LIF) || sink->index != 0) + struct vsp1_rwpf *wpf = vsp1->wpf[i]; + unsigned int flags = MEDIA_LNK_FL_ENABLED; + + if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0) flags |= MEDIA_LNK_FL_IMMUTABLE; - return media_create_pad_link(&wpf->entity.subdev.entity, - RWPF_PAD_SOURCE, - &wpf->video->video.entity, - 0, flags); + ret = media_create_pad_link(&wpf->entity.subdev.entity, + RWPF_PAD_SOURCE, + &wpf->video->video.entity, 0, + flags); + if (ret < 0) + return ret; } return 0; @@ -310,22 +340,9 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Create links. */ - list_for_each_entry(entity, &vsp1->entities, list_dev) { - if (entity->type == VSP1_ENTITY_LIF) - continue; - - ret = vsp1_create_links(vsp1, entity); - if (ret < 0) - goto done; - } - - if (vsp1->pdata.features & VSP1_HAS_LIF) { - ret = media_create_pad_link( - &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, - &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); - if (ret < 0) - return ret; - } + ret = vsp1_create_links(vsp1); + if (ret < 0) + goto done; ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); if (ret < 0) -- cgit v1.2.3 From ba3a5c6dc3fe4cf22bb1161d6c82c1f36f579b2d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 18:24:55 -0300 Subject: [media] v4l: vsp1: Document the vsp1_pipeline structure Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 8553d5a03aa3..9c8ded1c29f6 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -29,9 +29,23 @@ enum vsp1_pipeline_state { /* * struct vsp1_pipeline - A VSP1 hardware pipeline - * @media: the media pipeline + * @pipe: the media pipeline * @irqlock: protects the pipeline state + * @state: current state + * @wq: work queue to wait for state change completion + * @frame_end: frame end interrupt handler * @lock: protects the pipeline use count and stream count + * @use_count: number of video nodes using the pipeline + * @stream_count: number of streaming video nodes + * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available + * @num_inputs: number of RPFs + * @inputs: array of RPFs in the pipeline + * @output: WPF at the output of the pipeline + * @bru: BRU entity, if present + * @lif: LIF entity, if present + * @uds: UDS entity, if present + * @uds_input: entity at the input of the UDS, if the UDS is present + * @entities: list of entities in the pipeline */ struct vsp1_pipeline { struct media_pipeline pipe; -- cgit v1.2.3 From 5dc1e5fb47cd7433130fc496d426de45decead15 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Sep 2015 04:55:46 -0300 Subject: [media] v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register bit name Rename the VI6_DISP_IRQ_STA_DSE register bit to VI6_DISP_IRQ_STA_DST to fix a typo and match the datasheet. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 25b48738b147..8173ceaab9f9 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -46,7 +46,7 @@ #define VI6_DISP_IRQ_ENB_LNEE(n) (1 << (n)) #define VI6_DISP_IRQ_STA 0x007c -#define VI6_DISP_IRQ_STA_DSE (1 << 8) +#define VI6_DISP_IRQ_STA_DST (1 << 8) #define VI6_DISP_IRQ_STA_MAE (1 << 5) #define VI6_DISP_IRQ_STA_LNE(n) (1 << (n)) -- cgit v1.2.3 From f6acfcdc5b8cdc9ddd53a459361820b9efe958c4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Sep 2015 11:38:56 -0300 Subject: [media] v4l: vsp1: Set the SRU CTRL0 register when starting the stream Commit 58f896d859ce ("[media] v4l: vsp1: sru: Make the intensity controllable during streaming") refactored the stream start code and removed the SRU CTRL0 register write by mistake. Add it back. Fixes: 58f896d859ce ("[media] v4l: vsp1: sru: Make the intensity controllable during streaming") Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_sru.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 6310acab60e7..d41ae950d1a1 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -154,6 +154,7 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) mutex_lock(sru->ctrls.lock); ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0) & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK); + vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); mutex_unlock(sru->ctrls.lock); vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); -- cgit v1.2.3 From dc3bdddbd0ab550ae955e4f49ba46d7c124bbc32 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Sep 2015 11:32:06 -0300 Subject: [media] v4l: vsp1: Remove unused module read functions Several module read functions are not used, remove them. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 5 ----- drivers/media/platform/vsp1/vsp1_lif.c | 5 ----- drivers/media/platform/vsp1/vsp1_lut.c | 5 ----- drivers/media/platform/vsp1/vsp1_rpf.c | 6 ------ drivers/media/platform/vsp1/vsp1_uds.c | 6 ------ 5 files changed, 27 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index b4cc9bc478af..841bc6664bca 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -28,11 +28,6 @@ * Device Access */ -static inline u32 vsp1_bru_read(struct vsp1_bru *bru, u32 reg) -{ - return vsp1_read(bru->entity.vsp1, reg); -} - static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) { vsp1_write(bru->entity.vsp1, reg, data); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 39fa5ef20fbb..b868bce08982 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -26,11 +26,6 @@ * Device Access */ -static inline u32 vsp1_lif_read(struct vsp1_lif *lif, u32 reg) -{ - return vsp1_read(lif->entity.vsp1, reg); -} - static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) { vsp1_write(lif->entity.vsp1, reg, data); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 656ec272a414..9e33caa9c616 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -27,11 +27,6 @@ * Device Access */ -static inline u32 vsp1_lut_read(struct vsp1_lut *lut, u32 reg) -{ - return vsp1_read(lut->entity.vsp1, reg); -} - static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) { vsp1_write(lut->entity.vsp1, reg, data); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index c0b7f76cd0b5..b9c39f9e4458 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -26,12 +26,6 @@ * Device Access */ -static inline u32 vsp1_rpf_read(struct vsp1_rwpf *rpf, u32 reg) -{ - return vsp1_read(rpf->entity.vsp1, - reg + rpf->entity.index * VI6_RPF_OFFSET); -} - static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) { vsp1_write(rpf->entity.vsp1, diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index ccc8243e3493..27ad07466ebd 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -29,12 +29,6 @@ * Device Access */ -static inline u32 vsp1_uds_read(struct vsp1_uds *uds, u32 reg) -{ - return vsp1_read(uds->entity.vsp1, - reg + uds->entity.index * VI6_UDS_OFFSET); -} - static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) { vsp1_write(uds->entity.vsp1, -- cgit v1.2.3 From 665b693c82ca2f92c1e7d63357a52d21397b05f0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 18:58:31 -0300 Subject: [media] v4l: vsp1: Move entity route setup function to vsp1_entity.c The function will be used by the DU code, move it out of vsp1_video.c. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_entity.c | 12 ++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 2 ++ drivers/media/platform/vsp1/vsp1_video.c | 12 ------------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 46832242a672..479029fd4e90 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -58,6 +58,18 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) return ret; } +void vsp1_entity_route_setup(struct vsp1_entity *source) +{ + struct vsp1_entity *sink; + + if (source->route->reg == 0) + return; + + sink = container_of(source->sink, struct vsp1_entity, subdev.entity); + vsp1_write(source->vsp1, source->route->reg, + sink->route->inputs[source->sink_pad]); +} + /* ----------------------------------------------------------------------------- * V4L2 Subdevice Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 9c95507ec762..9606d0d21263 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -96,4 +96,6 @@ void vsp1_entity_init_formats(struct v4l2_subdev *subdev, bool vsp1_entity_is_streaming(struct vsp1_entity *entity); int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); +void vsp1_entity_route_setup(struct vsp1_entity *source); + #endif /* __VSP1_ENTITY_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index b1bb63d2a365..7cf73d4f0963 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -674,18 +674,6 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&pipe->irqlock, flags); } -static void vsp1_entity_route_setup(struct vsp1_entity *source) -{ - struct vsp1_entity *sink; - - if (source->route->reg == 0) - return; - - sink = container_of(source->sink, struct vsp1_entity, subdev.entity); - vsp1_write(source->vsp1, source->route->reg, - sink->route->inputs[source->sink_pad]); -} - static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) { struct vsp1_video *video = vb2_get_drv_priv(vq); -- cgit v1.2.3 From a96c5fa4502eec35972c9236636bd3f7af8bf69f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 3 Aug 2015 09:46:26 -0300 Subject: [media] v4l: vsp1: Make number of BRU inputs configurable The R-Car Gen3 family has 5-inputs BRUs, support them by making the number of BRU inputs configurable. As the driver assumes that the number of BRU inputs is equal to the number of RPFs, replace the BRU_MAX_INPUTS macro with VSP1_MAX_RPF to make the assumption apparent. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 + drivers/media/platform/vsp1/vsp1_bru.c | 19 ++++++++++--------- drivers/media/platform/vsp1/vsp1_bru.h | 3 +-- drivers/media/platform/vsp1/vsp1_drv.c | 3 +++ drivers/media/platform/vsp1/vsp1_entity.h | 4 +++- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index b25032bd37a7..29a8fd94a0aa 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -48,6 +48,7 @@ struct vsp1_platform_data { unsigned int rpf_count; unsigned int uds_count; unsigned int wpf_count; + unsigned int num_bru_inputs; }; struct vsp1_device { diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 841bc6664bca..baebfbbef61d 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -79,7 +79,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) if (!enable) return 0; - format = &bru->entity.formats[BRU_PAD_SOURCE]; + format = &bru->entity.formats[bru->entity.source_pad]; /* The hardware is extremely flexible but we have no userspace API to * expose all the parameters, nor is it clear whether we would have use @@ -109,7 +109,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) VI6_BRU_ROP_CROP(VI6_ROP_NOP) | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); - for (i = 0; i < 4; ++i) { + for (i = 0; i < bru->entity.source_pad; ++i) { bool premultiplied = false; u32 ctrl = 0; @@ -291,7 +291,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con *format = fmt->format; /* Reset the compose rectangle */ - if (fmt->pad != BRU_PAD_SOURCE) { + if (fmt->pad != bru->entity.source_pad) { struct v4l2_rect *compose; compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which); @@ -305,7 +305,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con if (fmt->pad == BRU_PAD_SINK(0)) { unsigned int i; - for (i = 0; i <= BRU_PAD_SOURCE; ++i) { + for (i = 0; i <= bru->entity.source_pad; ++i) { format = vsp1_entity_get_pad_format(&bru->entity, cfg, i, fmt->which); format->code = fmt->format.code; @@ -321,7 +321,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev, { struct vsp1_bru *bru = to_bru(subdev); - if (sel->pad == BRU_PAD_SOURCE) + if (sel->pad == bru->entity.source_pad) return -EINVAL; switch (sel->target) { @@ -349,7 +349,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *format; struct v4l2_rect *compose; - if (sel->pad == BRU_PAD_SOURCE) + if (sel->pad == bru->entity.source_pad) return -EINVAL; if (sel->target != V4L2_SEL_TGT_COMPOSE) @@ -358,8 +358,8 @@ static int bru_set_selection(struct v4l2_subdev *subdev, /* The compose rectangle top left corner must be inside the output * frame. */ - format = vsp1_entity_get_pad_format(&bru->entity, cfg, BRU_PAD_SOURCE, - sel->which); + format = vsp1_entity_get_pad_format(&bru->entity, cfg, + bru->entity.source_pad, sel->which); sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); @@ -415,7 +415,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) bru->entity.type = VSP1_ENTITY_BRU; - ret = vsp1_entity_init(vsp1, &bru->entity, 5); + ret = vsp1_entity_init(vsp1, &bru->entity, + vsp1->pdata.num_bru_inputs + 1); if (ret < 0) return ERR_PTR(ret); diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h index 16b1c6554911..dbac9686ea69 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.h +++ b/drivers/media/platform/vsp1/vsp1_bru.h @@ -23,7 +23,6 @@ struct vsp1_device; struct vsp1_rwpf; #define BRU_PAD_SINK(n) (n) -#define BRU_PAD_SOURCE 4 struct vsp1_bru { struct vsp1_entity entity; @@ -33,7 +32,7 @@ struct vsp1_bru { struct { struct vsp1_rwpf *rpf; struct v4l2_rect compose; - } inputs[4]; + } inputs[VSP1_MAX_RPF]; }; static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 81c49bfdc8dd..447f2bfe89f9 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -540,6 +541,8 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1) return -EINVAL; } + pdata->num_bru_inputs = 4; + return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 9606d0d21263..360a2e668ac2 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -32,6 +32,8 @@ enum vsp1_entity_type { VSP1_ENTITY_WPF, }; +#define VSP1_ENTITY_MAX_INPUTS 5 /* For the BRU */ + /* * struct vsp1_route - Entity routing configuration * @type: Entity type this routing entry is associated with @@ -48,7 +50,7 @@ struct vsp1_route { enum vsp1_entity_type type; unsigned int index; unsigned int reg; - unsigned int inputs[4]; + unsigned int inputs[VSP1_ENTITY_MAX_INPUTS]; }; struct vsp1_entity { -- cgit v1.2.3 From f74be41221913b42adbca55890fd9a9282312b74 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 14 Aug 2015 13:53:45 -0300 Subject: [media] v4l: vsp1: Make the BRU optional Not all VSP instances have a BRU on R-Car Gen3, make it optional. Set the feature unconditionally for now, this will be fixed when adding Gen3 support. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 29a8fd94a0aa..d980f32aac0b 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -42,6 +42,7 @@ struct vsp1_uds; #define VSP1_HAS_LIF (1 << 0) #define VSP1_HAS_LUT (1 << 1) #define VSP1_HAS_SRU (1 << 2) +#define VSP1_HAS_BRU (1 << 3) struct vsp1_platform_data { unsigned int features; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 447f2bfe89f9..8d67a06c86ea 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -220,13 +220,15 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Instantiate all the entities. */ - vsp1->bru = vsp1_bru_create(vsp1); - if (IS_ERR(vsp1->bru)) { - ret = PTR_ERR(vsp1->bru); - goto done; - } + if (vsp1->pdata.features & VSP1_HAS_BRU) { + vsp1->bru = vsp1_bru_create(vsp1); + if (IS_ERR(vsp1->bru)) { + ret = PTR_ERR(vsp1->bru); + goto done; + } - list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities); + list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities); + } vsp1->hsi = vsp1_hsit_create(vsp1, true); if (IS_ERR(vsp1->hsi)) { @@ -541,6 +543,7 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1) return -EINVAL; } + pdata->features |= VSP1_HAS_BRU; pdata->num_bru_inputs = 4; return 0; -- cgit v1.2.3 From c618b185fd98369e630a6ecc063da1e35da61de3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 3 Aug 2015 10:21:49 -0300 Subject: [media] v4l: vsp1: Move format info to vsp1_pipe.c Format information and the related helper function are not specific to the V4L2 API, move them from vsp1_video.c to vsp1_pipe.c. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 130 +++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_pipe.h | 29 +++++++ drivers/media/platform/vsp1/vsp1_video.c | 127 ------------------------------ drivers/media/platform/vsp1/vsp1_video.h | 27 ------- 4 files changed, 159 insertions(+), 154 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 584a9d408144..b850aeb885bf 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -25,6 +25,136 @@ #include "vsp1_rwpf.h" #include "vsp1_uds.h" +/* ----------------------------------------------------------------------------- + * Helper Functions + */ + +static const struct vsp1_format_info vsp1_video_formats[] = { + { V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 8, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 24, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 24, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 32, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 16, 0, 0 }, false, false, 2, 1, false }, + { V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 16, 0, 0 }, false, true, 2, 1, false }, + { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 16, 0, 0 }, true, false, 2, 1, false }, + { V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 16, 0, 0 }, true, true, 2, 1, false }, + { V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 2, { 8, 16, 0 }, false, false, 2, 2, false }, + { V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 2, { 8, 16, 0 }, false, true, 2, 2, false }, + { V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 2, { 8, 16, 0 }, false, false, 2, 1, false }, + { V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 2, { 8, 16, 0 }, false, true, 2, 1, false }, + { V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 2, 2, false }, + { V4L2_PIX_FMT_YVU420M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 2, 2, false }, + { V4L2_PIX_FMT_YUV422M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 2, 1, false }, + { V4L2_PIX_FMT_YVU422M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 2, 1, false }, + { V4L2_PIX_FMT_YUV444M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_YVU444M, MEDIA_BUS_FMT_AYUV8_1X32, + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 1, 1, false }, +}; + +/* + * vsp1_get_format_info - Retrieve format information for a 4CC + * @fourcc: the format 4CC + * + * Return a pointer to the format information structure corresponding to the + * given V4L2 format 4CC, or NULL if no corresponding format can be found. + */ +const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) { + const struct vsp1_format_info *info = &vsp1_video_formats[i]; + + if (info->fourcc == fourcc) + return info; + } + + return NULL; +} + /* ----------------------------------------------------------------------------- * Pipeline Management */ diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 9c8ded1c29f6..f9035c739e9a 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -21,6 +21,33 @@ struct vsp1_rwpf; +/* + * struct vsp1_format_info - VSP1 video format description + * @mbus: media bus format code + * @fourcc: V4L2 pixel format FCC identifier + * @planes: number of planes + * @bpp: bits per pixel + * @hwfmt: VSP1 hardware format + * @swap_yc: the Y and C components are swapped (Y comes before C) + * @swap_uv: the U and V components are swapped (V comes before U) + * @hsub: horizontal subsampling factor + * @vsub: vertical subsampling factor + * @alpha: has an alpha channel + */ +struct vsp1_format_info { + u32 fourcc; + unsigned int mbus; + unsigned int hwfmt; + unsigned int swap; + unsigned int planes; + unsigned int bpp[3]; + bool swap_yc; + bool swap_uv; + unsigned int hsub; + unsigned int vsub; + bool alpha; +}; + enum vsp1_pipeline_state { VSP1_PIPELINE_STOPPED, VSP1_PIPELINE_RUNNING, @@ -97,4 +124,6 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, void vsp1_pipelines_suspend(struct vsp1_device *vsp1); void vsp1_pipelines_resume(struct vsp1_device *vsp1); +const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc); + #endif /* __VSP1_PIPE_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 7cf73d4f0963..92eb39c509df 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -48,133 +48,6 @@ * Helper functions */ -static const struct vsp1_format_info vsp1_video_formats[] = { - { V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 8, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, true }, - { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, true }, - { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, true }, - { V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS, - 1, { 16, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 24, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 24, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, - 1, { 32, 0, 0 }, false, false, 1, 1, true }, - { V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, - 1, { 32, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 32, 0, 0 }, false, false, 1, 1, true }, - { V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32, - VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 32, 0, 0 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 16, 0, 0 }, false, false, 2, 1, false }, - { V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 16, 0, 0 }, false, true, 2, 1, false }, - { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 16, 0, 0 }, true, false, 2, 1, false }, - { V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 1, { 16, 0, 0 }, true, true, 2, 1, false }, - { V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 2, { 8, 16, 0 }, false, false, 2, 2, false }, - { V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 2, { 8, 16, 0 }, false, true, 2, 2, false }, - { V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 2, { 8, 16, 0 }, false, false, 2, 1, false }, - { V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 2, { 8, 16, 0 }, false, true, 2, 1, false }, - { V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, false, 2, 2, false }, - { V4L2_PIX_FMT_YVU420M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, true, 2, 2, false }, - { V4L2_PIX_FMT_YUV422M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, false, 2, 1, false }, - { V4L2_PIX_FMT_YVU422M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, true, 2, 1, false }, - { V4L2_PIX_FMT_YUV444M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, false, 1, 1, false }, - { V4L2_PIX_FMT_YVU444M, MEDIA_BUS_FMT_AYUV8_1X32, - VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | - VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, - 3, { 8, 8, 8 }, false, true, 1, 1, false }, -}; - -/* - * vsp1_get_format_info - Retrieve format information for a 4CC - * @fourcc: the format 4CC - * - * Return a pointer to the format information structure corresponding to the - * given V4L2 format 4CC, or NULL if no corresponding format can be found. - */ -static const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) { - const struct vsp1_format_info *info = &vsp1_video_formats[i]; - - if (info->fourcc == fourcc) - return info; - } - - return NULL; -} - - static struct v4l2_subdev * vsp1_video_remote_subdev(struct media_pad *local, u32 *pad) { diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index faccb2aede5c..64abd39ee1e7 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -21,33 +21,6 @@ #include "vsp1_pipe.h" #include "vsp1_rwpf.h" -/* - * struct vsp1_format_info - VSP1 video format description - * @mbus: media bus format code - * @fourcc: V4L2 pixel format FCC identifier - * @planes: number of planes - * @bpp: bits per pixel - * @hwfmt: VSP1 hardware format - * @swap_yc: the Y and C components are swapped (Y comes before C) - * @swap_uv: the U and V components are swapped (V comes before U) - * @hsub: horizontal subsampling factor - * @vsub: vertical subsampling factor - * @alpha: has an alpha channel - */ -struct vsp1_format_info { - u32 fourcc; - unsigned int mbus; - unsigned int hwfmt; - unsigned int swap; - unsigned int planes; - unsigned int bpp[3]; - bool swap_yc; - bool swap_uv; - unsigned int hsub; - unsigned int vsub; - bool alpha; -}; - struct vsp1_vb2_buffer { struct vb2_v4l2_buffer buf; struct list_head queue; -- cgit v1.2.3 From f2ed459db7a1537cddc50a58ee26df6b8f3fbe1f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jul 2015 16:16:05 -0300 Subject: [media] v4l: vsp1: Make the userspace API optional The R-Car Gen3 SoCs include VSP instances dedicated to the DU that will be controlled entirely by the rcar-du-drm driver through the KMS API. To support that use case make the userspace V4L2 API optional. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 46 +++++++++++++++++++------------ drivers/media/platform/vsp1/vsp1_entity.c | 2 +- drivers/media/platform/vsp1/vsp1_sru.c | 6 ++-- drivers/media/platform/vsp1/vsp1_wpf.c | 6 ++-- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index d980f32aac0b..4fd4386a7049 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -50,6 +50,7 @@ struct vsp1_platform_data { unsigned int uds_count; unsigned int wpf_count; unsigned int num_bru_inputs; + bool uapi; }; struct vsp1_device { diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 8d67a06c86ea..63892b2f4484 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -143,6 +143,9 @@ static int vsp1_create_links(struct vsp1_device *vsp1) return ret; } + if (!vsp1->pdata.uapi) + return 0; + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i]; @@ -267,7 +270,6 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } for (i = 0; i < vsp1->pdata.rpf_count; ++i) { - struct vsp1_video *video; struct vsp1_rwpf *rpf; rpf = vsp1_rpf_create(vsp1, i); @@ -279,13 +281,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->rpf[i] = rpf; list_add_tail(&rpf->entity.list_dev, &vsp1->entities); - video = vsp1_video_create(vsp1, rpf); - if (IS_ERR(video)) { - ret = PTR_ERR(video); - goto done; - } + if (vsp1->pdata.uapi) { + struct vsp1_video *video = vsp1_video_create(vsp1, rpf); - list_add_tail(&video->list, &vsp1->videos); + if (IS_ERR(video)) { + ret = PTR_ERR(video); + goto done; + } + + list_add_tail(&video->list, &vsp1->videos); + } } if (vsp1->pdata.features & VSP1_HAS_SRU) { @@ -312,7 +317,6 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } for (i = 0; i < vsp1->pdata.wpf_count; ++i) { - struct vsp1_video *video; struct vsp1_rwpf *wpf; wpf = vsp1_wpf_create(vsp1, i); @@ -324,14 +328,17 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->wpf[i] = wpf; list_add_tail(&wpf->entity.list_dev, &vsp1->entities); - video = vsp1_video_create(vsp1, wpf); - if (IS_ERR(video)) { - ret = PTR_ERR(video); - goto done; - } + if (vsp1->pdata.uapi) { + struct vsp1_video *video = vsp1_video_create(vsp1, wpf); - list_add_tail(&video->list, &vsp1->videos); - wpf->entity.sink = &video->video.entity; + if (IS_ERR(video)) { + ret = PTR_ERR(video); + goto done; + } + + list_add_tail(&video->list, &vsp1->videos); + wpf->entity.sink = &video->video.entity; + } } /* Register all subdevs. */ @@ -347,9 +354,11 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) if (ret < 0) goto done; - ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); - if (ret < 0) - goto done; + if (vsp1->pdata.uapi) { + ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); + if (ret < 0) + goto done; + } ret = media_device_register(mdev); @@ -545,6 +554,7 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1) pdata->features |= VSP1_HAS_BRU; pdata->num_bru_inputs = 4; + pdata->uapi = true; return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 479029fd4e90..338a1b0b4fad 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -45,7 +45,7 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) if (!streaming) return 0; - if (!entity->subdev.ctrl_handler) + if (!entity->vsp1->pdata.uapi || !entity->subdev.ctrl_handler) return 0; ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler); diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index d41ae950d1a1..cff4a1d82e3b 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -151,11 +151,13 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) /* Take the control handler lock to ensure that the CTRL0 value won't be * changed behind our back by a set control operation. */ - mutex_lock(sru->ctrls.lock); + if (sru->entity.vsp1->pdata.uapi) + mutex_lock(sru->ctrls.lock); ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0) & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK); vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); - mutex_unlock(sru->ctrls.lock); + if (sru->entity.vsp1->pdata.uapi) + mutex_unlock(sru->ctrls.lock); vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d2537b46fc46..184a7e01aad5 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -151,10 +151,12 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) /* Take the control handler lock to ensure that the PDV value won't be * changed behind our back by a set control operation. */ - mutex_lock(wpf->ctrls.lock); + if (vsp1->pdata.uapi) + mutex_lock(wpf->ctrls.lock); outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK; vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); - mutex_unlock(wpf->ctrls.lock); + if (vsp1->pdata.uapi) + mutex_unlock(wpf->ctrls.lock); vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), VI6_DPR_WPF_FPORCH_FP_WPFN); -- cgit v1.2.3 From 96bfa6a5fd1dc5a7f2b5cd6f58bdcf1501146d17 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 5 Aug 2015 16:40:31 -0300 Subject: [media] v4l: vsp1: Make pipeline inputs array index by RPF index The pipeline inputs array stores pointers to all RPFs contained in the pipeline. It's currently indexed contiguously by adding RPFs in the order they are found during graph walk. This can't easily support dynamic addition and removal of RPFs while streaming, which will be required for combined VSP+DU support. Make the array indexed by RPF index instead and skip NULL elements when iterating over RPFs. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +++++- drivers/media/platform/vsp1/vsp1_pipe.h | 2 +- drivers/media/platform/vsp1/vsp1_video.c | 16 ++++++++++++---- drivers/media/platform/vsp1/vsp1_wpf.c | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index b850aeb885bf..05d4c3870cff 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -161,14 +161,18 @@ const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc) void vsp1_pipeline_reset(struct vsp1_pipeline *pipe) { + unsigned int i; + if (pipe->bru) { struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); - unsigned int i; for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i) bru->inputs[i].rpf = NULL; } + for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) + pipe->inputs[i] = NULL; + INIT_LIST_HEAD(&pipe->entities); pipe->state = VSP1_PIPELINE_STOPPED; pipe->buffers_ready = 0; diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index f9035c739e9a..c4c300561c5c 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -66,7 +66,7 @@ enum vsp1_pipeline_state { * @stream_count: number of streaming video nodes * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available * @num_inputs: number of RPFs - * @inputs: array of RPFs in the pipeline + * @inputs: array of RPFs in the pipeline (indexed by RPF index) * @output: WPF at the output of the pipeline * @bru: BRU entity, if present * @lif: LIF entity, if present diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 92eb39c509df..b2eecabdc399 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -298,8 +298,8 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, if (e->type == VSP1_ENTITY_RPF) { rwpf = to_rwpf(subdev); - pipe->inputs[pipe->num_inputs++] = rwpf; - rwpf->video->pipe_index = pipe->num_inputs; + pipe->inputs[rwpf->entity.index] = rwpf; + rwpf->video->pipe_index = ++pipe->num_inputs; } else if (e->type == VSP1_ENTITY_WPF) { rwpf = to_rwpf(subdev); pipe->output = rwpf; @@ -324,7 +324,10 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, /* Follow links downstream for each input and make sure the graph * contains no loop and that all branches end at the output WPF. */ - for (i = 0; i < pipe->num_inputs; ++i) { + for (i = 0; i < video->vsp1->pdata.rpf_count; ++i) { + if (!pipe->inputs[i]) + continue; + ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i], pipe->output); if (ret < 0) @@ -449,11 +452,16 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) { + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; unsigned int i; /* Complete buffers on all video nodes. */ - for (i = 0; i < pipe->num_inputs; ++i) + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + if (!pipe->inputs[i]) + continue; + vsp1_video_frame_end(pipe, pipe->inputs[i]); + } if (!pipe->lif) vsp1_video_frame_end(pipe, pipe->output); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 184a7e01aad5..d0edcde721bd 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -97,9 +97,12 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) * inputs as sub-layers and select the virtual RPF as the master * layer. */ - for (i = 0; i < pipe->num_inputs; ++i) { + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { struct vsp1_rwpf *input = pipe->inputs[i]; + if (!input) + continue; + srcrpf |= (!pipe->bru && pipe->num_inputs == 1) ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); -- cgit v1.2.3 From 3dbb6100146666df45ef83d1552d4da097c60f72 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 5 Aug 2015 16:57:35 -0300 Subject: [media] v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream handlers The RPF and WPF alpha values are set through V4L2 controls and applied when starting the video stream by a call to v4l2_ctrl_handler_setup(). As that function uses the control handler mutex it can't be called in interrupt context, where the VSP+DU pipeline handler might need to reconfigure the pipeline. Set the alpha value manually in the RPF and WPF s_stream handler to ensure that the hardware is properly configured even when controlled without the userspace API. If the userspace API is enabled protect that with the control lock to avoid race conditions with userspace. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 16 ++++++++++++++-- drivers/media/platform/vsp1/vsp1_rwpf.h | 2 ++ drivers/media/platform/vsp1/vsp1_wpf.c | 7 ++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index b9c39f9e4458..b1d4a46f230e 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -68,7 +68,9 @@ static const struct v4l2_ctrl_ops rpf_ctrl_ops = { static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) { + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_rwpf *rpf = to_rwpf(subdev); + struct vsp1_device *vsp1 = rpf->entity.vsp1; const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_rect *crop = &rpf->crop; @@ -148,6 +150,15 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); + + if (vsp1->pdata.uapi) + mutex_lock(rpf->ctrls.lock); + vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, + rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); + vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val); + if (vsp1->pdata.uapi) + mutex_unlock(rpf->ctrls.lock); + vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); @@ -245,8 +256,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) /* Initialize the control handler. */ v4l2_ctrl_handler_init(&rpf->ctrls, 1); - v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, - 0, 255, 1, 255); + rpf->alpha = v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, + V4L2_CID_ALPHA_COMPONENT, + 0, 255, 1, 255); rpf->entity.subdev.ctrl_handler = &rpf->ctrls; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 1a90c7c8e972..8e8235682ada 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -23,6 +23,7 @@ #define RWPF_PAD_SINK 0 #define RWPF_PAD_SOURCE 1 +struct v4l2_ctrl; struct vsp1_rwpf; struct vsp1_video; @@ -40,6 +41,7 @@ struct vsp1_rwpf_operations { struct vsp1_rwpf { struct vsp1_entity entity; struct v4l2_ctrl_handler ctrls; + struct v4l2_ctrl *alpha; struct vsp1_video *video; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index d0edcde721bd..40eeaf2d76d2 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -156,7 +156,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) */ if (vsp1->pdata.uapi) mutex_lock(wpf->ctrls.lock); - outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK; + outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT; vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); if (vsp1->pdata.uapi) mutex_unlock(wpf->ctrls.lock); @@ -254,8 +254,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) /* Initialize the control handler. */ v4l2_ctrl_handler_init(&wpf->ctrls, 1); - v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, - 0, 255, 1, 255); + wpf->alpha = v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, + V4L2_CID_ALPHA_COMPONENT, + 0, 255, 1, 255); wpf->entity.subdev.ctrl_handler = &wpf->ctrls; -- cgit v1.2.3 From babca007e7c7943215052c95bebfdaac0ca0db7c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 5 Aug 2015 17:14:41 -0300 Subject: [media] v4l: vsp1: Don't validate links when the userspace API is disabled As the pipeline is configured internally by the driver when the userspace API is disabled its configuration can be trusted and link validation isn't needed. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1.h | 2 ++ drivers/media/platform/vsp1/vsp1_bru.c | 2 +- drivers/media/platform/vsp1/vsp1_drv.c | 10 ++++++++++ drivers/media/platform/vsp1/vsp1_entity.c | 11 +++-------- drivers/media/platform/vsp1/vsp1_entity.h | 5 ++++- drivers/media/platform/vsp1/vsp1_hsit.c | 2 +- drivers/media/platform/vsp1/vsp1_lif.c | 2 +- drivers/media/platform/vsp1/vsp1_lut.c | 2 +- drivers/media/platform/vsp1/vsp1_rpf.c | 2 +- drivers/media/platform/vsp1/vsp1_sru.c | 2 +- drivers/media/platform/vsp1/vsp1_uds.c | 2 +- drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- 12 files changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 4fd4386a7049..454201bf59ee 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -78,6 +78,8 @@ struct vsp1_device { struct v4l2_device v4l2_dev; struct media_device media_dev; + + struct media_entity_operations media_ops; }; int vsp1_device_get(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index baebfbbef61d..848bfb5a42ff 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -424,7 +424,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) subdev = &bru->entity.subdev; v4l2_subdev_init(subdev, &bru_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s bru", dev_name(vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 63892b2f4484..1e10fc4723c5 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -21,6 +21,8 @@ #include #include +#include + #include "vsp1.h" #include "vsp1_bru.h" #include "vsp1_hsit.h" @@ -214,6 +216,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) dev_name(mdev->dev)); media_device_init(mdev); + vsp1->media_ops.link_setup = vsp1_entity_link_setup; + /* Don't perform link validation when the userspace API is disabled as + * the pipeline is configured internally by the driver in that case, and + * its configuration can thus be trusted. + */ + if (vsp1->pdata.uapi) + vsp1->media_ops.link_validate = v4l2_subdev_link_validate; + vdev->mdev = mdev; ret = v4l2_device_register(vsp1->dev, vdev); if (ret < 0) { diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 338a1b0b4fad..03523899d7d0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -131,9 +131,9 @@ const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = { * Media Operations */ -static int vsp1_entity_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) +int vsp1_entity_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) { struct vsp1_entity *source; @@ -158,11 +158,6 @@ static int vsp1_entity_link_setup(struct media_entity *entity, return 0; } -const struct media_entity_operations vsp1_media_ops = { - .link_setup = vsp1_entity_link_setup, - .link_validate = v4l2_subdev_link_validate, -}; - /* ----------------------------------------------------------------------------- * Initialization */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 360a2e668ac2..83570dfde8ec 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -86,7 +86,10 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, void vsp1_entity_destroy(struct vsp1_entity *entity); extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops; -extern const struct media_entity_operations vsp1_media_ops; + +int vsp1_entity_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags); struct v4l2_mbus_framefmt * vsp1_entity_get_pad_format(struct vsp1_entity *entity, diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 8ffb817ae525..c1087cff31a0 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -203,7 +203,7 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) subdev = &hsit->entity.subdev; v4l2_subdev_init(subdev, &hsit_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s %s", dev_name(vsp1->dev), inverse ? "hsi" : "hst"); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b868bce08982..b8e73d32d14d 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -223,7 +223,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) subdev = &lif->entity.subdev; v4l2_subdev_init(subdev, &lif_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s lif", dev_name(vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 9e33caa9c616..4b89095e7b5f 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -237,7 +237,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) subdev = &lut->entity.subdev; v4l2_subdev_init(subdev, &lut_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s lut", dev_name(vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index b1d4a46f230e..3992da09e466 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -245,7 +245,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) subdev = &rpf->entity.subdev; v4l2_subdev_init(subdev, &rpf_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u", dev_name(vsp1->dev), index); diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index cff4a1d82e3b..6dcf76a1ca57 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -363,7 +363,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) subdev = &sru->entity.subdev; v4l2_subdev_init(subdev, &sru_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s sru", dev_name(vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 27ad07466ebd..bba67770cf95 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -338,7 +338,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) subdev = &uds->entity.subdev; v4l2_subdev_init(subdev, &uds_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u", dev_name(vsp1->dev), index); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 40eeaf2d76d2..849ed81d86a1 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -243,7 +243,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) subdev = &wpf->entity.subdev; v4l2_subdev_init(subdev, &wpf_ops); - subdev->entity.ops = &vsp1_media_ops; + subdev->entity.ops = &vsp1->media_ops; subdev->internal_ops = &vsp1_subdev_internal_ops; snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", dev_name(vsp1->dev), index); -- cgit v1.2.3 From f3af9572e85447102202c644c50c7460009d1cae Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 Aug 2015 18:37:01 -0300 Subject: [media] v4l: vsp1: Add VSP+DU support Implement internal control of the VSP pipeline to be used by the DU DRM/KMS driver when using the VSP as an internal composer handled through DRM/KMS only. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 3 +- drivers/media/platform/vsp1/vsp1_drm.c | 552 +++++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_drm.h | 26 ++ drivers/media/platform/vsp1/vsp1_drv.c | 23 +- include/media/vsp1.h | 30 ++ 6 files changed, 625 insertions(+), 11 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_drm.c create mode 100644 drivers/media/platform/vsp1/vsp1_drm.h create mode 100644 include/media/vsp1.h diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 0ef0b5384125..447e72a2ef43 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,5 +1,5 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_pipe.o -vsp1-y += vsp1_video.o +vsp1-y += vsp1_drm.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 454201bf59ee..67a026ae88cb 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -26,6 +26,7 @@ struct clk; struct device; +struct vsp1_drm; struct vsp1_platform_data; struct vsp1_bru; struct vsp1_hsit; @@ -78,8 +79,8 @@ struct vsp1_device { struct v4l2_device v4l2_dev; struct media_device media_dev; - struct media_entity_operations media_ops; + struct vsp1_drm *drm; }; int vsp1_device_get(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c new file mode 100644 index 000000000000..ac81ff10c339 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -0,0 +1,552 @@ +/* + * vsp1_drm.c -- R-Car VSP1 DRM API + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 +#include +#include + +#include +#include + +#include "vsp1.h" +#include "vsp1_bru.h" +#include "vsp1_drm.h" +#include "vsp1_lif.h" +#include "vsp1_pipe.h" +#include "vsp1_rwpf.h" + +/* ----------------------------------------------------------------------------- + * Runtime Handling + */ + +static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe) +{ + struct vsp1_device *vsp1 = pipe->output->entity.vsp1; + int ret; + + if (vsp1->drm->update) { + struct vsp1_entity *entity; + + list_for_each_entry(entity, &pipe->entities, list_pipe) { + /* Skip unused RPFs. */ + if (entity->type == VSP1_ENTITY_RPF) { + struct vsp1_rwpf *rpf = + to_rwpf(&entity->subdev); + + if (!pipe->inputs[rpf->entity.index]) + continue; + } + + vsp1_entity_route_setup(entity); + + ret = v4l2_subdev_call(&entity->subdev, video, + s_stream, 1); + if (ret < 0) { + dev_err(vsp1->dev, + "DRM pipeline start failure on entity %s\n", + entity->subdev.name); + return ret; + } + } + + vsp1->drm->update = false; + } + + vsp1_pipeline_run(pipe); + + return 0; +} + +static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + unsigned long flags; + + spin_lock_irqsave(&pipe->irqlock, flags); + if (pipe->num_inputs) + vsp1_drm_pipeline_run(pipe); + spin_unlock_irqrestore(&pipe->irqlock, flags); +} + +/* ----------------------------------------------------------------------------- + * DU Driver API + */ + +int vsp1_du_init(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + + if (!vsp1) + return -EPROBE_DEFER; + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_init); + +/** + * vsp1_du_setup_lif - Setup the output part of the VSP pipeline + * @dev: the VSP device + * @width: output frame width in pixels + * @height: output frame height in pixels + * + * Configure the output part of VSP DRM pipeline for the given frame @width and + * @height. This sets up formats on the BRU source pad, the WPF0 sink and source + * pads, and the LIF sink pad. + * + * As the media bus code on the BRU source pad is conditioned by the + * configuration of the BRU sink 0 pad, we also set up the formats on all BRU + * sinks, even if the configuration will be overwritten later by + * vsp1_du_setup_rpf(). This ensures that the BRU configuration is set to a well + * defined state. + * + * Return 0 on success or a negative error code on failure. + */ +int vsp1_du_setup_lif(struct device *dev, unsigned int width, + unsigned int height) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + struct vsp1_bru *bru = vsp1->bru; + struct v4l2_subdev_format format; + unsigned int i; + int ret; + + dev_dbg(vsp1->dev, "%s: configuring LIF with format %ux%u\n", + __func__, width, height); + + if (width == 0 || height == 0) { + /* Zero width or height means the CRTC is being disabled, stop + * the pipeline and turn the light off. + */ + ret = vsp1_pipeline_stop(pipe); + if (ret == -ETIMEDOUT) + dev_err(vsp1->dev, "DRM pipeline stop timeout\n"); + + media_entity_pipeline_stop(&pipe->output->entity.subdev.entity); + + for (i = 0; i < bru->entity.source_pad; ++i) { + bru->inputs[i].rpf = NULL; + pipe->inputs[i] = NULL; + } + + pipe->num_inputs = 0; + + vsp1_device_put(vsp1); + + dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__); + + return 0; + } + + /* Configure the format at the BRU sinks and propagate it through the + * pipeline. + */ + memset(&format, 0, sizeof(format)); + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + for (i = 0; i < bru->entity.source_pad; ++i) { + format.pad = i; + + format.format.width = width; + format.format.height = height; + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, + set_fmt, NULL, &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, i); + } + + format.pad = bru->entity.source_pad; + format.format.width = width; + format.format.height = height; + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, i); + + format.pad = RWPF_PAD_SINK; + ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF0 sink\n", + __func__, format.format.width, format.format.height, + format.format.code); + + format.pad = RWPF_PAD_SOURCE; + ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF0 source\n", + __func__, format.format.width, format.format.height, + format.format.code); + + format.pad = LIF_PAD_SINK; + ret = v4l2_subdev_call(&vsp1->lif->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF sink\n", + __func__, format.format.width, format.format.height, + format.format.code); + + /* Verify that the format at the output of the pipeline matches the + * requested frame size and media bus code. + */ + if (format.format.width != width || format.format.height != height || + format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) { + dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__); + return -EPIPE; + } + + /* Mark the pipeline as streaming and enable the VSP1. This will store + * the pipeline pointer in all entities, which the s_stream handlers + * will need. We don't start the entities themselves right at this point + * as there's no plane configured yet, so we can't start processing + * buffers. + */ + ret = vsp1_device_get(vsp1); + if (ret < 0) + return ret; + + ret = media_entity_pipeline_start(&pipe->output->entity.subdev.entity, + &pipe->pipe); + if (ret < 0) { + dev_dbg(vsp1->dev, "%s: pipeline start failed\n", __func__); + vsp1_device_put(vsp1); + return ret; + } + + dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); + +/** + * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline + * @dev: the VSP device + * @rpf_index: index of the RPF to setup (0-based) + * @pixelformat: V4L2 pixel format for the RPF memory input + * @pitch: number of bytes per line in the image stored in memory + * @mem: DMA addresses of the memory buffers (one per plane) + * @src: the source crop rectangle for the RPF + * @dst: the destination compose rectangle for the BRU input + * + * Configure the VSP to perform composition of the image referenced by @mem + * through RPF @rpf_index, using the @src crop rectangle and the @dst + * composition rectangle. The Z-order is fixed with RPF 0 at the bottom. + * + * Image format as stored in memory is expressed as a V4L2 @pixelformat value. + * As a special case, setting the pixel format to 0 will disable the RPF. The + * @pitch, @mem, @src and @dst parameters are ignored in that case. Calling the + * function on a disabled RPF is allowed. + * + * The memory pitch is configurable to allow for padding at end of lines, or + * simple for images that extend beyond the crop rectangle boundaries. The + * @pitch value is expressed in bytes and applies to all planes for multiplanar + * formats. + * + * The source memory buffer is referenced by the DMA address of its planes in + * the @mem array. Up to two planes are supported. The second plane DMA address + * is ignored for formats using a single plane. + * + * This function isn't reentrant, the caller needs to serialize calls. + * + * TODO: Implement Z-order control by decoupling the RPF index from the BRU + * input index. + * + * Return 0 on success or a negative error code on failure. + */ +int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + const struct vsp1_format_info *fmtinfo; + struct v4l2_subdev_selection sel; + struct v4l2_subdev_format format; + struct vsp1_rwpf_memory memory; + struct vsp1_rwpf *rpf; + unsigned long flags; + bool start_stop = false; + int ret; + + if (rpf_index >= vsp1->pdata.rpf_count) + return -EINVAL; + + rpf = vsp1->rpf[rpf_index]; + + if (pixelformat == 0) { + dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__, + rpf_index); + + spin_lock_irqsave(&pipe->irqlock, flags); + + if (pipe->inputs[rpf_index]) { + /* Remove the RPF from the pipeline if it was previously + * enabled. + */ + vsp1->bru->inputs[rpf_index].rpf = NULL; + pipe->inputs[rpf_index] = NULL; + + vsp1->drm->update = true; + start_stop = --pipe->num_inputs == 0; + } + + spin_unlock_irqrestore(&pipe->irqlock, flags); + + /* Stop the pipeline if we're the last user. */ + if (start_stop) + vsp1_pipeline_stop(pipe); + + return 0; + } + + dev_dbg(vsp1->dev, + "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad }\n", + __func__, rpf_index, + src->left, src->top, src->width, src->height, + dst->left, dst->top, dst->width, dst->height, + pixelformat, pitch, &mem[0], &mem[1]); + + /* Set the stride at the RPF input. */ + fmtinfo = vsp1_get_format_info(pixelformat); + if (!fmtinfo) { + dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n", + pixelformat); + return -EINVAL; + } + + rpf->fmtinfo = fmtinfo; + rpf->format.num_planes = fmtinfo->planes; + rpf->format.plane_fmt[0].bytesperline = pitch; + rpf->format.plane_fmt[1].bytesperline = pitch; + + /* Configure the format on the RPF sink pad and propagate it up to the + * BRU sink pad. + */ + memset(&format, 0, sizeof(format)); + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + format.pad = RWPF_PAD_SINK; + format.format.width = src->width + src->left; + format.format.height = src->height + src->top; + format.format.code = fmtinfo->mbus; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set format %ux%u (%x) on RPF%u sink\n", + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + + memset(&sel, 0, sizeof(sel)); + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.pad = RWPF_PAD_SINK; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = *src; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, + &sel); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n", + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, + rpf->entity.index); + + /* RPF source, hardcode the format to ARGB8888 to turn on format + * conversion if needed. + */ + format.pad = RWPF_PAD_SOURCE; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: got format %ux%u (%x) on RPF%u source\n", + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + /* BRU sink, propagate the format from the RPF source. */ + format.pad = rpf->entity.index; + + ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n", + __func__, format.format.width, format.format.height, + format.format.code, format.pad); + + sel.pad = rpf->entity.index; + sel.target = V4L2_SEL_TGT_COMPOSE; + sel.r = *dst; + + ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection, + NULL, &sel); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, + "%s: set selection (%u,%u)/%ux%u on BRU pad %u\n", + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, + sel.pad); + + /* Store the compose rectangle coordinates in the RPF. */ + rpf->location.left = dst->left; + rpf->location.top = dst->top; + + /* Set the memory buffer address. */ + memory.num_planes = fmtinfo->planes; + memory.addr[0] = mem[0]; + memory.addr[1] = mem[1]; + + rpf->ops->set_memory(rpf, &memory); + + spin_lock_irqsave(&pipe->irqlock, flags); + + /* If the RPF was previously stopped set the BRU input to the RPF and + * store the RPF in the pipeline inputs array. + */ + if (!pipe->inputs[rpf->entity.index]) { + vsp1->bru->inputs[rpf_index].rpf = rpf; + pipe->inputs[rpf->entity.index] = rpf; + start_stop = pipe->num_inputs++ == 0; + } + + /* Start the pipeline if it's currently stopped. */ + vsp1->drm->update = true; + if (start_stop) + vsp1_drm_pipeline_run(pipe); + + spin_unlock_irqrestore(&pipe->irqlock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf); + +/* ----------------------------------------------------------------------------- + * Initialization + */ + +int vsp1_drm_create_links(struct vsp1_device *vsp1) +{ + const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; + unsigned int i; + int ret; + + /* VSPD instances require a BRU to perform composition and a LIF to + * output to the DU. + */ + if (!vsp1->bru || !vsp1->lif) + return -ENXIO; + + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_rwpf *rpf = vsp1->rpf[i]; + + ret = media_create_pad_link(&rpf->entity.subdev.entity, + RWPF_PAD_SOURCE, + &vsp1->bru->entity.subdev.entity, + i, flags); + if (ret < 0) + return ret; + + rpf->entity.sink = &vsp1->bru->entity.subdev.entity; + rpf->entity.sink_pad = i; + } + + ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity, + vsp1->bru->entity.source_pad, + &vsp1->wpf[0]->entity.subdev.entity, + RWPF_PAD_SINK, flags); + if (ret < 0) + return ret; + + vsp1->bru->entity.sink = &vsp1->wpf[0]->entity.subdev.entity; + vsp1->bru->entity.sink_pad = RWPF_PAD_SINK; + + ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity, + RWPF_PAD_SOURCE, + &vsp1->lif->entity.subdev.entity, + LIF_PAD_SINK, flags); + if (ret < 0) + return ret; + + return 0; +} + +int vsp1_drm_init(struct vsp1_device *vsp1) +{ + struct vsp1_pipeline *pipe; + unsigned int i; + + vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL); + if (!vsp1->drm) + return -ENOMEM; + + pipe = &vsp1->drm->pipe; + + vsp1_pipeline_init(pipe); + pipe->frame_end = vsp1_drm_pipeline_frame_end; + + /* The DRM pipeline is static, add entities manually. */ + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + struct vsp1_rwpf *input = vsp1->rpf[i]; + + list_add_tail(&input->entity.list_pipe, &pipe->entities); + } + + list_add_tail(&vsp1->bru->entity.list_pipe, &pipe->entities); + list_add_tail(&vsp1->wpf[0]->entity.list_pipe, &pipe->entities); + list_add_tail(&vsp1->lif->entity.list_pipe, &pipe->entities); + + pipe->bru = &vsp1->bru->entity; + pipe->lif = &vsp1->lif->entity; + pipe->output = vsp1->wpf[0]; + + return 0; +} diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h new file mode 100644 index 000000000000..2ad320ab1e45 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -0,0 +1,26 @@ +/* + * vsp1_drm.h -- R-Car VSP1 DRM/KMS Interface + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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. + */ +#ifndef __VSP1_DRM_H__ +#define __VSP1_DRM_H__ + +#include "vsp1_pipe.h" + +struct vsp1_drm { + struct vsp1_pipeline pipe; + bool update; +}; + +int vsp1_drm_init(struct vsp1_device *vsp1); +int vsp1_drm_create_links(struct vsp1_device *vsp1); + +#endif /* __VSP1_DRM_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 1e10fc4723c5..74b5920e516b 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -25,6 +25,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_drm.h" #include "vsp1_hsit.h" #include "vsp1_lif.h" #include "vsp1_lut.h" @@ -120,7 +121,7 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1, return 0; } -static int vsp1_create_links(struct vsp1_device *vsp1) +static int vsp1_uapi_create_links(struct vsp1_device *vsp1) { struct vsp1_entity *entity; unsigned int i; @@ -145,9 +146,6 @@ static int vsp1_create_links(struct vsp1_device *vsp1) return ret; } - if (!vsp1->pdata.uapi) - return 0; - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i]; @@ -360,15 +358,22 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Create links. */ - ret = vsp1_create_links(vsp1); + if (vsp1->pdata.uapi) + ret = vsp1_uapi_create_links(vsp1); + else + ret = vsp1_drm_create_links(vsp1); if (ret < 0) goto done; - if (vsp1->pdata.uapi) { + /* Register subdev nodes if the userspace API is enabled or initialize + * the DRM pipeline otherwise. + */ + if (vsp1->pdata.uapi) ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); - if (ret < 0) - goto done; - } + else + ret = vsp1_drm_init(vsp1); + if (ret < 0) + goto done; ret = media_device_register(mdev); diff --git a/include/media/vsp1.h b/include/media/vsp1.h new file mode 100644 index 000000000000..2c1aea7066be --- /dev/null +++ b/include/media/vsp1.h @@ -0,0 +1,30 @@ +/* + * vsp1.h -- R-Car VSP1 API + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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. + */ +#ifndef __MEDIA_VSP1_H__ +#define __MEDIA_VSP1_H__ + +#include + +struct device; +struct v4l2_rect; + +int vsp1_du_init(struct device *dev); + +int vsp1_du_setup_lif(struct device *dev, unsigned int width, + unsigned int height); + +int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat, + unsigned int pitch, dma_addr_t mem[2], + const struct v4l2_rect *src, const struct v4l2_rect *dst); + +#endif /* __MEDIA_VSP1_H__ */ -- cgit v1.2.3 From 3afb193991ccf80edad9b797ec67a35886a2825a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Sep 2015 15:56:29 -0300 Subject: [media] v4l: vsp1: Disconnect unused RPFs from the DRM pipeline Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index ac81ff10c339..a918bb4ab46c 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -38,13 +38,17 @@ static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe) struct vsp1_entity *entity; list_for_each_entry(entity, &pipe->entities, list_pipe) { - /* Skip unused RPFs. */ + /* Disconnect unused RPFs from the pipeline. */ if (entity->type == VSP1_ENTITY_RPF) { struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); - if (!pipe->inputs[rpf->entity.index]) + if (!pipe->inputs[rpf->entity.index]) { + vsp1_write(entity->vsp1, + entity->route->reg, + VI6_DPR_NODE_UNUSED); continue; + } } vsp1_entity_route_setup(entity); -- cgit v1.2.3 From 7b4baddca69e61cdbabe8caff614778d188d89d8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Sep 2015 09:28:39 -0300 Subject: [media] v4l: vsp1: Implement atomic update for the DRM driver Add two API functions named vsp1_du_atomic_begin() and vsp1_du_atomic_flush() to signal the start and end of an atomic update. The vsp1_du_setup_rpf() function is renamed to vsp1_du_atomic_update() for consistency. With this new API, the driver will reprogram all modified inputs atomically before restarting the video stream. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.c | 70 +++++++++++++++++++++++++--------- drivers/media/platform/vsp1/vsp1_drm.h | 7 ++++ include/media/vsp1.h | 9 +++-- 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a918bb4ab46c..8c76086caa67 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); /** - * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline + * vsp1_du_atomic_begin - Prepare for an atomic update + * @dev: the VSP device + */ +void vsp1_du_atomic_begin(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + unsigned long flags; + + spin_lock_irqsave(&pipe->irqlock, flags); + + vsp1->drm->num_inputs = pipe->num_inputs; + vsp1->drm->update = false; + + spin_unlock_irqrestore(&pipe->irqlock, flags); +} +EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); + +/** + * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline * @dev: the VSP device * @rpf_index: index of the RPF to setup (0-based) * @pixelformat: V4L2 pixel format for the RPF memory input @@ -288,10 +307,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); * * Return 0 on success or a negative error code on failure. */ -int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, - u32 pixelformat, unsigned int pitch, - dma_addr_t mem[2], const struct v4l2_rect *src, - const struct v4l2_rect *dst) +int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_pipeline *pipe = &vsp1->drm->pipe; @@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, struct vsp1_rwpf_memory memory; struct vsp1_rwpf *rpf; unsigned long flags; - bool start_stop = false; int ret; if (rpf_index >= vsp1->pdata.rpf_count) @@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, vsp1->bru->inputs[rpf_index].rpf = NULL; pipe->inputs[rpf_index] = NULL; - vsp1->drm->update = true; - start_stop = --pipe->num_inputs == 0; + pipe->num_inputs--; } spin_unlock_irqrestore(&pipe->irqlock, flags); - /* Stop the pipeline if we're the last user. */ - if (start_stop) - vsp1_pipeline_stop(pipe); - return 0; } @@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, if (!pipe->inputs[rpf->entity.index]) { vsp1->bru->inputs[rpf_index].rpf = rpf; pipe->inputs[rpf->entity.index] = rpf; - start_stop = pipe->num_inputs++ == 0; + pipe->num_inputs++; } - /* Start the pipeline if it's currently stopped. */ + spin_unlock_irqrestore(&pipe->irqlock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); + +/** + * vsp1_du_atomic_flush - Commit an atomic update + * @dev: the VSP device + */ +void vsp1_du_atomic_flush(struct device *dev) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + unsigned long flags; + bool stop = false; + + spin_lock_irqsave(&pipe->irqlock, flags); + vsp1->drm->update = true; - if (start_stop) + + /* Start or stop the pipeline if needed. */ + if (!vsp1->drm->num_inputs && pipe->num_inputs) vsp1_drm_pipeline_run(pipe); + else if (vsp1->drm->num_inputs && !pipe->num_inputs) + stop = true; spin_unlock_irqrestore(&pipe->irqlock, flags); - return 0; + if (stop) + vsp1_pipeline_stop(pipe); } -EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf); +EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); /* ----------------------------------------------------------------------------- * Initialization diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 2ad320ab1e45..25d7f017feb4 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -15,8 +15,15 @@ #include "vsp1_pipe.h" +/** + * vsp1_drm - State for the API exposed to the DRM driver + * @pipe: the VSP1 pipeline used for display + * @num_inputs: number of active pipeline inputs at the beginning of an update + * @update: the pipeline configuration has been updated + */ struct vsp1_drm { struct vsp1_pipeline pipe; + unsigned int num_inputs; bool update; }; diff --git a/include/media/vsp1.h b/include/media/vsp1.h index 2c1aea7066be..cc541753896f 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev); int vsp1_du_setup_lif(struct device *dev, unsigned int width, unsigned int height); -int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat, - unsigned int pitch, dma_addr_t mem[2], - const struct v4l2_rect *src, const struct v4l2_rect *dst); +int vsp1_du_atomic_begin(struct device *dev); +int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat, + unsigned int pitch, dma_addr_t mem[2], + const struct v4l2_rect *src, + const struct v4l2_rect *dst); +int vsp1_du_atomic_flush(struct device *dev); #endif /* __MEDIA_VSP1_H__ */ -- cgit v1.2.3 From 7f2d50f8da43fde0c883c378fd81f64c8bca74eb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 7 Sep 2015 08:05:39 -0300 Subject: [media] v4l: vsp1: Add support for the R-Car Gen3 VSP2 Add DT compatible strings for the VSP2 instances found in the R-Car Gen3 SoCs and support them in the vsp1 driver. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/renesas,vsp1.txt | 20 ++++++++------- drivers/media/platform/vsp1/vsp1_drv.c | 25 ++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.c | 3 ++- drivers/media/platform/vsp1/vsp1_regs.h | 30 +++++++++++++++++----- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt index 674c8c30d046..fe74fb38e4d5 100644 --- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt +++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt @@ -1,24 +1,26 @@ -* Renesas VSP1 Video Processing Engine +* Renesas VSP Video Processing Engine -The VSP1 is a video processing engine that supports up-/down-scaling, alpha +The VSP is a video processing engine that supports up-/down-scaling, alpha blending, color space conversion and various other image processing features. It can be found in the Renesas R-Car second generation SoCs. Required properties: - - compatible: Must contain "renesas,vsp1" + - compatible: Must contain one of the following values + - "renesas,vsp1" for the R-Car Gen2 VSP1 + - "renesas,vsp2" for the R-Car Gen3 VSP2 - - reg: Base address and length of the registers block for the VSP1. - - interrupts: VSP1 interrupt specifier. - - clocks: A phandle + clock-specifier pair for the VSP1 functional clock. + - reg: Base address and length of the registers block for the VSP. + - interrupts: VSP interrupt specifier. + - clocks: A phandle + clock-specifier pair for the VSP functional clock. - - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP1. - - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP1. + - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP. + - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP. Optional properties: - - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1. Defaults + - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP. Defaults to 0 if not present. - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is available. diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 74b5920e516b..7530dbc978cd 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -579,6 +579,7 @@ static int vsp1_probe(struct platform_device *pdev) struct vsp1_device *vsp1; struct resource *irq; struct resource *io; + u32 version; int ret; vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL); @@ -619,6 +620,29 @@ static int vsp1_probe(struct platform_device *pdev) return ret; } + /* Configure device parameters based on the version register. */ + ret = clk_prepare_enable(vsp1->clock); + if (ret < 0) + return ret; + + version = vsp1_read(vsp1, VI6_IP_VERSION); + clk_disable_unprepare(vsp1->clock); + + dev_dbg(&pdev->dev, "IP version 0x%08x\n", version); + + switch (version & VI6_IP_VERSION_MODEL_MASK) { + case VI6_IP_VERSION_MODEL_VSPD_GEN3: + vsp1->pdata.num_bru_inputs = 5; + vsp1->pdata.uapi = false; + break; + + case VI6_IP_VERSION_MODEL_VSPI_GEN3: + case VI6_IP_VERSION_MODEL_VSPBD_GEN3: + case VI6_IP_VERSION_MODEL_VSPBC_GEN3: + vsp1->pdata.features &= ~VSP1_HAS_BRU; + break; + } + /* Instanciate entities */ ret = vsp1_create_entities(vsp1); if (ret < 0) { @@ -642,6 +666,7 @@ static int vsp1_remove(struct platform_device *pdev) static const struct of_device_id vsp1_of_match[] = { { .compatible = "renesas,vsp1" }, + { .compatible = "renesas,vsp2" }, { }, }; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 03523899d7d0..1fcee58fae62 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -165,7 +165,8 @@ int vsp1_entity_link_setup(struct media_entity *entity, static const struct vsp1_route vsp1_routes[] = { { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE, { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1), - VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), } }, + VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), + VI6_DPR_NODE_BRU_IN(4) } }, { VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } }, { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } }, { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } }, diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 8173ceaab9f9..069216f0eb44 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -322,7 +322,7 @@ #define VI6_DPR_NODE_SRU 16 #define VI6_DPR_NODE_UDS(n) (17 + (n)) #define VI6_DPR_NODE_LUT 22 -#define VI6_DPR_NODE_BRU_IN(n) (23 + (n)) +#define VI6_DPR_NODE_BRU_IN(n) (((n) <= 3) ? 23 + (n) : 49) #define VI6_DPR_NODE_BRU_OUT 27 #define VI6_DPR_NODE_CLU 29 #define VI6_DPR_NODE_HST 30 @@ -504,12 +504,12 @@ #define VI6_BRU_VIRRPF_COL_BCB_MASK (0xff << 0) #define VI6_BRU_VIRRPF_COL_BCB_SHIFT 0 -#define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8) +#define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8 + ((n) <= 3 ? 0 : 4)) #define VI6_BRU_CTRL_RBC (1 << 31) -#define VI6_BRU_CTRL_DSTSEL_BRUIN(n) ((n) << 20) +#define VI6_BRU_CTRL_DSTSEL_BRUIN(n) (((n) <= 3 ? (n) : (n)+1) << 20) #define VI6_BRU_CTRL_DSTSEL_VRPF (4 << 20) #define VI6_BRU_CTRL_DSTSEL_MASK (7 << 20) -#define VI6_BRU_CTRL_SRCSEL_BRUIN(n) ((n) << 16) +#define VI6_BRU_CTRL_SRCSEL_BRUIN(n) (((n) <= 3 ? (n) : (n)+1) << 16) #define VI6_BRU_CTRL_SRCSEL_VRPF (4 << 16) #define VI6_BRU_CTRL_SRCSEL_MASK (7 << 16) #define VI6_BRU_CTRL_CROP(rop) ((rop) << 4) @@ -517,7 +517,7 @@ #define VI6_BRU_CTRL_AROP(rop) ((rop) << 0) #define VI6_BRU_CTRL_AROP_MASK (0xf << 0) -#define VI6_BRU_BLD(n) (0x2c14 + (n) * 8) +#define VI6_BRU_BLD(n) (0x2c14 + (n) * 8 + ((n) <= 3 ? 0 : 4)) #define VI6_BRU_BLD_CBES (1 << 31) #define VI6_BRU_BLD_CCMDX_DST_A (0 << 28) #define VI6_BRU_BLD_CCMDX_255_DST_A (1 << 28) @@ -551,7 +551,7 @@ #define VI6_BRU_BLD_COEFY_SHIFT 0 #define VI6_BRU_ROP 0x2c30 -#define VI6_BRU_ROP_DSTSEL_BRUIN(n) ((n) << 20) +#define VI6_BRU_ROP_DSTSEL_BRUIN(n) (((n) <= 3 ? (n) : (n)+1) << 20) #define VI6_BRU_ROP_DSTSEL_VRPF (4 << 20) #define VI6_BRU_ROP_DSTSEL_MASK (7 << 20) #define VI6_BRU_ROP_CROP(rop) ((rop) << 4) @@ -624,6 +624,24 @@ #define VI6_SECURITY_CTRL0 0x3d00 #define VI6_SECURITY_CTRL1 0x3d04 +/* ----------------------------------------------------------------------------- + * IP Version Registers + */ + +#define VI6_IP_VERSION 0x3f00 +#define VI6_IP_VERSION_MODEL_MASK (0xff << 8) +#define VI6_IP_VERSION_MODEL_VSPS_H2 (0x09 << 8) +#define VI6_IP_VERSION_MODEL_VSPR_H2 (0x0a << 8) +#define VI6_IP_VERSION_MODEL_VSPD_GEN2 (0x0b << 8) +#define VI6_IP_VERSION_MODEL_VSPS_M2 (0x0c << 8) +#define VI6_IP_VERSION_MODEL_VSPI_GEN3 (0x14 << 8) +#define VI6_IP_VERSION_MODEL_VSPBD_GEN3 (0x15 << 8) +#define VI6_IP_VERSION_MODEL_VSPBC_GEN3 (0x16 << 8) +#define VI6_IP_VERSION_MODEL_VSPD_GEN3 (0x17 << 8) +#define VI6_IP_VERSION_SOC_MASK (0xff << 0) +#define VI6_IP_VERSION_SOC_H (0x01 << 0) +#define VI6_IP_VERSION_SOC_M (0x02 << 0) + /* ----------------------------------------------------------------------------- * RPF CLUT Registers */ -- cgit v1.2.3 From 1517b0392369d67250e6b275671be5bdbf64b81e Mon Sep 17 00:00:00 2001 From: Takashi Saito Date: Mon, 7 Sep 2015 01:40:25 -0300 Subject: [media] v4l: vsp1: Add display list support Display lists contain lists of registers and associated values to be applied atomically by the hardware. They lower the pressure on interrupt processing delays when reprogramming the device as settings can be prepared well in advance and queued to the hardware without waiting for the end of the current frame. Display list support is currently limited to the DRM pipeline. Signed-off-by: Koji Matsuoka Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 17 ++ drivers/media/platform/vsp1/vsp1_bru.c | 2 +- drivers/media/platform/vsp1/vsp1_dl.c | 305 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_dl.h | 42 ++++ drivers/media/platform/vsp1/vsp1_drm.c | 105 +++++----- drivers/media/platform/vsp1/vsp1_drm.h | 5 + drivers/media/platform/vsp1/vsp1_drv.c | 76 ++++++-- drivers/media/platform/vsp1/vsp1_entity.c | 4 +- drivers/media/platform/vsp1/vsp1_lif.c | 4 +- drivers/media/platform/vsp1/vsp1_pipe.c | 54 +++++- drivers/media/platform/vsp1/vsp1_pipe.h | 5 + drivers/media/platform/vsp1/vsp1_rpf.c | 4 +- drivers/media/platform/vsp1/vsp1_wpf.c | 13 +- 14 files changed, 543 insertions(+), 95 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_dl.c create mode 100644 drivers/media/platform/vsp1/vsp1_dl.h diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 447e72a2ef43..95b3ac2ea7ef 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,5 +1,5 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_pipe.o -vsp1-y += vsp1_drm.o vsp1_video.o +vsp1-y += vsp1_dl.o vsp1_drm.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 67a026ae88cb..5b210b69f09c 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -26,7 +26,9 @@ struct clk; struct device; +struct vsp1_dl; struct vsp1_drm; +struct vsp1_entity; struct vsp1_platform_data; struct vsp1_bru; struct vsp1_hsit; @@ -80,12 +82,17 @@ struct vsp1_device { struct v4l2_device v4l2_dev; struct media_device media_dev; struct media_entity_operations media_ops; + struct vsp1_drm *drm; + + bool use_dl; }; int vsp1_device_get(struct vsp1_device *vsp1); void vsp1_device_put(struct vsp1_device *vsp1); +int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index); + static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg) { return ioread32(vsp1->mmio + reg); @@ -96,4 +103,14 @@ static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data) iowrite32(data, vsp1->mmio + reg); } +#include "vsp1_dl.h" + +static inline void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data) +{ + if (e->vsp1->use_dl) + vsp1_dl_add(e, reg, data); + else + vsp1_write(e->vsp1, reg, data); +} + #endif /* __VSP1_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 848bfb5a42ff..32e2009c215a 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -30,7 +30,7 @@ static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) { - vsp1_write(bru->entity.vsp1, reg, data); + vsp1_mod_write(&bru->entity, reg, data); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c new file mode 100644 index 000000000000..7dc27ac6bd02 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -0,0 +1,305 @@ +/* + * vsp1_dl.h -- R-Car VSP1 Display List + * + * Copyright (C) 2015 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 +#include +#include +#include + +#include "vsp1.h" +#include "vsp1_dl.h" +#include "vsp1_pipe.h" + +/* + * Global resources + * + * - Display-related interrupts (can be used for vblank evasion ?) + * - Display-list enable + * - Header-less for WPF0 + * - DL swap + */ + +#define VSP1_DL_BODY_SIZE (2 * 4 * 256) +#define VSP1_DL_NUM_LISTS 3 + +struct vsp1_dl_entry { + u32 addr; + u32 data; +} __attribute__((__packed__)); + +struct vsp1_dl_list { + size_t size; + int reg_count; + + bool in_use; + + struct vsp1_dl_entry *body; + dma_addr_t dma; +}; + +/** + * struct vsp1_dl - Display List manager + * @vsp1: the VSP1 device + * @lock: protects the active, queued and pending lists + * @lists.all: array of all allocate display lists + * @lists.active: list currently being processed (loaded) by hardware + * @lists.queued: list queued to the hardware (written to the DL registers) + * @lists.pending: list waiting to be queued to the hardware + * @lists.write: list being written to by software + */ +struct vsp1_dl { + struct vsp1_device *vsp1; + + spinlock_t lock; + + size_t size; + dma_addr_t dma; + void *mem; + + struct { + struct vsp1_dl_list all[VSP1_DL_NUM_LISTS]; + + struct vsp1_dl_list *active; + struct vsp1_dl_list *queued; + struct vsp1_dl_list *pending; + struct vsp1_dl_list *write; + } lists; +}; + +/* ----------------------------------------------------------------------------- + * Display List Transaction Management + */ + +static void vsp1_dl_free_list(struct vsp1_dl_list *list) +{ + if (!list) + return; + + list->in_use = false; +} + +void vsp1_dl_reset(struct vsp1_dl *dl) +{ + unsigned int i; + + dl->lists.active = NULL; + dl->lists.queued = NULL; + dl->lists.pending = NULL; + dl->lists.write = NULL; + + for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) + dl->lists.all[i].in_use = false; +} + +void vsp1_dl_begin(struct vsp1_dl *dl) +{ + struct vsp1_dl_list *list = NULL; + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&dl->lock, flags); + + for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { + if (!dl->lists.all[i].in_use) { + list = &dl->lists.all[i]; + break; + } + } + + if (!list) { + list = dl->lists.pending; + dl->lists.pending = NULL; + } + + spin_unlock_irqrestore(&dl->lock, flags); + + dl->lists.write = list; + + list->in_use = true; + list->reg_count = 0; +} + +void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data) +{ + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); + struct vsp1_dl *dl = pipe->dl; + struct vsp1_dl_list *list = dl->lists.write; + + list->body[list->reg_count].addr = reg; + list->body[list->reg_count].data = data; + list->reg_count++; +} + +void vsp1_dl_commit(struct vsp1_dl *dl) +{ + struct vsp1_device *vsp1 = dl->vsp1; + struct vsp1_dl_list *list; + unsigned long flags; + bool update; + + list = dl->lists.write; + dl->lists.write = NULL; + + spin_lock_irqsave(&dl->lock, flags); + + /* Once the UPD bit has been set the hardware can start processing the + * display list at any time and we can't touch the address and size + * registers. In that case mark the update as pending, it will be + * queued up to the hardware by the frame end interrupt handler. + */ + update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD); + if (update) { + vsp1_dl_free_list(dl->lists.pending); + dl->lists.pending = list; + goto done; + } + + /* Program the hardware with the display list body address and size. + * The UPD bit will be cleared by the device when the display list is + * processed. + */ + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); + vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | + (list->reg_count * 8)); + + vsp1_dl_free_list(dl->lists.queued); + dl->lists.queued = list; + +done: + spin_unlock_irqrestore(&dl->lock, flags); +} + +/* ----------------------------------------------------------------------------- + * Interrupt Handling + */ + +void vsp1_dl_irq_display_start(struct vsp1_dl *dl) +{ + spin_lock(&dl->lock); + + /* The display start interrupt signals the end of the display list + * processing by the device. The active display list, if any, won't be + * accessed anymore and can be reused. + */ + if (dl->lists.active) { + vsp1_dl_free_list(dl->lists.active); + dl->lists.active = NULL; + } + + spin_unlock(&dl->lock); +} + +void vsp1_dl_irq_frame_end(struct vsp1_dl *dl) +{ + struct vsp1_device *vsp1 = dl->vsp1; + + spin_lock(&dl->lock); + + /* The UPD bit set indicates that the commit operation raced with the + * interrupt and occurred after the frame end event and UPD clear but + * before interrupt processing. The hardware hasn't taken the update + * into account yet, we'll thus skip one frame and retry. + */ + if (vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD) + goto done; + + /* The device starts processing the queued display list right after the + * frame end interrupt. The display list thus becomes active. + */ + if (dl->lists.queued) { + WARN_ON(dl->lists.active); + dl->lists.active = dl->lists.queued; + dl->lists.queued = NULL; + } + + /* Now that the UPD bit has been cleared we can queue the next display + * list to the hardware if one has been prepared. + */ + if (dl->lists.pending) { + struct vsp1_dl_list *list = dl->lists.pending; + + vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); + vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | + (list->reg_count * 8)); + + dl->lists.queued = list; + dl->lists.pending = NULL; + } + +done: + spin_unlock(&dl->lock); +} + +/* ----------------------------------------------------------------------------- + * Hardware Setup + */ + +void vsp1_dl_setup(struct vsp1_device *vsp1) +{ + u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT) + | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 + | VI6_DL_CTRL_DLE; + + /* The DRM pipeline operates with header-less display lists in + * Continuous Frame Mode. + */ + if (vsp1->drm) + ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; + + vsp1_write(vsp1, VI6_DL_CTRL, ctrl); + vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); +} + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1) +{ + struct vsp1_dl *dl; + unsigned int i; + + dl = kzalloc(sizeof(*dl), GFP_KERNEL); + if (!dl) + return NULL; + + spin_lock_init(&dl->lock); + + dl->vsp1 = vsp1; + dl->size = VSP1_DL_BODY_SIZE * ARRAY_SIZE(dl->lists.all); + + dl->mem = dma_alloc_writecombine(vsp1->dev, dl->size, &dl->dma, + GFP_KERNEL); + if (!dl->mem) { + kfree(dl); + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { + struct vsp1_dl_list *list = &dl->lists.all[i]; + + list->size = VSP1_DL_BODY_SIZE; + list->reg_count = 0; + list->in_use = false; + list->dma = dl->dma + VSP1_DL_BODY_SIZE * i; + list->body = dl->mem + VSP1_DL_BODY_SIZE * i; + } + + return dl; +} + +void vsp1_dl_destroy(struct vsp1_dl *dl) +{ + dma_free_writecombine(dl->vsp1->dev, dl->size, dl->mem, dl->dma); + kfree(dl); +} diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h new file mode 100644 index 000000000000..448c4250e54c --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -0,0 +1,42 @@ +/* + * vsp1_dl.h -- R-Car VSP1 Display List + * + * Copyright (C) 2015 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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. + */ +#ifndef __VSP1_DL_H__ +#define __VSP1_DL_H__ + +#include "vsp1_entity.h" + +struct vsp1_device; +struct vsp1_dl; + +struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1); +void vsp1_dl_destroy(struct vsp1_dl *dl); + +void vsp1_dl_setup(struct vsp1_device *vsp1); + +void vsp1_dl_reset(struct vsp1_dl *dl); +void vsp1_dl_begin(struct vsp1_dl *dl); +void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data); +void vsp1_dl_commit(struct vsp1_dl *dl); + +void vsp1_dl_irq_display_start(struct vsp1_dl *dl); +void vsp1_dl_irq_frame_end(struct vsp1_dl *dl); + +static inline void vsp1_dl_mod_write(struct vsp1_entity *e, u32 reg, u32 data) +{ + if (e->vsp1->use_dl) + vsp1_dl_add(e, reg, data); + else + vsp1_write(e->vsp1, reg, data); +} + +#endif /* __VSP1_DL_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 8c76086caa67..ddd98212bf39 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -20,6 +20,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_dl.h" #include "vsp1_drm.h" #include "vsp1_lif.h" #include "vsp1_pipe.h" @@ -29,55 +30,13 @@ * Runtime Handling */ -static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe) -{ - struct vsp1_device *vsp1 = pipe->output->entity.vsp1; - int ret; - - if (vsp1->drm->update) { - struct vsp1_entity *entity; - - list_for_each_entry(entity, &pipe->entities, list_pipe) { - /* Disconnect unused RPFs from the pipeline. */ - if (entity->type == VSP1_ENTITY_RPF) { - struct vsp1_rwpf *rpf = - to_rwpf(&entity->subdev); - - if (!pipe->inputs[rpf->entity.index]) { - vsp1_write(entity->vsp1, - entity->route->reg, - VI6_DPR_NODE_UNUSED); - continue; - } - } - - vsp1_entity_route_setup(entity); - - ret = v4l2_subdev_call(&entity->subdev, video, - s_stream, 1); - if (ret < 0) { - dev_err(vsp1->dev, - "DRM pipeline start failure on entity %s\n", - entity->subdev.name); - return ret; - } - } - - vsp1->drm->update = false; - } - - vsp1_pipeline_run(pipe); - - return 0; -} - static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe) { unsigned long flags; spin_lock_irqsave(&pipe->irqlock, flags); if (pipe->num_inputs) - vsp1_drm_pipeline_run(pipe); + vsp1_pipeline_run(pipe); spin_unlock_irqrestore(&pipe->irqlock, flags); } @@ -151,6 +110,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, return 0; } + vsp1_dl_reset(vsp1->drm->dl); + /* Configure the format at the BRU sinks and propagate it through the * pipeline. */ @@ -266,9 +227,11 @@ void vsp1_du_atomic_begin(struct device *dev) spin_lock_irqsave(&pipe->irqlock, flags); vsp1->drm->num_inputs = pipe->num_inputs; - vsp1->drm->update = false; spin_unlock_irqrestore(&pipe->irqlock, flags); + + /* Prepare the display list. */ + vsp1_dl_begin(vsp1->drm->dl); } EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); @@ -489,23 +452,54 @@ void vsp1_du_atomic_flush(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_pipeline *pipe = &vsp1->drm->pipe; + struct vsp1_entity *entity; unsigned long flags; bool stop = false; + int ret; - spin_lock_irqsave(&pipe->irqlock, flags); + list_for_each_entry(entity, &pipe->entities, list_pipe) { + /* Disconnect unused RPFs from the pipeline. */ + if (entity->type == VSP1_ENTITY_RPF) { + struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); + + if (!pipe->inputs[rpf->entity.index]) { + vsp1_mod_write(entity, entity->route->reg, + VI6_DPR_NODE_UNUSED); + continue; + } + } + + vsp1_entity_route_setup(entity); + + ret = v4l2_subdev_call(&entity->subdev, video, + s_stream, 1); + if (ret < 0) { + dev_err(vsp1->dev, + "DRM pipeline start failure on entity %s\n", + entity->subdev.name); + return; + } + } + + vsp1_dl_commit(vsp1->drm->dl); - vsp1->drm->update = true; + spin_lock_irqsave(&pipe->irqlock, flags); /* Start or stop the pipeline if needed. */ - if (!vsp1->drm->num_inputs && pipe->num_inputs) - vsp1_drm_pipeline_run(pipe); - else if (vsp1->drm->num_inputs && !pipe->num_inputs) + if (!vsp1->drm->num_inputs && pipe->num_inputs) { + vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); + vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE); + vsp1_pipeline_run(pipe); + } else if (vsp1->drm->num_inputs && !pipe->num_inputs) { stop = true; + } spin_unlock_irqrestore(&pipe->irqlock, flags); - if (stop) + if (stop) { + vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); vsp1_pipeline_stop(pipe); + } } EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); @@ -568,6 +562,10 @@ int vsp1_drm_init(struct vsp1_device *vsp1) if (!vsp1->drm) return -ENOMEM; + vsp1->drm->dl = vsp1_dl_create(vsp1); + if (!vsp1->drm->dl) + return -ENOMEM; + pipe = &vsp1->drm->pipe; vsp1_pipeline_init(pipe); @@ -588,5 +586,12 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe->lif = &vsp1->lif->entity; pipe->output = vsp1->wpf[0]; + pipe->dl = vsp1->drm->dl; + return 0; } + +void vsp1_drm_cleanup(struct vsp1_device *vsp1) +{ + vsp1_dl_destroy(vsp1->drm->dl); +} diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 25d7f017feb4..7704038c3add 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -15,19 +15,24 @@ #include "vsp1_pipe.h" +struct vsp1_dl; + /** * vsp1_drm - State for the API exposed to the DRM driver + * @dl: display list for DRM pipeline operation * @pipe: the VSP1 pipeline used for display * @num_inputs: number of active pipeline inputs at the beginning of an update * @update: the pipeline configuration has been updated */ struct vsp1_drm { + struct vsp1_dl *dl; struct vsp1_pipeline pipe; unsigned int num_inputs; bool update; }; int vsp1_drm_init(struct vsp1_device *vsp1); +void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); #endif /* __VSP1_DRM_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 7530dbc978cd..b2a7d58e3e13 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -25,6 +25,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_dl.h" #include "vsp1_drm.h" #include "vsp1_hsit.h" #include "vsp1_lif.h" @@ -44,11 +45,11 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) struct vsp1_device *vsp1 = data; irqreturn_t ret = IRQ_NONE; unsigned int i; + u32 status; for (i = 0; i < vsp1->pdata.wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; - u32 status; if (wpf == NULL) continue; @@ -63,6 +64,21 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) } } + status = vsp1_read(vsp1, VI6_DISP_IRQ_STA); + vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST); + + if (status & VI6_DISP_IRQ_STA_DST) { + struct vsp1_rwpf *wpf = vsp1->wpf[0]; + struct vsp1_pipeline *pipe; + + if (wpf) { + pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); + vsp1_pipeline_display_start(pipe); + } + + ret = IRQ_HANDLED; + } + return ret; } @@ -198,6 +214,9 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1) v4l2_device_unregister(&vsp1->v4l2_dev); media_device_unregister(&vsp1->media_dev); media_device_cleanup(&vsp1->media_dev); + + if (!vsp1->pdata.uapi) + vsp1_drm_cleanup(vsp1); } static int vsp1_create_entities(struct vsp1_device *vsp1) @@ -368,10 +387,13 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) /* Register subdev nodes if the userspace API is enabled or initialize * the DRM pipeline otherwise. */ - if (vsp1->pdata.uapi) + if (vsp1->pdata.uapi) { + vsp1->use_dl = false; ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); - else + } else { + vsp1->use_dl = true; ret = vsp1_drm_init(vsp1); + } if (ret < 0) goto done; @@ -384,33 +406,42 @@ done: return ret; } -static int vsp1_device_init(struct vsp1_device *vsp1) +int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index) { - unsigned int i; + unsigned int timeout; u32 status; - /* Reset any channel that might be running. */ status = vsp1_read(vsp1, VI6_STATUS); + if (!(status & VI6_STATUS_SYS_ACT(index))) + return 0; - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { - unsigned int timeout; + vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(index)); + for (timeout = 10; timeout > 0; --timeout) { + status = vsp1_read(vsp1, VI6_STATUS); + if (!(status & VI6_STATUS_SYS_ACT(index))) + break; - if (!(status & VI6_STATUS_SYS_ACT(i))) - continue; + usleep_range(1000, 2000); + } - vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(i)); - for (timeout = 10; timeout > 0; --timeout) { - status = vsp1_read(vsp1, VI6_STATUS); - if (!(status & VI6_STATUS_SYS_ACT(i))) - break; + if (!timeout) { + dev_err(vsp1->dev, "failed to reset wpf.%u\n", index); + return -ETIMEDOUT; + } - usleep_range(1000, 2000); - } + return 0; +} - if (!timeout) { - dev_err(vsp1->dev, "failed to reset wpf.%u\n", i); - return -ETIMEDOUT; - } +static int vsp1_device_init(struct vsp1_device *vsp1) +{ + unsigned int i; + int ret; + + /* Reset any channel that might be running. */ + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + ret = vsp1_reset_wpf(vsp1, i); + if (ret < 0) + return ret; } vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) | @@ -434,6 +465,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); + if (vsp1->use_dl) + vsp1_dl_setup(vsp1); + return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 1fcee58fae62..b9df8349b529 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -66,8 +66,8 @@ void vsp1_entity_route_setup(struct vsp1_entity *source) return; sink = container_of(source->sink, struct vsp1_entity, subdev.entity); - vsp1_write(source->vsp1, source->route->reg, - sink->route->inputs[source->sink_pad]); + vsp1_mod_write(source, source->route->reg, + sink->route->inputs[source->sink_pad]); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b8e73d32d14d..433853ce8dbf 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -28,7 +28,7 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) { - vsp1_write(lif->entity.vsp1, reg, data); + vsp1_mod_write(&lif->entity, reg, data); } /* ----------------------------------------------------------------------------- @@ -44,7 +44,7 @@ static int lif_s_stream(struct v4l2_subdev *subdev, int enable) unsigned int lbth = 200; if (!enable) { - vsp1_lif_write(lif, VI6_LIF_CTRL, 0); + vsp1_write(lif->entity.vsp1, VI6_LIF_CTRL, 0); return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 05d4c3870cff..36aa825b5ce6 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -11,6 +11,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -20,6 +21,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_dl.h" #include "vsp1_entity.h" #include "vsp1_pipe.h" #include "vsp1_rwpf.h" @@ -197,8 +199,12 @@ void vsp1_pipeline_run(struct vsp1_pipeline *pipe) { struct vsp1_device *vsp1 = pipe->output->entity.vsp1; - vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD); - pipe->state = VSP1_PIPELINE_RUNNING; + if (pipe->state == VSP1_PIPELINE_STOPPED) { + vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), + VI6_CMD_STRCMD); + pipe->state = VSP1_PIPELINE_RUNNING; + } + pipe->buffers_ready = 0; } @@ -220,14 +226,28 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) unsigned long flags; int ret; - spin_lock_irqsave(&pipe->irqlock, flags); - if (pipe->state == VSP1_PIPELINE_RUNNING) - pipe->state = VSP1_PIPELINE_STOPPING; - spin_unlock_irqrestore(&pipe->irqlock, flags); + if (pipe->dl) { + /* When using display lists in continuous frame mode the only + * way to stop the pipeline is to reset the hardware. + */ + ret = vsp1_reset_wpf(pipe->output->entity.vsp1, + pipe->output->entity.index); + if (ret == 0) { + spin_lock_irqsave(&pipe->irqlock, flags); + pipe->state = VSP1_PIPELINE_STOPPED; + spin_unlock_irqrestore(&pipe->irqlock, flags); + } + } else { + /* Otherwise just request a stop and wait. */ + spin_lock_irqsave(&pipe->irqlock, flags); + if (pipe->state == VSP1_PIPELINE_RUNNING) + pipe->state = VSP1_PIPELINE_STOPPING; + spin_unlock_irqrestore(&pipe->irqlock, flags); - ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), - msecs_to_jiffies(500)); - ret = ret == 0 ? -ETIMEDOUT : 0; + ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), + msecs_to_jiffies(500)); + ret = ret == 0 ? -ETIMEDOUT : 0; + } list_for_each_entry(entity, &pipe->entities, list_pipe) { if (entity->route && entity->route->reg) @@ -251,6 +271,12 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) return pipe->buffers_ready == mask; } +void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe) +{ + if (pipe->dl) + vsp1_dl_irq_display_start(pipe->dl); +} + void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { enum vsp1_pipeline_state state; @@ -259,13 +285,21 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) if (pipe == NULL) return; + if (pipe->dl) + vsp1_dl_irq_frame_end(pipe->dl); + /* Signal frame end to the pipeline handler. */ pipe->frame_end(pipe); spin_lock_irqsave(&pipe->irqlock, flags); state = pipe->state; - pipe->state = VSP1_PIPELINE_STOPPED; + + /* When using display lists in continuous frame mode the pipeline is + * automatically restarted by the hardware. + */ + if (!pipe->dl) + pipe->state = VSP1_PIPELINE_STOPPED; /* If a stop has been requested, mark the pipeline as stopped and * return. diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index c4c300561c5c..b2f3a8a896c9 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -19,6 +19,7 @@ #include +struct vsp1_dl; struct vsp1_rwpf; /* @@ -73,6 +74,7 @@ enum vsp1_pipeline_state { * @uds: UDS entity, if present * @uds_input: entity at the input of the UDS, if the UDS is present * @entities: list of entities in the pipeline + * @dl: display list associated with the pipeline */ struct vsp1_pipeline { struct media_pipeline pipe; @@ -97,6 +99,8 @@ struct vsp1_pipeline { struct vsp1_entity *uds_input; struct list_head entities; + + struct vsp1_dl *dl; }; static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) @@ -115,6 +119,7 @@ bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe); int vsp1_pipeline_stop(struct vsp1_pipeline *pipe); bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe); +void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe); void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 3992da09e466..1eb9a3ef05c8 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -28,8 +28,8 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) { - vsp1_write(rpf->entity.vsp1, - reg + rpf->entity.index * VI6_RPF_OFFSET, data); + vsp1_mod_write(&rpf->entity, reg + rpf->entity.index * VI6_RPF_OFFSET, + data); } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 849ed81d86a1..4a741a597878 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -34,8 +34,8 @@ static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg) static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) { - vsp1_write(wpf->entity.vsp1, - reg + wpf->entity.index * VI6_WPF_OFFSET, data); + vsp1_mod_write(&wpf->entity, + reg + wpf->entity.index * VI6_WPF_OFFSET, data); } /* ----------------------------------------------------------------------------- @@ -88,7 +88,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) if (!enable) { vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); - vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0); + vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + + VI6_WPF_SRCRPF, 0); return 0; } @@ -161,10 +162,10 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) if (vsp1->pdata.uapi) mutex_unlock(wpf->ctrls.lock); - vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), - VI6_DPR_WPF_FPORCH_FP_WPFN); + vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index), + VI6_DPR_WPF_FPORCH_FP_WPFN); - vsp1_write(vsp1, VI6_WPF_WRBCK_CTRL, 0); + vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0); /* Enable interrupts */ vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0); -- cgit v1.2.3 From 5aa2eb3c86d4fd167b7c4e41eceb99a8598bcc76 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 5 Dec 2015 20:17:10 -0200 Subject: [media] v4l: vsp1: Configure device based on IP version The IP version number carries enough information to identify the exact device instance features. Drop the related DT properties and use the IP version instead. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/renesas,vsp1.txt | 21 --- drivers/media/platform/vsp1/vsp1.h | 5 +- drivers/media/platform/vsp1/vsp1_bru.c | 2 +- drivers/media/platform/vsp1/vsp1_drm.c | 6 +- drivers/media/platform/vsp1/vsp1_drv.c | 173 ++++++++++++--------- drivers/media/platform/vsp1/vsp1_entity.c | 2 +- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +- drivers/media/platform/vsp1/vsp1_rpf.c | 4 +- drivers/media/platform/vsp1/vsp1_sru.c | 4 +- drivers/media/platform/vsp1/vsp1_video.c | 4 +- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +- 11 files changed, 116 insertions(+), 117 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt index fe74fb38e4d5..627405abd144 100644 --- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt +++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt @@ -14,21 +14,6 @@ Required properties: - interrupts: VSP interrupt specifier. - clocks: A phandle + clock-specifier pair for the VSP functional clock. - - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP. - - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP. - - -Optional properties: - - - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP. Defaults - to 0 if not present. - - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is - available. - - renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is - available. - - renesas,has-sru: Boolean, indicates that the Super Resolution Unit (SRU) - module is available. - Example: R8A7790 (R-Car H2) VSP1-S node @@ -37,10 +22,4 @@ Example: R8A7790 (R-Car H2) VSP1-S node reg = <0 0xfe928000 0 0x8000>; interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>; - - renesas,has-lut; - renesas,has-sru; - renesas,#rpf = <5>; - renesas,#uds = <3>; - renesas,#wpf = <4>; }; diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 5b210b69f09c..910d6b8e8b50 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -47,7 +47,8 @@ struct vsp1_uds; #define VSP1_HAS_SRU (1 << 2) #define VSP1_HAS_BRU (1 << 3) -struct vsp1_platform_data { +struct vsp1_device_info { + u32 version; unsigned int features; unsigned int rpf_count; unsigned int uds_count; @@ -58,7 +59,7 @@ struct vsp1_platform_data { struct vsp1_device { struct device *dev; - struct vsp1_platform_data pdata; + const struct vsp1_device_info *info; void __iomem *mmio; struct clk *clock; diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index 32e2009c215a..cb0dbc15ddad 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -416,7 +416,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) bru->entity.type = VSP1_ENTITY_BRU; ret = vsp1_entity_init(vsp1, &bru->entity, - vsp1->pdata.num_bru_inputs + 1); + vsp1->info->num_bru_inputs + 1); if (ret < 0) return ERR_PTR(ret); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index ddd98212bf39..021fe5778cd1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -285,7 +285,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, unsigned long flags; int ret; - if (rpf_index >= vsp1->pdata.rpf_count) + if (rpf_index >= vsp1->info->rpf_count) return -EINVAL; rpf = vsp1->rpf[rpf_index]; @@ -519,7 +519,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1) if (!vsp1->bru || !vsp1->lif) return -ENXIO; - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i]; ret = media_create_pad_link(&rpf->entity.subdev.entity, @@ -572,7 +572,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe->frame_end = vsp1_drm_pipeline_frame_end; /* The DRM pipeline is static, add entities manually. */ - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *input = vsp1->rpf[i]; list_add_tail(&input->entity.list_pipe, &pipe->entities); diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index b2a7d58e3e13..25750a0e4631 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -47,7 +47,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) unsigned int i; u32 status; - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; @@ -153,7 +153,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1) return ret; } - if (vsp1->pdata.features & VSP1_HAS_LIF) { + if (vsp1->info->features & VSP1_HAS_LIF) { ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, &vsp1->lif->entity.subdev.entity, @@ -162,7 +162,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1) return ret; } - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i]; ret = media_create_pad_link(&rpf->video->video.entity, 0, @@ -174,7 +174,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1) return ret; } - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { /* Connect the video device to the WPF. All connections are * immutable except for the WPF0 source link if a LIF is * present. @@ -182,7 +182,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1) struct vsp1_rwpf *wpf = vsp1->wpf[i]; unsigned int flags = MEDIA_LNK_FL_ENABLED; - if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0) + if (!(vsp1->info->features & VSP1_HAS_LIF) || i != 0) flags |= MEDIA_LNK_FL_IMMUTABLE; ret = media_create_pad_link(&wpf->entity.subdev.entity, @@ -215,7 +215,7 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1) media_device_unregister(&vsp1->media_dev); media_device_cleanup(&vsp1->media_dev); - if (!vsp1->pdata.uapi) + if (!vsp1->info->uapi) vsp1_drm_cleanup(vsp1); } @@ -238,7 +238,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) * the pipeline is configured internally by the driver in that case, and * its configuration can thus be trusted. */ - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) vsp1->media_ops.link_validate = v4l2_subdev_link_validate; vdev->mdev = mdev; @@ -250,7 +250,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Instantiate all the entities. */ - if (vsp1->pdata.features & VSP1_HAS_BRU) { + if (vsp1->info->features & VSP1_HAS_BRU) { vsp1->bru = vsp1_bru_create(vsp1); if (IS_ERR(vsp1->bru)) { ret = PTR_ERR(vsp1->bru); @@ -276,7 +276,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities); - if (vsp1->pdata.features & VSP1_HAS_LIF) { + if (vsp1->info->features & VSP1_HAS_LIF) { vsp1->lif = vsp1_lif_create(vsp1); if (IS_ERR(vsp1->lif)) { ret = PTR_ERR(vsp1->lif); @@ -286,7 +286,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities); } - if (vsp1->pdata.features & VSP1_HAS_LUT) { + if (vsp1->info->features & VSP1_HAS_LUT) { vsp1->lut = vsp1_lut_create(vsp1); if (IS_ERR(vsp1->lut)) { ret = PTR_ERR(vsp1->lut); @@ -296,7 +296,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *rpf; rpf = vsp1_rpf_create(vsp1, i); @@ -308,7 +308,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->rpf[i] = rpf; list_add_tail(&rpf->entity.list_dev, &vsp1->entities); - if (vsp1->pdata.uapi) { + if (vsp1->info->uapi) { struct vsp1_video *video = vsp1_video_create(vsp1, rpf); if (IS_ERR(video)) { @@ -320,7 +320,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } } - if (vsp1->pdata.features & VSP1_HAS_SRU) { + if (vsp1->info->features & VSP1_HAS_SRU) { vsp1->sru = vsp1_sru_create(vsp1); if (IS_ERR(vsp1->sru)) { ret = PTR_ERR(vsp1->sru); @@ -330,7 +330,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata.uds_count; ++i) { + for (i = 0; i < vsp1->info->uds_count; ++i) { struct vsp1_uds *uds; uds = vsp1_uds_create(vsp1, i); @@ -343,7 +343,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&uds->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf; wpf = vsp1_wpf_create(vsp1, i); @@ -355,7 +355,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) vsp1->wpf[i] = wpf; list_add_tail(&wpf->entity.list_dev, &vsp1->entities); - if (vsp1->pdata.uapi) { + if (vsp1->info->uapi) { struct vsp1_video *video = vsp1_video_create(vsp1, wpf); if (IS_ERR(video)) { @@ -377,7 +377,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Create links. */ - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) ret = vsp1_uapi_create_links(vsp1); else ret = vsp1_drm_create_links(vsp1); @@ -387,7 +387,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) /* Register subdev nodes if the userspace API is enabled or initialize * the DRM pipeline otherwise. */ - if (vsp1->pdata.uapi) { + if (vsp1->info->uapi) { vsp1->use_dl = false; ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); } else { @@ -438,7 +438,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1) int ret; /* Reset any channel that might be running. */ - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { ret = vsp1_reset_wpf(vsp1, i); if (ret < 0) return ret; @@ -447,10 +447,10 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) | (8 << VI6_CLK_DCSWT_CSTRW_SHIFT)); - for (i = 0; i < vsp1->pdata.rpf_count; ++i) + for (i = 0; i < vsp1->info->rpf_count; ++i) vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED); - for (i = 0; i < vsp1->pdata.uds_count; ++i) + for (i = 0; i < vsp1->info->uds_count; ++i) vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); @@ -567,52 +567,75 @@ static const struct dev_pm_ops vsp1_pm_ops = { * Platform Driver */ -static int vsp1_parse_dt(struct vsp1_device *vsp1) -{ - struct device_node *np = vsp1->dev->of_node; - struct vsp1_platform_data *pdata = &vsp1->pdata; - - if (of_property_read_bool(np, "renesas,has-lif")) - pdata->features |= VSP1_HAS_LIF; - if (of_property_read_bool(np, "renesas,has-lut")) - pdata->features |= VSP1_HAS_LUT; - if (of_property_read_bool(np, "renesas,has-sru")) - pdata->features |= VSP1_HAS_SRU; - - of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count); - of_property_read_u32(np, "renesas,#uds", &pdata->uds_count); - of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count); - - if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) { - dev_err(vsp1->dev, "invalid number of RPF (%u)\n", - pdata->rpf_count); - return -EINVAL; - } - - if (pdata->uds_count > VSP1_MAX_UDS) { - dev_err(vsp1->dev, "invalid number of UDS (%u)\n", - pdata->uds_count); - return -EINVAL; - } - - if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) { - dev_err(vsp1->dev, "invalid number of WPF (%u)\n", - pdata->wpf_count); - return -EINVAL; - } - - pdata->features |= VSP1_HAS_BRU; - pdata->num_bru_inputs = 4; - pdata->uapi = true; - - return 0; -} +static const struct vsp1_device_info vsp1_device_infos[] = { + { + .version = VI6_IP_VERSION_MODEL_VSPS_H2, + .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, + .rpf_count = 5, + .uds_count = 3, + .wpf_count = 4, + .num_bru_inputs = 4, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPR_H2, + .features = VSP1_HAS_BRU | VSP1_HAS_SRU, + .rpf_count = 5, + .uds_count = 1, + .wpf_count = 4, + .num_bru_inputs = 4, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPD_GEN2, + .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, + .rpf_count = 4, + .uds_count = 1, + .wpf_count = 4, + .num_bru_inputs = 4, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPS_M2, + .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, + .rpf_count = 5, + .uds_count = 3, + .wpf_count = 4, + .num_bru_inputs = 4, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPI_GEN3, + .features = VSP1_HAS_LUT | VSP1_HAS_SRU, + .rpf_count = 1, + .uds_count = 1, + .wpf_count = 1, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3, + .features = VSP1_HAS_BRU, + .rpf_count = 5, + .wpf_count = 1, + .num_bru_inputs = 5, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3, + .features = VSP1_HAS_BRU | VSP1_HAS_LUT, + .rpf_count = 5, + .wpf_count = 1, + .num_bru_inputs = 5, + .uapi = true, + }, { + .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, + .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, + .rpf_count = 5, + .wpf_count = 2, + .num_bru_inputs = 5, + }, +}; static int vsp1_probe(struct platform_device *pdev) { struct vsp1_device *vsp1; struct resource *irq; struct resource *io; + unsigned int i; u32 version; int ret; @@ -625,10 +648,6 @@ static int vsp1_probe(struct platform_device *pdev) INIT_LIST_HEAD(&vsp1->entities); INIT_LIST_HEAD(&vsp1->videos); - ret = vsp1_parse_dt(vsp1); - if (ret < 0) - return ret; - /* I/O, IRQ and clock resources */ io = platform_get_resource(pdev, IORESOURCE_MEM, 0); vsp1->mmio = devm_ioremap_resource(&pdev->dev, io); @@ -662,21 +681,21 @@ static int vsp1_probe(struct platform_device *pdev) version = vsp1_read(vsp1, VI6_IP_VERSION); clk_disable_unprepare(vsp1->clock); - dev_dbg(&pdev->dev, "IP version 0x%08x\n", version); + for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) { + if ((version & VI6_IP_VERSION_MODEL_MASK) == + vsp1_device_infos[i].version) { + vsp1->info = &vsp1_device_infos[i]; + break; + } + } - switch (version & VI6_IP_VERSION_MODEL_MASK) { - case VI6_IP_VERSION_MODEL_VSPD_GEN3: - vsp1->pdata.num_bru_inputs = 5; - vsp1->pdata.uapi = false; - break; - - case VI6_IP_VERSION_MODEL_VSPI_GEN3: - case VI6_IP_VERSION_MODEL_VSPBD_GEN3: - case VI6_IP_VERSION_MODEL_VSPBC_GEN3: - vsp1->pdata.features &= ~VSP1_HAS_BRU; - break; + if (!vsp1->info) { + dev_err(&pdev->dev, "unsupported IP version 0x%08x\n", version); + return -ENXIO; } + dev_dbg(&pdev->dev, "IP version 0x%08x\n", version); + /* Instanciate entities */ ret = vsp1_create_entities(vsp1); if (ret < 0) { diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index b9df8349b529..20a78fbd3691 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -45,7 +45,7 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) if (!streaming) return 0; - if (!entity->vsp1->pdata.uapi || !entity->subdev.ctrl_handler) + if (!entity->vsp1->info->uapi || !entity->subdev.ctrl_handler) return 0; ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler); diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 36aa825b5ce6..6659f06b1643 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -368,7 +368,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1) * pipelines twice, first to set them all to the stopping state, and * then to wait for the stop to complete. */ - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; @@ -385,7 +385,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1) spin_unlock_irqrestore(&pipe->irqlock, flags); } - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; @@ -409,7 +409,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1) unsigned int i; /* Resume pipeline all running pipelines. */ - for (i = 0; i < vsp1->pdata.wpf_count; ++i) { + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 1eb9a3ef05c8..5bc1d1574a43 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -151,12 +151,12 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) mutex_lock(rpf->ctrls.lock); vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val); - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) mutex_unlock(rpf->ctrls.lock); vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 6dcf76a1ca57..cc09efbfb24f 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -151,12 +151,12 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) /* Take the control handler lock to ensure that the CTRL0 value won't be * changed behind our back by a set control operation. */ - if (sru->entity.vsp1->pdata.uapi) + if (sru->entity.vsp1->info->uapi) mutex_lock(sru->ctrls.lock); ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0) & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK); vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0); - if (sru->entity.vsp1->pdata.uapi) + if (sru->entity.vsp1->info->uapi) mutex_unlock(sru->ctrls.lock); vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index b2eecabdc399..61ee0f92c1e5 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -324,7 +324,7 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, /* Follow links downstream for each input and make sure the graph * contains no loop and that all branches end at the output WPF. */ - for (i = 0; i < video->vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < video->vsp1->info->rpf_count; ++i) { if (!pipe->inputs[i]) continue; @@ -456,7 +456,7 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) unsigned int i; /* Complete buffers on all video nodes. */ - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { if (!pipe->inputs[i]) continue; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 4a741a597878..c78d4af50fcf 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -98,7 +98,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) * inputs as sub-layers and select the virtual RPF as the master * layer. */ - for (i = 0; i < vsp1->pdata.rpf_count; ++i) { + for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *input = pipe->inputs[i]; if (!input) @@ -155,11 +155,11 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) /* Take the control handler lock to ensure that the PDV value won't be * changed behind our back by a set control operation. */ - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) mutex_lock(wpf->ctrls.lock); outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT; vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); - if (vsp1->pdata.uapi) + if (vsp1->info->uapi) mutex_unlock(wpf->ctrls.lock); vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index), -- cgit v1.2.3 From 18922936dc2817488ebba985c5aaf3498f2ef96d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 19 Feb 2016 10:02:53 -0200 Subject: [media] vsp1_drm.h: add missing prototypes drivers/media/platform/vsp1/vsp1_drm.c:47:5: warning: no previous prototype for 'vsp1_du_init' [-Wmissing-prototypes] int vsp1_du_init(struct device *dev) ^ drivers/media/platform/vsp1/vsp1_drm.c:76:5: warning: no previous prototype for 'vsp1_du_setup_lif' [-Wmissing-prototypes] int vsp1_du_setup_lif(struct device *dev, unsigned int width, ^ drivers/media/platform/vsp1/vsp1_drm.c:221:6: warning: no previous prototype for 'vsp1_du_atomic_begin' [-Wmissing-prototypes] void vsp1_du_atomic_begin(struct device *dev) ^ drivers/media/platform/vsp1/vsp1_drm.c:273:5: warning: no previous prototype for 'vsp1_du_atomic_update' [-Wmissing-prototypes] int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, ^ drivers/media/platform/vsp1/vsp1_drm.c:451:6: warning: no previous prototype for 'vsp1_du_atomic_flush' [-Wmissing-prototypes] void vsp1_du_atomic_flush(struct device *dev) ^ Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drm.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index 7704038c3add..f68056838319 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -35,4 +35,15 @@ int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); +int vsp1_du_init(struct device *dev); +int vsp1_du_setup_lif(struct device *dev, unsigned int width, + unsigned int height); +void vsp1_du_atomic_begin(struct device *dev); +int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + u32 pixelformat, unsigned int pitch, + dma_addr_t mem[2], const struct v4l2_rect *src, + const struct v4l2_rect *dst); +void vsp1_du_atomic_flush(struct device *dev); + + #endif /* __VSP1_DRM_H__ */ -- cgit v1.2.3