public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul
@ 2013-03-02 23:45 Hans Verkuil
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
  2013-03-07 18:46 ` [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Ismael Luceno
  0 siblings, 2 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno

Hi all,

This patch series updates the solo6x10 staging driver to a usable state.

It has been tested with my Bluecherry BC-04120A MPEG4 4 port video encoder/decoder
card, generously provided by Bluecherry about two years ago.

Most of these fixes are the usual fall-out from testing with v4l2-compliance,
but due to the many locking errors in this driver I decided to also convert
it to vb2. It was frankly easier then trying to fix the locking madness
caused by the interaction between threads and videobuf.

Currently this driver seems to be quite reliable (I haven't done any long-term
tests though), but there are a few TODO items:

1) Most importantly, the video from video0 is broken: it is supposed to be
   either one of the four inputs or a 2x2 image of all four inputs, instead I
   always get the first video line of the input repeated for the whole image.

   I have no idea why and it would be very nice if someone from Bluecherry
   can look at this. I do not see anything wrong in the DMA code, so it is
   a mystery to me. I'm beginning to wonder if you are actually supposed to
   be able to DMA from video0!

2) I couldn't get it to work on a big-endian system. I keep getting
   SOLO_PCI_ERR_P2M_DESC errors, but I see nothing wrong with the DMA
   descriptor. Perhaps if someone with a solo datasheet can tell me the
   possible causes of that error interrupt I might be able to figure it
   out. It's just the DMA setup that does something wrong, the rest seems
   fine.

3) What is the meaning of this snippet of code in v4l2-enc.c?

	if (pix->priv)
		solo_enc->type = SOLO_ENC_TYPE_EXT;

   I've commented it out since it is completely undocumented and no driver
   should assume that priv is non-zero anymore, precisely because of issues
   like this. Ismael, do you know what the difference is between SOLO_ENC_TYPE_STD
   and SOLO_ENC_TYPE_EXT?

4) Most of the sources and headers need to be renamed with a solo6x10- prefix.
   The current names are too general.

5) There is a custom extension for motion detection. I left that part unchanged
   as it doesn't look too bad, but I am unable to test it properly. I've
   ordered a suitable CCTV camera from dealextreme, but that will take a few
   weeks before I have it (dx.com is cheap, but delivery is quite slow). I'd
   like to experiment a bit with this.

6) The tw28* 'drivers' should really be split off as subdevice drivers, but
   unfortunately I don't have a datasheet for the tw2815 (I found one for the
   tw2864 though). If I ever get hold of a datasheet, then creating subdev
   drivers for this would be nice.

7) The kernel threads really should be replaced by workqueues.

All in all this driver is now almost ready to go into the mainline part of
the kernel. Before that's done I'd like to get items 1, 3 and 5 resolved
first. Ismael, it would be great if you could help me out with 1 and 3!

Regards,

	Hans


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC PATCH 01/20] videobuf2: add gfp_flags.
  2013-03-02 23:45 [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Hans Verkuil
@ 2013-03-02 23:45 ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 02/20] vb2-dma-sg: add debug module option Hans Verkuil
                     ` (18 more replies)
  2013-03-07 18:46 ` [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Ismael Luceno
  1 sibling, 19 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Some drivers have special memory requirements for their buffers, usually
related to DMA (e.g. GFP_DMA or __GFP_DMA32). Make it possible to specify
additional GFP flags for those buffers by adding a gfp_flags field to
vb2_queue.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c       |    2 +-
 drivers/media/v4l2-core/videobuf2-dma-contig.c |    5 +++--
 drivers/media/v4l2-core/videobuf2-dma-sg.c     |    5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c    |    4 ++--
 include/media/videobuf2-core.h                 |   10 ++++++++--
 5 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index db1235d..adde3e6 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -57,7 +57,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 	/* Allocate memory for all planes in this buffer */
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
-				      q->plane_sizes[plane]);
+				      q->plane_sizes[plane], q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 10beaee..ae35d25 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -152,7 +152,7 @@ static void vb2_dc_put(void *buf_priv)
 	kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct device *dev = conf->dev;
@@ -165,7 +165,8 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	/* align image size to PAGE_SIZE */
 	size = PAGE_ALIGN(size);
 
-	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
+	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
+						GFP_KERNEL | gfp_flags);
 	if (!buf->vaddr) {
 		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
 		kfree(buf);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 25c3b36..952776f 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -33,7 +33,7 @@ struct vb2_dma_sg_buf {
 
 static void vb2_dma_sg_put(void *buf_priv);
 
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_dma_sg_buf *buf;
 	int i;
@@ -60,7 +60,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
 		goto fail_pages_array_alloc;
 
 	for (i = 0; i < buf->sg_desc.num_pages; ++i) {
-		buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
+		buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO |
+					   __GFP_NOWARN | gfp_flags);
 		if (NULL == buf->pages[i])
 			goto fail_pages_alloc;
 		sg_set_page(&buf->sg_desc.sglist[i],
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index a47fd4f..313d977 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -35,11 +35,11 @@ struct vb2_vmalloc_buf {
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_vmalloc_buf *buf;
 
-	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags);
 	if (!buf)
 		return NULL;
 
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 9cfd4ee..251d66b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -27,7 +27,9 @@ struct vb2_fileio_data;
  *		return NULL on failure or a pointer to allocator private,
  *		per-buffer data on success; the returned private structure
  *		will then be passed as buf_priv argument to other ops in this
- *		structure
+ *		structure. Additional gfp_flags to use when allocating the
+ *		are also passed to this operation. These flags are from the
+ *		gfp_flags field of vb2_queue.
  * @put:	inform the allocator that the buffer will no longer be used;
  *		usually will result in the allocator freeing the buffer (if
  *		no other users of this buffer are present); the buf_priv
@@ -79,7 +81,7 @@ struct vb2_fileio_data;
  *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
-	void		*(*alloc)(void *alloc_ctx, unsigned long size);
+	void		*(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
 	void		(*put)(void *buf_priv);
 	struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
@@ -302,6 +304,9 @@ struct v4l2_fh;
  * @buf_struct_size: size of the driver-specific buffer structure;
  *		"0" indicates the driver doesn't want to use a custom buffer
  *		structure type, so sizeof(struct vb2_buffer) will is used
+ * @gfp_flags:	additional gfp flags used when allocating the buffers.
+ *		Typically this is 0, but it may be e.g. GFP_DMA or __GFP_DMA32
+ *		to force the buffer allocation to a specific memory zone.
  *
  * @memory:	current memory type used
  * @bufs:	videobuf buffer structures
@@ -326,6 +331,7 @@ struct vb2_queue {
 	const struct vb2_mem_ops	*mem_ops;
 	void				*drv_priv;
 	unsigned int			buf_struct_size;
+	gfp_t				gfp_flags;
 
 /* private: internal use only */
 	enum v4l2_memory		memory;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 02/20] vb2-dma-sg: add debug module option.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 03/20] solo6x10: fix querycap Hans Verkuil
                     ` (17 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This prevents the kernel log from being spammed with these messages.
By turning on the debug option you will see them again.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-dma-sg.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 952776f..59522b2 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -21,6 +21,15 @@
 #include <media/videobuf2-memops.h>
 #include <media/videobuf2-dma-sg.h>
 
+static int debug;
+module_param(debug, int, 0644);
+
+#define dprintk(level, fmt, arg...)					\
+	do {								\
+		if (debug >= level)					\
+			printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg);	\
+	} while (0)
+
 struct vb2_dma_sg_buf {
 	void				*vaddr;
 	struct page			**pages;
@@ -74,7 +83,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
 
 	atomic_inc(&buf->refcount);
 
-	printk(KERN_DEBUG "%s: Allocated buffer of %d pages\n",
+	dprintk(1, "%s: Allocated buffer of %d pages\n",
 		__func__, buf->sg_desc.num_pages);
 	return buf;
 
@@ -97,7 +106,7 @@ static void vb2_dma_sg_put(void *buf_priv)
 	int i = buf->sg_desc.num_pages;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
-		printk(KERN_DEBUG "%s: Freeing buffer of %d pages\n", __func__,
+		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->sg_desc.num_pages);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
@@ -163,7 +172,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	return buf;
 
 userptr_fail_get_user_pages:
-	printk(KERN_DEBUG "get_user_pages requested/got: %d/%d]\n",
+	dprintk(1, "get_user_pages requested/got: %d/%d]\n",
 	       num_pages_from_user, buf->sg_desc.num_pages);
 	while (--num_pages_from_user >= 0)
 		put_page(buf->pages[num_pages_from_user]);
@@ -186,7 +195,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 	struct vb2_dma_sg_buf *buf = buf_priv;
 	int i = buf->sg_desc.num_pages;
 
-	printk(KERN_DEBUG "%s: Releasing userspace buffer of %d pages\n",
+	dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 	       __func__, buf->sg_desc.num_pages);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 03/20] solo6x10: fix querycap.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 02/20] vb2-dma-sg: add debug module option Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 04/20] solo6x10: add v4l2_device Hans Verkuil
                     ` (16 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Setup correct bus_info, let the v4l2 core set the version and add device_caps
support.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |    9 ++++-----
 drivers/staging/media/solo6x10/v4l2.c     |    9 ++++-----
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 4977e86..85e90df 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -1061,12 +1061,11 @@ static int solo_enc_querycap(struct file *file, void  *priv,
 	strcpy(cap->driver, SOLO6X10_NAME);
 	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
 		 solo_enc->ch);
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
 		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6X10_VER_NUM;
-	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index ca774cc..9c69c34 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -573,12 +573,11 @@ static int solo_querycap(struct file *file, void  *priv,
 
 	strcpy(cap->driver, SOLO6X10_NAME);
 	strcpy(cap->card, "Softlogic 6x10");
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
 		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6X10_VER_NUM;
-	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 04/20] solo6x10: add v4l2_device.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 02/20] vb2-dma-sg: add debug module option Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 03/20] solo6x10: fix querycap Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 05/20] solo6x10: add control framework Hans Verkuil
                     ` (15 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add support for struct v4l2_device.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/core.c     |    8 ++++++--
 drivers/staging/media/solo6x10/solo6x10.h |    2 ++
 drivers/staging/media/solo6x10/v4l2-enc.c |    2 +-
 drivers/staging/media/solo6x10/v4l2.c     |    2 +-
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
index fd83d6d..f571a24 100644
--- a/drivers/staging/media/solo6x10/core.c
+++ b/drivers/staging/media/solo6x10/core.c
@@ -124,6 +124,7 @@ static void free_solo_dev(struct solo_dev *solo_dev)
 
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
+	v4l2_device_unregister(&solo_dev->v4l2_dev);
 	pci_set_drvdata(pdev, NULL);
 
 	kfree(solo_dev);
@@ -144,7 +145,9 @@ static int solo_pci_probe(struct pci_dev *pdev,
 
 	solo_dev->pdev = pdev;
 	spin_lock_init(&solo_dev->reg_io_lock);
-	pci_set_drvdata(pdev, solo_dev);
+	ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
+	if (ret)
+		goto fail_probe;
 
 	ret = pci_enable_device(pdev);
 	if (ret)
@@ -286,7 +289,8 @@ fail_probe:
 
 static void solo_pci_remove(struct pci_dev *pdev)
 {
-	struct solo_dev *solo_dev = pci_get_drvdata(pdev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+	struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
 
 	free_solo_dev(solo_dev);
 }
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index abee721..8fd3a6a 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -33,6 +33,7 @@
 #include <linux/atomic.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
 #include <media/videobuf-core.h>
 #include "registers.h"
 
@@ -189,6 +190,7 @@ struct solo_dev {
 	u32			irq_mask;
 	u32			motion_mask;
 	spinlock_t		reg_io_lock;
+	struct v4l2_device	v4l2_dev;
 
 	/* tw28xx accounting */
 	u8			tw2865, tw2864, tw2815;
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 85e90df..a949a14 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -1746,7 +1746,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	solo_enc->ch = ch;
 
 	*solo_enc->vfd = solo_enc_template;
-	solo_enc->vfd->parent = &solo_dev->pdev->dev;
+	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
 	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
 				    video_nr);
 	if (ret < 0) {
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index 9c69c34..f15ca03 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -912,7 +912,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 		return -ENOMEM;
 
 	*solo_dev->vfd = solo_v4l2_template;
-	solo_dev->vfd->parent = &solo_dev->pdev->dev;
+	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
 
 	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
 	if (ret < 0) {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 05/20] solo6x10: add control framework.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (2 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 04/20] solo6x10: add v4l2_device Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 06/20] solo6x10: fix scheduling while atomic error Hans Verkuil
                     ` (14 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/solo6x10.h |   12 +-
 drivers/staging/media/solo6x10/tw28.c     |   12 +-
 drivers/staging/media/solo6x10/tw28.h     |    1 +
 drivers/staging/media/solo6x10/v4l2-enc.c |  342 ++++++++---------------------
 drivers/staging/media/solo6x10/v4l2.c     |   83 +++----
 5 files changed, 130 insertions(+), 320 deletions(-)

diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 8fd3a6a..4e32065 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -34,6 +34,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 #include <media/videobuf-core.h>
 #include "registers.h"
 
@@ -114,11 +115,14 @@
 #define V4L2_BUF_FLAG_MOTION_ON		0x0400
 #define V4L2_BUF_FLAG_MOTION_DETECTED	0x0800
 #endif
+
 #ifndef V4L2_CID_MOTION_ENABLE
 #define PRIVATE_CIDS
-#define V4L2_CID_MOTION_ENABLE		(V4L2_CID_PRIVATE_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD	(V4L2_CID_PRIVATE_BASE+1)
-#define V4L2_CID_MOTION_TRACE		(V4L2_CID_PRIVATE_BASE+2)
+#define SOLO_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
+#define V4L2_CID_MOTION_ENABLE		(SOLO_CID_CUSTOM_BASE+0)
+#define V4L2_CID_MOTION_THRESHOLD	(SOLO_CID_CUSTOM_BASE+1)
+#define V4L2_CID_MOTION_TRACE		(SOLO_CID_CUSTOM_BASE+2)
+#define V4L2_CID_OSD_TEXT		(SOLO_CID_CUSTOM_BASE+3)
 #endif
 
 enum SOLO_I2C_STATE {
@@ -152,6 +156,7 @@ enum solo_enc_types {
 struct solo_enc_dev {
 	struct solo_dev		*solo_dev;
 	/* V4L2 Items */
+	struct v4l2_ctrl_handler hdl;
 	struct video_device	*vfd;
 	/* General accounting */
 	wait_queue_head_t	thread_wait;
@@ -215,6 +220,7 @@ struct solo_dev {
 	unsigned int		frame_blank;
 	u8			cur_disp_ch;
 	wait_queue_head_t	disp_thread_wait;
+	struct v4l2_ctrl_handler disp_hdl;
 
 	/* V4L2 Encoder items */
 	struct solo_enc_dev	*v4l2_enc[SOLO_MAX_CHANNELS];
diff --git a/drivers/staging/media/solo6x10/tw28.c b/drivers/staging/media/solo6x10/tw28.c
index db56b42..aea56c7 100644
--- a/drivers/staging/media/solo6x10/tw28.c
+++ b/drivers/staging/media/solo6x10/tw28.c
@@ -635,6 +635,11 @@ u16 tw28_get_audio_status(struct solo_dev *solo_dev)
 }
 #endif
 
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch)
+{
+	return is_tw286x(solo_dev, ch / 4);
+}
+
 int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val)
 {
 	char sval;
@@ -650,8 +655,6 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val)
 	switch (ctrl) {
 	case V4L2_CID_SHARPNESS:
 		/* Only 286x has sharpness */
-		if (val > 0x0f || val < 0)
-			return -ERANGE;
 		if (is_tw286x(solo_dev, chip_num)) {
 			u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
 						 TW_CHIP_OFFSET_ADDR(chip_num),
@@ -661,8 +664,9 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val)
 			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
 					   TW_CHIP_OFFSET_ADDR(chip_num),
 					   TW286x_SHARPNESS(chip_num), v);
-		} else if (val != 0)
-			return -ERANGE;
+		} else {
+			return -EINVAL;
+		}
 		break;
 
 	case V4L2_CID_HUE:
diff --git a/drivers/staging/media/solo6x10/tw28.h b/drivers/staging/media/solo6x10/tw28.h
index a44a03a..9a6c733 100644
--- a/drivers/staging/media/solo6x10/tw28.h
+++ b/drivers/staging/media/solo6x10/tw28.h
@@ -50,6 +50,7 @@ int solo_tw28_init(struct solo_dev *solo_dev);
 
 int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val);
 int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val);
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch);
 
 u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch);
 void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val);
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index a949a14..71d9656f 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -48,40 +48,6 @@ struct solo_enc_fh {
 	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
 };
 
-static const u32 solo_user_ctrls[] = {
-	V4L2_CID_BRIGHTNESS,
-	V4L2_CID_CONTRAST,
-	V4L2_CID_SATURATION,
-	V4L2_CID_HUE,
-	V4L2_CID_SHARPNESS,
-	0
-};
-
-static const u32 solo_mpeg_ctrls[] = {
-	V4L2_CID_MPEG_VIDEO_ENCODING,
-	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-	0
-};
-
-static const u32 solo_private_ctrls[] = {
-	V4L2_CID_MOTION_ENABLE,
-	V4L2_CID_MOTION_THRESHOLD,
-	0
-};
-
-static const u32 solo_fmtx_ctrls[] = {
-	V4L2_CID_RDS_TX_RADIO_TEXT,
-	0
-};
-
-static const u32 *solo_ctrl_classes[] = {
-	solo_user_ctrls,
-	solo_mpeg_ctrls,
-	solo_fmtx_ctrls,
-	solo_private_ctrls,
-	NULL
-};
-
 static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
@@ -1438,123 +1404,10 @@ static int solo_s_parm(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_queryctrl(struct file *file, void *priv,
-			  struct v4l2_queryctrl *qc)
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
-	if (!qc->id)
-		return -EINVAL;
-
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, 0x00, 0xff, 1, 0x80);
-	case V4L2_CID_SHARPNESS:
-		return v4l2_ctrl_query_fill(qc, 0x00, 0x0f, 1, 0x00);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		return v4l2_ctrl_query_fill(
-			qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
-			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		return v4l2_ctrl_query_fill(qc, 1, 255, 1, solo_dev->fps);
-#ifdef PRIVATE_CIDS
-	case V4L2_CID_MOTION_THRESHOLD:
-		qc->flags |= V4L2_CTRL_FLAG_SLIDER;
-		qc->type = V4L2_CTRL_TYPE_INTEGER;
-		qc->minimum = 0;
-		qc->maximum = 0xffff;
-		qc->step = 1;
-		qc->default_value = SOLO_DEF_MOT_THRESH;
-		strlcpy(qc->name, "Motion Detection Threshold",
-			sizeof(qc->name));
-		return 0;
-	case V4L2_CID_MOTION_ENABLE:
-		qc->type = V4L2_CTRL_TYPE_BOOLEAN;
-		qc->minimum = 0;
-		qc->maximum = qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "Motion Detection Enable", sizeof(qc->name));
-		return 0;
-#else
-	case V4L2_CID_MOTION_THRESHOLD:
-		return v4l2_ctrl_query_fill(qc, 0, 0xffff, 1,
-					    SOLO_DEF_MOT_THRESH);
-	case V4L2_CID_MOTION_ENABLE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-#endif
-	case V4L2_CID_RDS_TX_RADIO_TEXT:
-		qc->type = V4L2_CTRL_TYPE_STRING;
-		qc->minimum = 0;
-		qc->maximum = OSD_TEXT_MAX;
-		qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "OSD Text", sizeof(qc->name));
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int solo_querymenu(struct file *file, void *priv,
-			  struct v4l2_querymenu *qmenu)
-{
-	struct v4l2_queryctrl qctrl;
-	int err;
-
-	qctrl.id = qmenu->id;
-	err = solo_queryctrl(file, priv, &qctrl);
-	if (err)
-		return err;
-
-	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
-}
-
-static int solo_g_ctrl(struct file *file, void *priv,
-		       struct v4l2_control *ctrl)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SHARPNESS:
-		return tw28_get_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
-					 &ctrl->value);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		ctrl->value = solo_enc->gop;
-		break;
-	case V4L2_CID_MOTION_THRESHOLD:
-		ctrl->value = solo_enc->motion_thresh;
-		break;
-	case V4L2_CID_MOTION_ENABLE:
-		ctrl->value = solo_is_motion_on(solo_enc);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int solo_s_ctrl(struct file *file, void *priv,
-		       struct v4l2_control *ctrl)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc =
+		container_of(ctrl->handler, struct solo_enc_dev, hdl);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 	switch (ctrl->id) {
@@ -1564,112 +1417,31 @@ static int solo_s_ctrl(struct file *file, void *priv,
 	case V4L2_CID_HUE:
 	case V4L2_CID_SHARPNESS:
 		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
-					 ctrl->value);
+					 ctrl->val);
 	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		if (ctrl->value != V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
-			return -ERANGE;
-		break;
+		return 0;
 	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		if (ctrl->value < 1 || ctrl->value > 255)
-			return -ERANGE;
-		solo_enc->gop = ctrl->value;
+		solo_enc->gop = ctrl->val;
 		solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch),
 			       solo_enc->gop);
 		solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch),
 			       solo_enc->gop);
-		break;
+		return 0;
 	case V4L2_CID_MOTION_THRESHOLD:
-		/* TODO accept value on lower 16-bits and use high
-		 * 16-bits to assign the value to a specific block */
-		if (ctrl->value < 0 || ctrl->value > 0xffff)
-			return -ERANGE;
-		solo_enc->motion_thresh = ctrl->value;
-		solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->value);
-		break;
+		solo_enc->motion_thresh = ctrl->val;
+		solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->val);
+		return 0;
 	case V4L2_CID_MOTION_ENABLE:
-		solo_motion_toggle(solo_enc, ctrl->value);
-		break;
+		solo_motion_toggle(solo_enc, ctrl->val);
+		return 0;
+	case V4L2_CID_OSD_TEXT:
+		strcpy(solo_enc->osd_text, ctrl->string);
+		return solo_osd_print(solo_enc);
 	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int solo_s_ext_ctrls(struct file *file, void *priv,
-			    struct v4l2_ext_controls *ctrls)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	int i;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
-		int err;
-
-		switch (ctrl->id) {
-		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			if (ctrl->size - 1 > OSD_TEXT_MAX)
-				err = -ERANGE;
-			else {
-				err = copy_from_user(solo_enc->osd_text,
-						     ctrl->string,
-						     OSD_TEXT_MAX);
-				solo_enc->osd_text[OSD_TEXT_MAX] = '\0';
-				if (!err)
-					err = solo_osd_print(solo_enc);
-				else
-					err = -EFAULT;
-			}
-			break;
-		default:
-			err = -EINVAL;
-		}
-
-		if (err < 0) {
-			ctrls->error_idx = i;
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-static int solo_g_ext_ctrls(struct file *file, void *priv,
-			    struct v4l2_ext_controls *ctrls)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	int i;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
-		int err;
-
-		switch (ctrl->id) {
-		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			if (ctrl->size < OSD_TEXT_MAX) {
-				ctrl->size = OSD_TEXT_MAX;
-				err = -ENOSPC;
-			} else {
-				err = copy_to_user(ctrl->string,
-						   solo_enc->osd_text,
-						   OSD_TEXT_MAX);
-				if (err)
-					err = -EFAULT;
-			}
-			break;
-		default:
-			err = -EINVAL;
-		}
-
-		if (err < 0) {
-			ctrls->error_idx = i;
-			return err;
-		}
+		break;
 	}
 
-	return 0;
+	return -EINVAL;
 }
 
 static const struct v4l2_file_operations solo_enc_fops = {
@@ -1707,13 +1479,6 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
 	/* Video capture parameters */
 	.vidioc_s_parm			= solo_s_parm,
 	.vidioc_g_parm			= solo_g_parm,
-	/* Controls */
-	.vidioc_queryctrl		= solo_queryctrl,
-	.vidioc_querymenu		= solo_querymenu,
-	.vidioc_g_ctrl			= solo_g_ctrl,
-	.vidioc_s_ctrl			= solo_s_ctrl,
-	.vidioc_g_ext_ctrls		= solo_g_ext_ctrls,
-	.vidioc_s_ext_ctrls		= solo_s_ext_ctrls,
 };
 
 static struct video_device solo_enc_template = {
@@ -1727,8 +1492,42 @@ static struct video_device solo_enc_template = {
 	.current_norm		= V4L2_STD_NTSC_M,
 };
 
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD,
+	.name = "Motion Detection Threshold",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.max = 0xffff,
+	.def = SOLO_DEF_MOT_THRESH,
+	.step = 1,
+	.flags = V4L2_CTRL_FLAG_SLIDER,
+};
+
+static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_ENABLE,
+	.name = "Motion Detection Enable",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_OSD_TEXT,
+	.name = "OSD Text",
+	.type = V4L2_CTRL_TYPE_STRING,
+	.max = OSD_TEXT_MAX,
+	.step = 1,
+};
+
 static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 {
+	struct v4l2_ctrl_handler *hdl;
 	struct solo_enc_dev *solo_enc;
 	int ret;
 
@@ -1736,8 +1535,38 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	if (!solo_enc)
 		return ERR_PTR(-ENOMEM);
 
+	hdl = &solo_enc->hdl;
+	v4l2_ctrl_handler_init(hdl, 10);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 127);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 127);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_HUE, 0, 255, 1, 127);
+	if (tw28_has_sharpness(solo_dev, ch))
+		v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0, 15, 1, 0);
+	v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_ENCODING,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 3,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
+	v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+	if (hdl->error) {
+		ret = hdl->error;
+		v4l2_ctrl_handler_free(hdl);
+		kfree(solo_enc);
+		return ERR_PTR(ret);
+	}
+
 	solo_enc->vfd = video_device_alloc();
 	if (!solo_enc->vfd) {
+		v4l2_ctrl_handler_free(hdl);
 		kfree(solo_enc);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -1747,10 +1576,12 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 
 	*solo_enc->vfd = solo_enc_template;
 	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_enc->vfd->ctrl_handler = hdl;
 	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
 				    video_nr);
 	if (ret < 0) {
 		video_device_release(solo_enc->vfd);
+		v4l2_ctrl_handler_free(hdl);
 		kfree(solo_enc);
 		return ERR_PTR(ret);
 	}
@@ -1781,12 +1612,13 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	return solo_enc;
 }
 
-static void solo_enc_free(struct solo_enc_dev *solo_enc)
+static void solo_enc_free(struct solo_enc_dev *solo_enc, int ch)
 {
 	if (solo_enc == NULL)
 		return;
 
 	video_unregister_device(solo_enc->vfd);
+	v4l2_ctrl_handler_free(&solo_enc->hdl);
 	kfree(solo_enc);
 }
 
@@ -1803,7 +1635,7 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev)
 	if (i != solo_dev->nr_chans) {
 		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
 		while (i--)
-			solo_enc_free(solo_dev->v4l2_enc[i]);
+			solo_enc_free(solo_dev->v4l2_enc[i], i);
 		return ret;
 	}
 
@@ -1824,5 +1656,5 @@ void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
 	solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
 
 	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_enc_free(solo_dev->v4l2_enc[i]);
+		solo_enc_free(solo_dev->v4l2_enc[i], i);
 }
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index f15ca03..e0cf498 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -777,64 +777,14 @@ static int solo_s_std(struct file *file, void *priv, v4l2_std_id *i)
 	return 0;
 }
 
-static const u32 solo_motion_ctrls[] = {
-	V4L2_CID_MOTION_TRACE,
-	0
-};
-
-static const u32 *solo_ctrl_classes[] = {
-	solo_motion_ctrls,
-	NULL
-};
-
-static int solo_disp_queryctrl(struct file *file, void *priv,
-			       struct v4l2_queryctrl *qc)
-{
-	qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
-	if (!qc->id)
-		return -EINVAL;
-
-	switch (qc->id) {
-#ifdef PRIVATE_CIDS
-	case V4L2_CID_MOTION_TRACE:
-		qc->type = V4L2_CTRL_TYPE_BOOLEAN;
-		qc->minimum = 0;
-		qc->maximum = qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "Motion Detection Trace", sizeof(qc->name));
-		return 0;
-#else
-	case V4L2_CID_MOTION_TRACE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-#endif
-	}
-	return -EINVAL;
-}
-
-static int solo_disp_g_ctrl(struct file *file, void *priv,
-			    struct v4l2_control *ctrl)
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev =
+		container_of(ctrl->handler, struct solo_dev, disp_hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_MOTION_TRACE:
-		ctrl->value = solo_reg_read(solo_dev, SOLO_VI_MOTION_BAR)
-			? 1 : 0;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int solo_disp_s_ctrl(struct file *file, void *priv,
-			    struct v4l2_control *ctrl)
-{
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MOTION_TRACE:
-		if (ctrl->value) {
+		if (ctrl->val) {
 			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
 					SOLO_VI_MOTION_Y_ADD |
 					SOLO_VI_MOTION_Y_VALUE(0x20) |
@@ -850,6 +800,8 @@ static int solo_disp_s_ctrl(struct file *file, void *priv,
 			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
 		}
 		return 0;
+	default:
+		break;
 	}
 	return -EINVAL;
 }
@@ -883,10 +835,6 @@ static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
 	.vidioc_dqbuf			= solo_dqbuf,
 	.vidioc_streamon		= solo_streamon,
 	.vidioc_streamoff		= solo_streamoff,
-	/* Controls */
-	.vidioc_queryctrl		= solo_disp_queryctrl,
-	.vidioc_g_ctrl			= solo_disp_g_ctrl,
-	.vidioc_s_ctrl			= solo_disp_s_ctrl,
 };
 
 static struct video_device solo_v4l2_template = {
@@ -900,6 +848,19 @@ static struct video_device solo_v4l2_template = {
 	.current_norm		= V4L2_STD_NTSC_M,
 };
 
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_motion_trace_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_TRACE,
+	.name = "Motion Detection Trace",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.step = 1,
+};
+
 int solo_v4l2_init(struct solo_dev *solo_dev)
 {
 	int ret;
@@ -913,6 +874,11 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 
 	*solo_dev->vfd = solo_v4l2_template;
 	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
+	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
+	if (solo_dev->disp_hdl.error)
+		return solo_dev->disp_hdl.error;
+	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
 
 	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
 	if (ret < 0) {
@@ -957,4 +923,5 @@ void solo_v4l2_exit(struct solo_dev *solo_dev)
 		video_unregister_device(solo_dev->vfd);
 		solo_dev->vfd = NULL;
 	}
+	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 06/20] solo6x10: fix scheduling while atomic error.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (3 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 05/20] solo6x10: add control framework Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 07/20] solo6x10: fix various format-related compliancy issues Hans Verkuil
                     ` (13 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 71d9656f..6b5b8c0 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -188,27 +188,26 @@ static void solo_enc_off(struct solo_enc_fh *fh)
 		fh->kthread = NULL;
 	}
 
+	spin_lock(&solo_enc->lock);
 	solo_dev->enc_bw_remain += solo_enc->bw_weight;
 	fh->enc_on = 0;
 
 	if (atomic_dec_return(&solo_enc->readers) > 0)
-		return;
+		goto unlock;
 
 	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
 	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
+unlock:
+	spin_unlock(&solo_enc->lock);
 }
 
 static int solo_start_fh_thread(struct solo_enc_fh *fh)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
-
 	fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6X10_NAME "_enc");
 
 	/* Oops, we had a problem */
 	if (IS_ERR(fh->kthread)) {
-		spin_lock(&solo_enc->lock);
 		solo_enc_off(fh);
-		spin_unlock(&solo_enc->lock);
 
 		return PTR_ERR(fh->kthread);
 	}
@@ -1003,14 +1002,11 @@ static ssize_t solo_enc_read(struct file *file, char __user *data,
 static int solo_enc_release(struct file *file)
 {
 	struct solo_enc_fh *fh = file->private_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
 
 	videobuf_stop(&fh->vidq);
 	videobuf_mmap_free(&fh->vidq);
 
-	spin_lock(&solo_enc->lock);
 	solo_enc_off(fh);
-	spin_unlock(&solo_enc->lock);
 
 	kfree(fh);
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 07/20] solo6x10: fix various format-related compliancy issues.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (4 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 06/20] solo6x10: fix scheduling while atomic error Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 08/20] solo6x10: add support for prio and control event handling Hans Verkuil
                     ` (12 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

- try_fmt should never return -EBUSY.
- invalid pix->field values were not mapped to a valid value.
- the priv field of struct v4l2_pix_format wasn't zeroed.
- the try_fmt error code was not checked in set_fmt.
- enum_framesizes/intervals is valid for both MJPEG and MPEG pixel formats.
- enum_frameintervals didn't check width and height and reported the
  wrong range.
- s_parm didn't set readbuffers.
- don't fail on invalid colorspace, just replace with the valid colorspace.
- bytesperline should be 0 for compressed formats.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |   51 ++++++++++++++++++++---------
 drivers/staging/media/solo6x10/v4l2.c     |   29 +++++++---------
 2 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 6b5b8c0..43ce8c5 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -1105,13 +1105,6 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv,
 	    pix->pixelformat != V4L2_PIX_FMT_MJPEG)
 		return -EINVAL;
 
-	/* We cannot change width/height in mid read */
-	if (atomic_read(&solo_enc->readers) > 0) {
-		if (pix->width != solo_enc->width ||
-		    pix->height != solo_enc->height)
-			return -EBUSY;
-	}
-
 	if (pix->width < solo_dev->video_hsize ||
 	    pix->height < solo_dev->video_vsize << 1) {
 		/* Default to CIF 1/2 size */
@@ -1123,14 +1116,20 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv,
 		pix->height = solo_dev->video_vsize << 1;
 	}
 
-	if (pix->field == V4L2_FIELD_ANY)
-		pix->field = V4L2_FIELD_INTERLACED;
-	else if (pix->field != V4L2_FIELD_INTERLACED)
+	switch (pix->field) {
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_ANY:
+	default:
 		pix->field = V4L2_FIELD_INTERLACED;
+		break;
+	}
 
 	/* Just set these */
 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->priv = 0;
 
 	return 0;
 }
@@ -1147,6 +1146,15 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 	spin_lock(&solo_enc->lock);
 
 	ret = solo_enc_try_fmt_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	/* We cannot change width/height in mid read */
+	if (!ret && atomic_read(&solo_enc->readers) > 0) {
+		if (pix->width != solo_enc->width ||
+		    pix->height != solo_enc->height)
+			ret = -EBUSY;
+	}
 	if (ret) {
 		spin_unlock(&solo_enc->lock);
 		return ret;
@@ -1186,6 +1194,7 @@ static int solo_enc_get_fmt_cap(struct file *file, void *priv,
 		     V4L2_FIELD_NONE;
 	pix->sizeimage = FRAME_BUF_SIZE;
 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
 
 	return 0;
 }
@@ -1298,7 +1307,8 @@ static int solo_enum_framesizes(struct file *file, void *priv,
 	struct solo_enc_fh *fh = priv;
 	struct solo_dev *solo_dev = fh->enc->solo_dev;
 
-	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG)
+	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG &&
+	    fsize->pixel_format != V4L2_PIX_FMT_MJPEG)
 		return -EINVAL;
 
 	switch (fsize->index) {
@@ -1325,16 +1335,24 @@ static int solo_enum_frameintervals(struct file *file, void *priv,
 	struct solo_enc_fh *fh = priv;
 	struct solo_dev *solo_dev = fh->enc->solo_dev;
 
-	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG || fintv->index)
+	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG &&
+	    fintv->pixel_format != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+	if (fintv->index)
+		return -EINVAL;
+	if ((fintv->width != solo_dev->video_hsize >> 1 ||
+	     fintv->height != solo_dev->video_vsize) &&
+	    (fintv->width != solo_dev->video_hsize ||
+	     fintv->height != solo_dev->video_vsize << 1))
 		return -EINVAL;
 
 	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
 
-	fintv->stepwise.min.numerator = solo_dev->fps;
-	fintv->stepwise.min.denominator = 1;
+	fintv->stepwise.min.denominator = solo_dev->fps;
+	fintv->stepwise.min.numerator = 15;
 
-	fintv->stepwise.max.numerator = solo_dev->fps;
-	fintv->stepwise.max.denominator = 15;
+	fintv->stepwise.max.denominator = solo_dev->fps;
+	fintv->stepwise.max.numerator = 1;
 
 	fintv->stepwise.step.numerator = 1;
 	fintv->stepwise.step.denominator = 1;
@@ -1391,6 +1409,7 @@ static int solo_s_parm(struct file *file, void *priv,
 	solo_enc->interval = cp->timeperframe.numerator;
 
 	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->readbuffers = 2;
 
 	solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
 	solo_update_mode(solo_enc);
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index e0cf498..3db65a7 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -28,7 +28,6 @@
 #include "tw28.h"
 
 #define SOLO_HW_BPL		2048
-#define SOLO_DISP_PIX_FIELD	V4L2_FIELD_INTERLACED
 
 /* Image size is two fields, SOLO_HW_BPL is one horizontal line */
 #define solo_vlines(__solo)	(__solo->video_vsize * 2)
@@ -538,7 +537,7 @@ static int solo_v4l2_open(struct file *file)
 	videobuf_queue_sg_init(&fh->vidq, &solo_video_qops,
 			       &solo_dev->pdev->dev, &fh->slock,
 			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       SOLO_DISP_PIX_FIELD,
+			       V4L2_FIELD_INTERLACED,
 			       sizeof(struct videobuf_buffer), fh, NULL);
 
 	return 0;
@@ -672,23 +671,16 @@ static int solo_try_fmt_cap(struct file *file, void *priv,
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	int image_size = solo_image_size(solo_dev);
 
-	/* Check supported sizes */
-	if (pix->width != solo_dev->video_hsize)
-		pix->width = solo_dev->video_hsize;
-	if (pix->height != solo_vlines(solo_dev))
-		pix->height = solo_vlines(solo_dev);
-	if (pix->sizeimage != image_size)
-		pix->sizeimage = image_size;
-
-	/* Check formats */
-	if (pix->field == V4L2_FIELD_ANY)
-		pix->field = SOLO_DISP_PIX_FIELD;
-
-	if (pix->pixelformat != V4L2_PIX_FMT_UYVY ||
-	    pix->field       != SOLO_DISP_PIX_FIELD ||
-	    pix->colorspace  != V4L2_COLORSPACE_SMPTE170M)
+	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
 		return -EINVAL;
 
+	pix->width = solo_dev->video_hsize;
+	pix->height = solo_vlines(solo_dev);
+	pix->sizeimage = image_size;
+	pix->field = V4L2_FIELD_INTERLACED;
+	pix->pixelformat = V4L2_PIX_FMT_UYVY;
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
 	return 0;
 }
 
@@ -715,10 +707,11 @@ static int solo_get_fmt_cap(struct file *file, void *priv,
 	pix->width = solo_dev->video_hsize;
 	pix->height = solo_vlines(solo_dev);
 	pix->pixelformat = V4L2_PIX_FMT_UYVY;
-	pix->field = SOLO_DISP_PIX_FIELD;
+	pix->field = V4L2_FIELD_INTERLACED;
 	pix->sizeimage = solo_image_size(solo_dev);
 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pix->bytesperline = solo_bytesperline(solo_dev);
+	pix->priv = 0;
 
 	return 0;
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 08/20] solo6x10: add support for prio and control event handling.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (5 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 07/20] solo6x10: fix various format-related compliancy issues Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 09/20] solo6x10: move global fields in solo_enc_fh to solo_enc_dev Hans Verkuil
                     ` (11 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |   19 +++++++++++++++++--
 drivers/staging/media/solo6x10/v4l2.c     |   18 ++++++++++++++++--
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 43ce8c5..453bdba 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -23,6 +23,7 @@
 #include <linux/freezer.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
 #include <media/videobuf-dma-sg.h>
 #include "solo6x10.h"
 #include "tw28.h"
@@ -37,7 +38,8 @@ static int solo_enc_thread(void *data);
 extern unsigned video_nr;
 
 struct solo_enc_fh {
-	struct			solo_enc_dev *enc;
+	struct v4l2_fh		fh;
+	struct solo_enc_dev	*enc;
 	u32			fmt;
 	u16			rd_idx;
 	u8			enc_on;
@@ -938,7 +940,11 @@ static unsigned int solo_enc_poll(struct file *file,
 				  struct poll_table_struct *wait)
 {
 	struct solo_enc_fh *fh = file->private_data;
+	unsigned long req_events = poll_requested_events(wait);
+	unsigned res = v4l2_ctrl_poll(file, wait);
 
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return res;
 	return videobuf_poll_stream(file, &fh->vidq, wait);
 }
 
@@ -958,6 +964,7 @@ static int solo_enc_open(struct file *file)
 	if (fh == NULL)
 		return -ENOMEM;
 
+	v4l2_fh_init(&fh->fh, video_devdata(file));
 	fh->enc = solo_enc;
 	file->private_data = fh;
 	INIT_LIST_HEAD(&fh->vidq_active);
@@ -970,7 +977,7 @@ static int solo_enc_open(struct file *file)
 			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			       V4L2_FIELD_INTERLACED,
 			       sizeof(struct videobuf_buffer), fh, NULL);
-
+	v4l2_fh_add(&fh->fh);
 	return 0;
 }
 
@@ -1007,6 +1014,8 @@ static int solo_enc_release(struct file *file)
 	videobuf_mmap_free(&fh->vidq);
 
 	solo_enc_off(fh);
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 
 	kfree(fh);
 
@@ -1129,6 +1138,7 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv,
 	/* Just set these */
 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->bytesperline = 0;
 	pix->priv = 0;
 
 	return 0;
@@ -1494,6 +1504,10 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
 	/* Video capture parameters */
 	.vidioc_s_parm			= solo_s_parm,
 	.vidioc_g_parm			= solo_g_parm,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
 static struct video_device solo_enc_template = {
@@ -1592,6 +1606,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	*solo_enc->vfd = solo_enc_template;
 	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
 	solo_enc->vfd->ctrl_handler = hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
 	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
 				    video_nr);
 	if (ret < 0) {
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index 3db65a7..d9298ac 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -23,6 +23,7 @@
 #include <linux/freezer.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
 #include <media/videobuf-dma-sg.h>
 #include "solo6x10.h"
 #include "tw28.h"
@@ -39,6 +40,7 @@
 
 /* Simple file handle */
 struct solo_filehandle {
+	struct v4l2_fh		fh;
 	struct solo_dev		*solo_dev;
 	struct videobuf_queue	vidq;
 	struct task_struct      *kthread;
@@ -502,8 +504,12 @@ static unsigned int solo_v4l2_poll(struct file *file,
 				   struct poll_table_struct *wait)
 {
 	struct solo_filehandle *fh = file->private_data;
+	unsigned long req_events = poll_requested_events(wait);
+	unsigned res = v4l2_ctrl_poll(file, wait);
 
-	return videobuf_poll_stream(file, &fh->vidq, wait);
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return res;
+	return res | videobuf_poll_stream(file, &fh->vidq, wait);
 }
 
 static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
@@ -523,6 +529,7 @@ static int solo_v4l2_open(struct file *file)
 	if (fh == NULL)
 		return -ENOMEM;
 
+	v4l2_fh_init(&fh->fh, video_devdata(file));
 	spin_lock_init(&fh->slock);
 	INIT_LIST_HEAD(&fh->vidq_active);
 	fh->solo_dev = solo_dev;
@@ -539,7 +546,7 @@ static int solo_v4l2_open(struct file *file)
 			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			       V4L2_FIELD_INTERLACED,
 			       sizeof(struct videobuf_buffer), fh, NULL);
-
+	v4l2_fh_add(&fh->fh);
 	return 0;
 }
 
@@ -559,6 +566,8 @@ static int solo_v4l2_release(struct file *file)
 	videobuf_stop(&fh->vidq);
 	videobuf_mmap_free(&fh->vidq);
 	solo_stop_thread(fh);
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 
 	return 0;
@@ -828,6 +837,10 @@ static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
 	.vidioc_dqbuf			= solo_dqbuf,
 	.vidioc_streamon		= solo_streamon,
 	.vidioc_streamoff		= solo_streamoff,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
 static struct video_device solo_v4l2_template = {
@@ -872,6 +885,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 	if (solo_dev->disp_hdl.error)
 		return solo_dev->disp_hdl.error;
 	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
 
 	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
 	if (ret < 0) {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 09/20] solo6x10: move global fields in solo_enc_fh to solo_enc_dev.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (6 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 08/20] solo6x10: add support for prio and control event handling Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 10/20] solo6x10: move global fields in solo_dev_fh to solo_dev Hans Verkuil
                     ` (10 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

All fields in solo_enc_fh do not belong there since they refer to global
properties. After moving all these fields to solo_enc_dev the solo_dev_fh
struct can be removed completely.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/solo6x10.h |    9 +
 drivers/staging/media/solo6x10/v4l2-enc.c |  287 ++++++++++++-----------------
 2 files changed, 127 insertions(+), 169 deletions(-)

diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 4e32065..ef18abd 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -171,6 +171,15 @@ struct solo_enc_dev {
 	u16			width;
 	u16			height;
 	char			osd_text[OSD_TEXT_MAX + 1];
+
+	u32			fmt;
+	u16			rd_idx;
+	u8			enc_on;
+	enum solo_enc_types	type;
+	struct videobuf_queue	vidq;
+	struct list_head	vidq_active;
+	struct task_struct	*kthread;
+	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
 };
 
 struct solo_enc_buf {
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 453bdba..cb78ea2 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -37,19 +37,6 @@ static int solo_enc_thread(void *data);
 
 extern unsigned video_nr;
 
-struct solo_enc_fh {
-	struct v4l2_fh		fh;
-	struct solo_enc_dev	*enc;
-	u32			fmt;
-	u16			rd_idx;
-	u8			enc_on;
-	enum solo_enc_types	type;
-	struct videobuf_queue	vidq;
-	struct list_head	vidq_active;
-	struct task_struct	*kthread;
-	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
-};
-
 static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
@@ -115,16 +102,15 @@ static void solo_update_mode(struct solo_enc_dev *solo_enc)
 }
 
 /* Should be called with solo_enc->lock held */
-static int solo_enc_on(struct solo_enc_fh *fh)
+static int solo_enc_on(struct solo_enc_dev *solo_enc)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
 	u8 ch = solo_enc->ch;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	u8 interval;
 
 	assert_spin_locked(&solo_enc->lock);
 
-	if (fh->enc_on)
+	if (solo_enc->enc_on)
 		return 0;
 
 	solo_update_mode(solo_enc);
@@ -137,10 +123,10 @@ static int solo_enc_on(struct solo_enc_fh *fh)
 			solo_dev->enc_bw_remain -= solo_enc->bw_weight;
 	}
 
-	fh->enc_on = 1;
-	fh->rd_idx = solo_enc->solo_dev->enc_wr_idx;
+	solo_enc->enc_on = 1;
+	solo_enc->rd_idx = solo_enc->solo_dev->enc_wr_idx;
 
-	if (fh->type == SOLO_ENC_TYPE_EXT)
+	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
 		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
 
 	if (atomic_inc_return(&solo_enc->readers) > 1)
@@ -177,22 +163,21 @@ static int solo_enc_on(struct solo_enc_fh *fh)
 	return 0;
 }
 
-static void solo_enc_off(struct solo_enc_fh *fh)
+static void solo_enc_off(struct solo_enc_dev *solo_enc)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
-	if (!fh->enc_on)
+	if (!solo_enc->enc_on)
 		return;
 
-	if (fh->kthread) {
-		kthread_stop(fh->kthread);
-		fh->kthread = NULL;
+	if (solo_enc->kthread) {
+		kthread_stop(solo_enc->kthread);
+		solo_enc->kthread = NULL;
 	}
 
 	spin_lock(&solo_enc->lock);
 	solo_dev->enc_bw_remain += solo_enc->bw_weight;
-	fh->enc_on = 0;
+	solo_enc->enc_on = 0;
 
 	if (atomic_dec_return(&solo_enc->readers) > 0)
 		goto unlock;
@@ -203,15 +188,15 @@ unlock:
 	spin_unlock(&solo_enc->lock);
 }
 
-static int solo_start_fh_thread(struct solo_enc_fh *fh)
+static int solo_start_thread(struct solo_enc_dev *solo_enc)
 {
-	fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6X10_NAME "_enc");
+	solo_enc->kthread = kthread_run(solo_enc_thread, solo_enc, SOLO6X10_NAME "_enc");
 
 	/* Oops, we had a problem */
-	if (IS_ERR(fh->kthread)) {
-		solo_enc_off(fh);
+	if (IS_ERR(solo_enc->kthread)) {
+		solo_enc_off(solo_enc);
 
-		return PTR_ERR(fh->kthread);
+		return PTR_ERR(solo_enc->kthread);
 	}
 
 	return 0;
@@ -384,20 +369,20 @@ static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
 	}
 }
 
-static int solo_fill_jpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
+static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *enc_buf,
 			  struct videobuf_buffer *vb,
 			  struct videobuf_dmabuf *vbuf)
 {
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	int size = enc_buf->jpeg_size;
 
 	/* Copy the header first (direct write) */
-	solo_jpeg_header(fh->enc, vbuf);
+	solo_jpeg_header(solo_enc, vbuf);
 
 	vb->size = size + sizeof(jpeg_header);
 
 	/* Grab the jpeg frame */
-	return enc_get_jpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
+	return enc_get_jpeg_dma_sg(solo_dev, solo_enc->desc, vbuf->sglist,
 				   sizeof(jpeg_header),
 				   enc_buf->jpeg_off, size);
 }
@@ -584,11 +569,10 @@ static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh)
 	write_h264_end(out, &bits, 1);
 }
 
-static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
+static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *enc_buf,
 			  struct videobuf_buffer *vb,
 			  struct videobuf_dmabuf *vbuf)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 #define VH_WORDS 16
@@ -634,23 +618,22 @@ static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
 	frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
 	frame_size = enc_buf->size - sizeof(vh);
 
-	ret = enc_get_mpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
+	ret = enc_get_mpeg_dma_sg(solo_dev, solo_enc->desc, vbuf->sglist,
 				  skip, frame_off, frame_size);
 	WARN_ON_ONCE(ret);
 
 	return ret;
 }
 
-static void solo_enc_fillbuf(struct solo_enc_fh *fh,
+static void solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
 			    struct videobuf_buffer *vb)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct solo_enc_buf *enc_buf = NULL;
 	struct videobuf_dmabuf *vbuf;
 	int ret;
 	int error = 1;
-	u16 idx = fh->rd_idx;
+	u16 idx = solo_enc->rd_idx;
 
 	while (idx != solo_dev->enc_wr_idx) {
 		struct solo_enc_buf *ebuf = &solo_dev->enc_buf[idx];
@@ -660,8 +643,8 @@ static void solo_enc_fillbuf(struct solo_enc_fh *fh,
 		if (ebuf->ch != solo_enc->ch)
 			continue;
 
-		if (fh->fmt == V4L2_PIX_FMT_MPEG) {
-			if (fh->type == ebuf->type) {
+		if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) {
+			if (solo_enc->type == ebuf->type) {
 				enc_buf = ebuf;
 				break;
 			}
@@ -671,14 +654,14 @@ static void solo_enc_fillbuf(struct solo_enc_fh *fh,
 		}
 	}
 
-	fh->rd_idx = idx;
+	solo_enc->rd_idx = idx;
 
 	if (WARN_ON_ONCE(!enc_buf))
 		goto buf_err;
 
-	if ((fh->fmt == V4L2_PIX_FMT_MPEG &&
+	if ((solo_enc->fmt == V4L2_PIX_FMT_MPEG &&
 	     vb->bsize < enc_buf->size) ||
-	    (fh->fmt == V4L2_PIX_FMT_MJPEG &&
+	    (solo_enc->fmt == V4L2_PIX_FMT_MJPEG &&
 	     vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
 		WARN_ON_ONCE(1);
 		goto buf_err;
@@ -688,10 +671,10 @@ static void solo_enc_fillbuf(struct solo_enc_fh *fh,
 	if (WARN_ON_ONCE(!vbuf))
 		goto buf_err;
 
-	if (fh->fmt == V4L2_PIX_FMT_MPEG)
-		ret = solo_fill_mpeg(fh, enc_buf, vb, vbuf);
+	if (solo_enc->fmt == V4L2_PIX_FMT_MPEG)
+		ret = solo_fill_mpeg(solo_enc, enc_buf, vb, vbuf);
 	else
-		ret = solo_fill_jpeg(fh, enc_buf, vb, vbuf);
+		ret = solo_fill_jpeg(solo_enc, enc_buf, vb, vbuf);
 
 	if (!ret)
 		error = 0;
@@ -710,22 +693,21 @@ buf_err:
 	return;
 }
 
-static void solo_enc_thread_try(struct solo_enc_fh *fh)
+static void solo_enc_thread_try(struct solo_enc_dev *solo_enc)
 {
-	struct solo_enc_dev *solo_enc = fh->enc;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct videobuf_buffer *vb;
 
 	for (;;) {
 		spin_lock(&solo_enc->lock);
 
-		if (fh->rd_idx == solo_dev->enc_wr_idx)
+		if (solo_enc->rd_idx == solo_dev->enc_wr_idx)
 			break;
 
-		if (list_empty(&fh->vidq_active))
+		if (list_empty(&solo_enc->vidq_active))
 			break;
 
-		vb = list_first_entry(&fh->vidq_active,
+		vb = list_first_entry(&solo_enc->vidq_active,
 				      struct videobuf_buffer, queue);
 
 		if (!waitqueue_active(&vb->done))
@@ -735,7 +717,7 @@ static void solo_enc_thread_try(struct solo_enc_fh *fh)
 
 		spin_unlock(&solo_enc->lock);
 
-		solo_enc_fillbuf(fh, vb);
+		solo_enc_fillbuf(solo_enc, vb);
 	}
 
 	assert_spin_locked(&solo_enc->lock);
@@ -744,8 +726,7 @@ static void solo_enc_thread_try(struct solo_enc_fh *fh)
 
 static int solo_enc_thread(void *data)
 {
-	struct solo_enc_fh *fh = data;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = data;
 	DECLARE_WAITQUEUE(wait, current);
 
 	set_freezable();
@@ -755,7 +736,7 @@ static int solo_enc_thread(void *data)
 		long timeout = schedule_timeout_interruptible(HZ);
 		if (timeout == -ERESTARTSYS || kthread_should_stop())
 			break;
-		solo_enc_thread_try(fh);
+		solo_enc_thread_try(solo_enc);
 		try_to_freeze();
 	}
 
@@ -882,8 +863,7 @@ static int solo_enc_buf_prepare(struct videobuf_queue *vq,
 				struct videobuf_buffer *vb,
 				enum v4l2_field field)
 {
-	struct solo_enc_fh *fh = vq->priv_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = vq->priv_data;
 
 	vb->size = FRAME_BUF_SIZE;
 	if (vb->baddr != 0 && vb->bsize < vb->size)
@@ -912,11 +892,11 @@ static int solo_enc_buf_prepare(struct videobuf_queue *vq,
 static void solo_enc_buf_queue(struct videobuf_queue *vq,
 			       struct videobuf_buffer *vb)
 {
-	struct solo_enc_fh *fh = vq->priv_data;
+	struct solo_enc_dev *solo_enc = vq->priv_data;
 
 	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &fh->vidq_active);
-	wake_up_interruptible(&fh->enc->thread_wait);
+	list_add_tail(&vb->queue, &solo_enc->vidq_active);
+	wake_up_interruptible(&solo_enc->thread_wait);
 }
 
 static void solo_enc_buf_release(struct videobuf_queue *vq,
@@ -939,94 +919,61 @@ static struct videobuf_queue_ops solo_enc_video_qops = {
 static unsigned int solo_enc_poll(struct file *file,
 				  struct poll_table_struct *wait)
 {
-	struct solo_enc_fh *fh = file->private_data;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	unsigned long req_events = poll_requested_events(wait);
 	unsigned res = v4l2_ctrl_poll(file, wait);
 
 	if (!(req_events & (POLLIN | POLLRDNORM)))
 		return res;
-	return videobuf_poll_stream(file, &fh->vidq, wait);
+	return videobuf_poll_stream(file, &solo_enc->vidq, wait);
 }
 
 static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct solo_enc_fh *fh = file->private_data;
-
-	return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
-static int solo_enc_open(struct file *file)
-{
 	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_enc_fh *fh;
-
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (fh == NULL)
-		return -ENOMEM;
-
-	v4l2_fh_init(&fh->fh, video_devdata(file));
-	fh->enc = solo_enc;
-	file->private_data = fh;
-	INIT_LIST_HEAD(&fh->vidq_active);
-	fh->fmt = V4L2_PIX_FMT_MPEG;
-	fh->type = SOLO_ENC_TYPE_STD;
 
-	videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops,
-			       &solo_enc->solo_dev->pdev->dev,
-			       &solo_enc->lock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       V4L2_FIELD_INTERLACED,
-			       sizeof(struct videobuf_buffer), fh, NULL);
-	v4l2_fh_add(&fh->fh);
-	return 0;
+	return videobuf_mmap_mapper(&solo_enc->vidq, vma);
 }
 
 static ssize_t solo_enc_read(struct file *file, char __user *data,
 			     size_t count, loff_t *ppos)
 {
-	struct solo_enc_fh *fh = file->private_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
 	/* Make sure the encoder is on */
-	if (!fh->enc_on) {
+	if (!solo_enc->enc_on) {
 		int ret;
 
 		spin_lock(&solo_enc->lock);
-		ret = solo_enc_on(fh);
+		ret = solo_enc_on(solo_enc);
 		spin_unlock(&solo_enc->lock);
 		if (ret)
 			return ret;
 
-		ret = solo_start_fh_thread(fh);
+		ret = solo_start_thread(solo_enc);
 		if (ret)
 			return ret;
 	}
 
-	return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
+	return videobuf_read_stream(&solo_enc->vidq, data, count, ppos, 0,
 				    file->f_flags & O_NONBLOCK);
 }
 
 static int solo_enc_release(struct file *file)
 {
-	struct solo_enc_fh *fh = file->private_data;
-
-	videobuf_stop(&fh->vidq);
-	videobuf_mmap_free(&fh->vidq);
-
-	solo_enc_off(fh);
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-	kfree(fh);
+	videobuf_stop(&solo_enc->vidq);
+	videobuf_mmap_free(&solo_enc->vidq);
 
-	return 0;
+	solo_enc_off(solo_enc);
+	return v4l2_fh_release(file);
 }
 
 static int solo_enc_querycap(struct file *file, void  *priv,
 			     struct v4l2_capability *cap)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 	strcpy(cap->driver, SOLO6X10_NAME);
@@ -1043,8 +990,7 @@ static int solo_enc_querycap(struct file *file, void  *priv,
 static int solo_enc_enum_input(struct file *file, void *priv,
 			       struct v4l2_input *input)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 	if (input->index)
@@ -1105,8 +1051,7 @@ static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
 static int solo_enc_try_fmt_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
@@ -1147,8 +1092,7 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv,
 static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	int ret;
@@ -1176,30 +1120,29 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 		solo_enc->mode = SOLO_ENC_MODE_CIF;
 
 	/* This does not change the encoder at all */
-	fh->fmt = pix->pixelformat;
+	solo_enc->fmt = pix->pixelformat;
 
 	if (pix->priv)
-		fh->type = SOLO_ENC_TYPE_EXT;
-	ret = solo_enc_on(fh);
+		solo_enc->type = SOLO_ENC_TYPE_EXT;
+	ret = solo_enc_on(solo_enc);
 
 	spin_unlock(&solo_enc->lock);
 
 	if (ret)
 		return ret;
 
-	return solo_start_fh_thread(fh);
+	return solo_start_thread(solo_enc);
 }
 
 static int solo_enc_get_fmt_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
 	pix->width = solo_enc->width;
 	pix->height = solo_enc->height;
-	pix->pixelformat = fh->fmt;
+	pix->pixelformat = solo_enc->fmt;
 	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
 		     V4L2_FIELD_NONE;
 	pix->sizeimage = FRAME_BUF_SIZE;
@@ -1212,47 +1155,46 @@ static int solo_enc_get_fmt_cap(struct file *file, void *priv,
 static int solo_enc_reqbufs(struct file *file, void *priv,
 			    struct v4l2_requestbuffers *req)
 {
-	struct solo_enc_fh *fh = priv;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-	return videobuf_reqbufs(&fh->vidq, req);
+	return videobuf_reqbufs(&solo_enc->vidq, req);
 }
 
 static int solo_enc_querybuf(struct file *file, void *priv,
 			     struct v4l2_buffer *buf)
 {
-	struct solo_enc_fh *fh = priv;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-	return videobuf_querybuf(&fh->vidq, buf);
+	return videobuf_querybuf(&solo_enc->vidq, buf);
 }
 
 static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
-	struct solo_enc_fh *fh = priv;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-	return videobuf_qbuf(&fh->vidq, buf);
+	return videobuf_qbuf(&solo_enc->vidq, buf);
 }
 
 static int solo_enc_dqbuf(struct file *file, void *priv,
 			  struct v4l2_buffer *buf)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	int ret;
 
 	/* Make sure the encoder is on */
-	if (!fh->enc_on) {
+	if (!solo_enc->enc_on) {
 		spin_lock(&solo_enc->lock);
-		ret = solo_enc_on(fh);
+		ret = solo_enc_on(solo_enc);
 		spin_unlock(&solo_enc->lock);
 		if (ret)
 			return ret;
 
-		ret = solo_start_fh_thread(fh);
+		ret = solo_start_thread(solo_enc);
 		if (ret)
 			return ret;
 	}
 
-	ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
+	ret = videobuf_dqbuf(&solo_enc->vidq, buf, file->f_flags & O_NONBLOCK);
 	if (ret)
 		return ret;
 
@@ -1268,9 +1210,9 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 	}
 
 	/* Check for key frame on mpeg data */
-	if (fh->fmt == V4L2_PIX_FMT_MPEG) {
+	if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) {
 		struct videobuf_dmabuf *vbuf =
-				videobuf_to_dma(fh->vidq.bufs[buf->index]);
+				videobuf_to_dma(solo_enc->vidq.bufs[buf->index]);
 
 		if (vbuf) {
 			u8 *p = sg_virt(vbuf->sglist);
@@ -1287,23 +1229,23 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 static int solo_enc_streamon(struct file *file, void *priv,
 			     enum v4l2_buf_type i)
 {
-	struct solo_enc_fh *fh = priv;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	return videobuf_streamon(&fh->vidq);
+	return videobuf_streamon(&solo_enc->vidq);
 }
 
 static int solo_enc_streamoff(struct file *file, void *priv,
 			      enum v4l2_buf_type i)
 {
-	struct solo_enc_fh *fh = priv;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	return videobuf_streamoff(&fh->vidq);
+	return videobuf_streamoff(&solo_enc->vidq);
 }
 
 static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -1314,8 +1256,8 @@ static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
 static int solo_enum_framesizes(struct file *file, void *priv,
 				struct v4l2_frmsizeenum *fsize)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG &&
 	    fsize->pixel_format != V4L2_PIX_FMT_MJPEG)
@@ -1342,8 +1284,8 @@ static int solo_enum_framesizes(struct file *file, void *priv,
 static int solo_enum_frameintervals(struct file *file, void *priv,
 				    struct v4l2_frmivalenum *fintv)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
 	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG &&
 	    fintv->pixel_format != V4L2_PIX_FMT_MJPEG)
@@ -1373,8 +1315,7 @@ static int solo_enum_frameintervals(struct file *file, void *priv,
 static int solo_g_parm(struct file *file, void *priv,
 		       struct v4l2_streamparm *sp)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_captureparm *cp = &sp->parm.capture;
 
@@ -1391,8 +1332,7 @@ static int solo_g_parm(struct file *file, void *priv,
 static int solo_s_parm(struct file *file, void *priv,
 		       struct v4l2_streamparm *sp)
 {
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_captureparm *cp = &sp->parm.capture;
 
@@ -1471,7 +1411,7 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 
 static const struct v4l2_file_operations solo_enc_fops = {
 	.owner			= THIS_MODULE,
-	.open			= solo_enc_open,
+	.open			= v4l2_fh_open,
 	.release		= solo_enc_release,
 	.read			= solo_enc_read,
 	.poll			= solo_enc_poll,
@@ -1593,6 +1533,33 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 		return ERR_PTR(ret);
 	}
 
+	solo_enc->solo_dev = solo_dev;
+	solo_enc->ch = ch;
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_enc->fmt = V4L2_PIX_FMT_MPEG;
+	solo_enc->type = SOLO_ENC_TYPE_STD;
+
+	spin_lock_init(&solo_enc->lock);
+	init_waitqueue_head(&solo_enc->thread_wait);
+	atomic_set(&solo_enc->readers, 0);
+
+	solo_enc->qp = SOLO_DEFAULT_QP;
+	solo_enc->gop = solo_dev->fps;
+	solo_enc->interval = 1;
+	solo_enc->mode = SOLO_ENC_MODE_CIF;
+	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
+
+	spin_lock(&solo_enc->lock);
+	solo_update_mode(solo_enc);
+	spin_unlock(&solo_enc->lock);
+
+	videobuf_queue_sg_init(&solo_enc->vidq, &solo_enc_video_qops,
+			       &solo_enc->solo_dev->pdev->dev,
+			       &solo_enc->lock,
+			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			       V4L2_FIELD_INTERLACED,
+			       sizeof(struct videobuf_buffer), solo_enc, NULL);
+
 	solo_enc->vfd = video_device_alloc();
 	if (!solo_enc->vfd) {
 		v4l2_ctrl_handler_free(hdl);
@@ -1600,13 +1567,11 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 		return ERR_PTR(-ENOMEM);
 	}
 
-	solo_enc->solo_dev = solo_dev;
-	solo_enc->ch = ch;
-
 	*solo_enc->vfd = solo_enc_template;
 	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
 	solo_enc->vfd->ctrl_handler = hdl;
 	set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
+	video_set_drvdata(solo_enc->vfd, solo_enc);
 	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
 				    video_nr);
 	if (ret < 0) {
@@ -1616,8 +1581,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 		return ERR_PTR(ret);
 	}
 
-	video_set_drvdata(solo_enc->vfd, solo_enc);
-
 	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
 		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
 		 solo_enc->vfd->num);
@@ -1625,20 +1588,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	if (video_nr != -1)
 		video_nr++;
 
-	spin_lock_init(&solo_enc->lock);
-	init_waitqueue_head(&solo_enc->thread_wait);
-	atomic_set(&solo_enc->readers, 0);
-
-	solo_enc->qp = SOLO_DEFAULT_QP;
-	solo_enc->gop = solo_dev->fps;
-	solo_enc->interval = 1;
-	solo_enc->mode = SOLO_ENC_MODE_CIF;
-	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
-
-	spin_lock(&solo_enc->lock);
-	solo_update_mode(solo_enc);
-	spin_unlock(&solo_enc->lock);
-
 	return solo_enc;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 10/20] solo6x10: move global fields in solo_dev_fh to solo_dev.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (7 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 09/20] solo6x10: move global fields in solo_enc_fh to solo_enc_dev Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 11/20] solo6x10: add missing size-- to enc_write_sg Hans Verkuil
                     ` (9 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

All fields in solo_dev_fh do not belong there since they refer to global
properties. After moving all these fields to solo_dev the solo_dev_fh
struct can be removed completely.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/solo6x10.h |    9 +
 drivers/staging/media/solo6x10/v4l2.c     |  254 ++++++++++++-----------------
 2 files changed, 114 insertions(+), 149 deletions(-)

diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index ef18abd..fcbe8ecf 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -252,6 +252,15 @@ struct solo_dev {
 	struct snd_pcm		*snd_pcm;
 	atomic_t		snd_users;
 	int			g723_hw_idx;
+
+	/* Buffer handling */
+	struct videobuf_queue	vidq;
+	struct task_struct      *kthread;
+	spinlock_t		slock;
+	int			old_write;
+	struct list_head	vidq_active;
+	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
+	int			desc_idx;
 };
 
 static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index d9298ac..ea9bda0 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -38,19 +38,6 @@
 
 #define MIN_VID_BUFFERS		4
 
-/* Simple file handle */
-struct solo_filehandle {
-	struct v4l2_fh		fh;
-	struct solo_dev		*solo_dev;
-	struct videobuf_queue	vidq;
-	struct task_struct      *kthread;
-	spinlock_t		slock;
-	int			old_write;
-	struct list_head	vidq_active;
-	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
-	int			desc_idx;
-};
-
 unsigned video_nr = -1;
 module_param(video_nr, uint, 0644);
 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
@@ -203,47 +190,46 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
 	return 0;
 }
 
-static void disp_reset_desc(struct solo_filehandle *fh)
+static void disp_reset_desc(struct solo_dev *solo_dev)
 {
 	/* We use desc mode, which ignores desc 0 */
-	memset(fh->desc, 0, sizeof(*fh->desc));
-	fh->desc_idx = 1;
+	memset(solo_dev->desc, 0, sizeof(*solo_dev->desc));
+	solo_dev->desc_idx = 1;
 }
 
-static int disp_flush_descs(struct solo_filehandle *fh)
+static int disp_flush_descs(struct solo_dev *solo_dev)
 {
 	int ret;
 
-	if (!fh->desc_idx)
+	if (!solo_dev->desc_idx)
 		return 0;
 
-	ret = solo_p2m_dma_desc(fh->solo_dev, SOLO_P2M_DMA_ID_DISP,
-				fh->desc, fh->desc_idx);
-	disp_reset_desc(fh);
+	ret = solo_p2m_dma_desc(solo_dev, SOLO_P2M_DMA_ID_DISP,
+				solo_dev->desc, solo_dev->desc_idx);
+	disp_reset_desc(solo_dev);
 
 	return ret;
 }
 
-static int disp_push_desc(struct solo_filehandle *fh, dma_addr_t dma_addr,
+static int disp_push_desc(struct solo_dev *solo_dev, dma_addr_t dma_addr,
 		      u32 ext_addr, int size, int repeat, int ext_size)
 {
-	if (fh->desc_idx >= SOLO_NR_P2M_DESC) {
-		int ret = disp_flush_descs(fh);
+	if (solo_dev->desc_idx >= SOLO_NR_P2M_DESC) {
+		int ret = disp_flush_descs(solo_dev);
 		if (ret)
 			return ret;
 	}
 
-	solo_p2m_push_desc(&fh->desc[fh->desc_idx], 0, dma_addr, ext_addr,
+	solo_p2m_push_desc(&solo_dev->desc[solo_dev->desc_idx], 0, dma_addr, ext_addr,
 			   size, repeat, ext_size);
-	fh->desc_idx++;
+	solo_dev->desc_idx++;
 
 	return 0;
 }
 
-static void solo_fillbuf(struct solo_filehandle *fh,
+static void solo_fillbuf(struct solo_dev *solo_dev,
 			 struct videobuf_buffer *vb)
 {
-	struct solo_dev *solo_dev = fh->solo_dev;
 	struct videobuf_dmabuf *vbuf;
 	unsigned int fdma_addr;
 	int error = 1;
@@ -274,12 +260,12 @@ static void solo_fillbuf(struct solo_filehandle *fh,
 		goto finish_buf;
 	}
 
-	disp_reset_desc(fh);
+	disp_reset_desc(solo_dev);
 	sg = vbuf->sglist;
 	sg_dma = sg_dma_address(sg);
 	sg_size_left = sg_dma_len(sg);
 
-	fdma_addr = SOLO_DISP_EXT_ADDR + (fh->old_write *
+	fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
 			(SOLO_HW_BPL * solo_vlines(solo_dev)));
 
 	for (i = 0; i < solo_vlines(solo_dev); i++) {
@@ -311,7 +297,7 @@ static void solo_fillbuf(struct solo_filehandle *fh,
 
 				this_write = min(sg_size_left, line_len);
 
-				if (disp_push_desc(fh, sg_dma, this_addr,
+				if (disp_push_desc(solo_dev, sg_dma, this_addr,
 						   this_write, 0, 0))
 					goto finish_buf;
 
@@ -329,7 +315,7 @@ static void solo_fillbuf(struct solo_filehandle *fh,
 		lines = min(sg_size_left / line_len,
 			    solo_vlines(solo_dev) - i);
 
-		if (disp_push_desc(fh, sg_dma, fdma_addr, line_len,
+		if (disp_push_desc(solo_dev, sg_dma, fdma_addr, line_len,
 				   lines - 1, SOLO_HW_BPL))
 			goto finish_buf;
 
@@ -339,7 +325,7 @@ static void solo_fillbuf(struct solo_filehandle *fh,
 		sg_size_left -= lines * line_len;
 	}
 
-	error = disp_flush_descs(fh);
+	error = disp_flush_descs(solo_dev);
 
 finish_buf:
 	if (error) {
@@ -356,44 +342,43 @@ finish_buf:
 	return;
 }
 
-static void solo_thread_try(struct solo_filehandle *fh)
+static void solo_thread_try(struct solo_dev *solo_dev)
 {
 	struct videobuf_buffer *vb;
 	unsigned int cur_write;
 
 	for (;;) {
-		spin_lock(&fh->slock);
+		spin_lock(&solo_dev->slock);
 
-		if (list_empty(&fh->vidq_active))
+		if (list_empty(&solo_dev->vidq_active))
 			break;
 
-		vb = list_first_entry(&fh->vidq_active, struct videobuf_buffer,
+		vb = list_first_entry(&solo_dev->vidq_active, struct videobuf_buffer,
 				      queue);
 
 		if (!waitqueue_active(&vb->done))
 			break;
 
-		cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(fh->solo_dev,
+		cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(solo_dev,
 						 SOLO_VI_STATUS0));
-		if (cur_write == fh->old_write)
+		if (cur_write == solo_dev->old_write)
 			break;
 
-		fh->old_write = cur_write;
+		solo_dev->old_write = cur_write;
 		list_del(&vb->queue);
 
-		spin_unlock(&fh->slock);
+		spin_unlock(&solo_dev->slock);
 
-		solo_fillbuf(fh, vb);
+		solo_fillbuf(solo_dev, vb);
 	}
 
-	assert_spin_locked(&fh->slock);
-	spin_unlock(&fh->slock);
+	assert_spin_locked(&solo_dev->slock);
+	spin_unlock(&solo_dev->slock);
 }
 
 static int solo_thread(void *data)
 {
-	struct solo_filehandle *fh = data;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = data;
 	DECLARE_WAITQUEUE(wait, current);
 
 	set_freezable();
@@ -403,7 +388,7 @@ static int solo_thread(void *data)
 		long timeout = schedule_timeout_interruptible(HZ);
 		if (timeout == -ERESTARTSYS || kthread_should_stop())
 			break;
-		solo_thread_try(fh);
+		solo_thread_try(solo_dev);
 		try_to_freeze();
 	}
 
@@ -412,26 +397,25 @@ static int solo_thread(void *data)
 	return 0;
 }
 
-static int solo_start_thread(struct solo_filehandle *fh)
+static int solo_start_thread(struct solo_dev *solo_dev)
 {
-	fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp");
+	solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp");
 
-	return PTR_RET(fh->kthread);
+	return PTR_RET(solo_dev->kthread);
 }
 
-static void solo_stop_thread(struct solo_filehandle *fh)
+static void solo_stop_thread(struct solo_dev *solo_dev)
 {
-	if (fh->kthread) {
-		kthread_stop(fh->kthread);
-		fh->kthread = NULL;
+	if (solo_dev->kthread) {
+		kthread_stop(solo_dev->kthread);
+		solo_dev->kthread = NULL;
 	}
 }
 
 static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count,
 			  unsigned int *size)
 {
-	struct solo_filehandle *fh = vq->priv_data;
-	struct solo_dev *solo_dev  = fh->solo_dev;
+	struct solo_dev *solo_dev = vq->priv_data;
 
 	*size = solo_image_size(solo_dev);
 
@@ -444,8 +428,7 @@ static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count,
 static int solo_buf_prepare(struct videobuf_queue *vq,
 			    struct videobuf_buffer *vb, enum v4l2_field field)
 {
-	struct solo_filehandle *fh  = vq->priv_data;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = vq->priv_data;
 
 	vb->size = solo_image_size(solo_dev);
 	if (vb->baddr != 0 && vb->bsize < vb->size)
@@ -475,11 +458,10 @@ static int solo_buf_prepare(struct videobuf_queue *vq,
 static void solo_buf_queue(struct videobuf_queue *vq,
 			   struct videobuf_buffer *vb)
 {
-	struct solo_filehandle *fh = vq->priv_data;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = vq->priv_data;
 
 	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &fh->vidq_active);
+	list_add_tail(&vb->queue, &solo_dev->vidq_active);
 	wake_up_interruptible(&solo_dev->disp_thread_wait);
 }
 
@@ -503,81 +485,45 @@ static struct videobuf_queue_ops solo_video_qops = {
 static unsigned int solo_v4l2_poll(struct file *file,
 				   struct poll_table_struct *wait)
 {
-	struct solo_filehandle *fh = file->private_data;
+	struct solo_dev *solo_dev = video_drvdata(file);
 	unsigned long req_events = poll_requested_events(wait);
 	unsigned res = v4l2_ctrl_poll(file, wait);
 
 	if (!(req_events & (POLLIN | POLLRDNORM)))
 		return res;
-	return res | videobuf_poll_stream(file, &fh->vidq, wait);
+	return res | videobuf_poll_stream(file, &solo_dev->vidq, wait);
 }
 
 static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct solo_filehandle *fh = file->private_data;
-
-	return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
-static int solo_v4l2_open(struct file *file)
-{
 	struct solo_dev *solo_dev = video_drvdata(file);
-	struct solo_filehandle *fh;
-	int ret;
-
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (fh == NULL)
-		return -ENOMEM;
-
-	v4l2_fh_init(&fh->fh, video_devdata(file));
-	spin_lock_init(&fh->slock);
-	INIT_LIST_HEAD(&fh->vidq_active);
-	fh->solo_dev = solo_dev;
-	file->private_data = fh;
-
-	ret = solo_start_thread(fh);
-	if (ret) {
-		kfree(fh);
-		return ret;
-	}
 
-	videobuf_queue_sg_init(&fh->vidq, &solo_video_qops,
-			       &solo_dev->pdev->dev, &fh->slock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       V4L2_FIELD_INTERLACED,
-			       sizeof(struct videobuf_buffer), fh, NULL);
-	v4l2_fh_add(&fh->fh);
-	return 0;
+	return videobuf_mmap_mapper(&solo_dev->vidq, vma);
 }
 
 static ssize_t solo_v4l2_read(struct file *file, char __user *data,
 			      size_t count, loff_t *ppos)
 {
-	struct solo_filehandle *fh = file->private_data;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
+	return videobuf_read_stream(&solo_dev->vidq, data, count, ppos, 0,
 				    file->f_flags & O_NONBLOCK);
 }
 
 static int solo_v4l2_release(struct file *file)
 {
-	struct solo_filehandle *fh = file->private_data;
-
-	videobuf_stop(&fh->vidq);
-	videobuf_mmap_free(&fh->vidq);
-	solo_stop_thread(fh);
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
-	kfree(fh);
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return 0;
+	videobuf_stop(&solo_dev->vidq);
+	videobuf_mmap_free(&solo_dev->vidq);
+	solo_stop_thread(solo_dev);
+	return v4l2_fh_release(file);
 }
 
 static int solo_querycap(struct file *file, void  *priv,
 			 struct v4l2_capability *cap)
 {
-	struct solo_filehandle  *fh  = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
 	strcpy(cap->driver, SOLO6X10_NAME);
 	strcpy(cap->card, "Softlogic 6x10");
@@ -618,8 +564,7 @@ static int solo_enum_ext_input(struct solo_dev *solo_dev,
 static int solo_enum_input(struct file *file, void *priv,
 			   struct v4l2_input *input)
 {
-	struct solo_filehandle *fh  = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
 	if (input->index >= solo_dev->nr_chans) {
 		int ret = solo_enum_ext_input(solo_dev, input);
@@ -646,16 +591,16 @@ static int solo_enum_input(struct file *file, void *priv,
 
 static int solo_set_input(struct file *file, void *priv, unsigned int index)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return solo_v4l2_set_ch(fh->solo_dev, index);
+	return solo_v4l2_set_ch(solo_dev, index);
 }
 
 static int solo_get_input(struct file *file, void *priv, unsigned int *index)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	*index = fh->solo_dev->cur_disp_ch;
+	*index = solo_dev->cur_disp_ch;
 
 	return 0;
 }
@@ -675,8 +620,7 @@ static int solo_enum_fmt_cap(struct file *file, void *priv,
 static int solo_try_fmt_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = video_drvdata(file);
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	int image_size = solo_image_size(solo_dev);
 
@@ -696,9 +640,9 @@ static int solo_try_fmt_cap(struct file *file, void *priv,
 static int solo_set_fmt_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	if (videobuf_queue_is_busy(&fh->vidq))
+	if (videobuf_queue_is_busy(&solo_dev->vidq))
 		return -EBUSY;
 
 	/* For right now, if it doesn't match our running config,
@@ -709,8 +653,7 @@ static int solo_set_fmt_cap(struct file *file, void *priv,
 static int solo_get_fmt_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
+	struct solo_dev *solo_dev = video_drvdata(file);
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
 	pix->width = solo_dev->video_hsize;
@@ -728,50 +671,55 @@ static int solo_get_fmt_cap(struct file *file, void *priv,
 static int solo_reqbufs(struct file *file, void *priv,
 			struct v4l2_requestbuffers *req)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return videobuf_reqbufs(&fh->vidq, req);
+	return videobuf_reqbufs(&solo_dev->vidq, req);
 }
 
 static int solo_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return videobuf_querybuf(&fh->vidq, buf);
+	return videobuf_querybuf(&solo_dev->vidq, buf);
 }
 
 static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return videobuf_qbuf(&fh->vidq, buf);
+	return videobuf_qbuf(&solo_dev->vidq, buf);
 }
 
 static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
-	return videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
+	return videobuf_dqbuf(&solo_dev->vidq, buf, file->f_flags & O_NONBLOCK);
 }
 
 static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
+	int ret;
 
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	return videobuf_streamon(&fh->vidq);
+	ret = solo_start_thread(solo_dev);
+	if (ret)
+		return ret;
+
+	return videobuf_streamon(&solo_dev->vidq);
 }
 
 static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-	struct solo_filehandle *fh = priv;
+	struct solo_dev *solo_dev = video_drvdata(file);
 
 	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	return videobuf_streamoff(&fh->vidq);
+	return videobuf_streamoff(&solo_dev->vidq);
 }
 
 static int solo_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -810,7 +758,7 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 
 static const struct v4l2_file_operations solo_v4l2_fops = {
 	.owner			= THIS_MODULE,
-	.open			= solo_v4l2_open,
+	.open			= v4l2_fh_open,
 	.release		= solo_v4l2_release,
 	.read			= solo_v4l2_read,
 	.poll			= solo_v4l2_poll,
@@ -886,25 +834,16 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 		return solo_dev->disp_hdl.error;
 	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
 	set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
-
-	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
-	if (ret < 0) {
-		video_device_release(solo_dev->vfd);
-		solo_dev->vfd = NULL;
-		return ret;
-	}
-
 	video_set_drvdata(solo_dev->vfd, solo_dev);
 
-	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
-		 SOLO6X10_NAME, solo_dev->vfd->num);
-
-	if (video_nr != -1)
-		video_nr++;
+	spin_lock_init(&solo_dev->slock);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
 
-	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
-		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
-		 solo_dev->nr_chans, solo_dev->nr_ext);
+	videobuf_queue_sg_init(&solo_dev->vidq, &solo_video_qops,
+			       &solo_dev->pdev->dev, &solo_dev->slock,
+			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			       V4L2_FIELD_INTERLACED,
+			       sizeof(struct videobuf_buffer), solo_dev, NULL);
 
 	/* Cycle all the channels and clear */
 	for (i = 0; i < solo_dev->nr_chans; i++) {
@@ -920,6 +859,23 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 
 	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
 
+	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
+	if (ret < 0) {
+		video_device_release(solo_dev->vfd);
+		solo_dev->vfd = NULL;
+		return ret;
+	}
+
+	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
+		 SOLO6X10_NAME, solo_dev->vfd->num);
+
+	if (video_nr != -1)
+		video_nr++;
+
+	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
+		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
+		 solo_dev->nr_chans, solo_dev->nr_ext);
+
 	return 0;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 11/20] solo6x10: add missing size-- to enc_write_sg.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (8 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 10/20] solo6x10: move global fields in solo_dev_fh to solo_dev Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 12/20] solo6x10: rename the spinlock 'lock' to 'slock' Hans Verkuil
                     ` (8 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The enc_write_sg() function wrote data to the whole scatterlist instead
of just 'size' bytes since 'size' was never decremented.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index cb78ea2..32f812f 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -232,7 +232,7 @@ static void enc_write_sg(struct scatterlist *sglist, void *buf, int size)
 		size_t len = sg_dma_len(sg);
 		int i;
 
-		for (i = 0; i < len && size; i++)
+		for (i = 0; i < len && size; i++, size--)
 			p[i] = *(src++);
 	}
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 12/20] solo6x10: rename the spinlock 'lock' to 'slock'.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (9 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 11/20] solo6x10: add missing size-- to enc_write_sg Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 13/20] solo6x10: convert encoder nodes to vb2 Hans Verkuil
                     ` (7 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The next patch will add a mutex called 'lock', so we have to rename this
spinlock first.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/solo6x10.h |    2 +-
 drivers/staging/media/solo6x10/v4l2-enc.c |   52 ++++++++++++++---------------
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index fcbe8ecf..2ab64cf 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -160,7 +160,7 @@ struct solo_enc_dev {
 	struct video_device	*vfd;
 	/* General accounting */
 	wait_queue_head_t	thread_wait;
-	spinlock_t		lock;
+	spinlock_t		slock;
 	atomic_t		readers;
 	u8			ch;
 	u8			mode, gop, qp, interlaced, interval;
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 32f812f..800719e 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -52,7 +52,7 @@ static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	u8 ch = solo_enc->ch;
 
-	spin_lock(&solo_enc->lock);
+	spin_lock(&solo_enc->slock);
 
 	if (on)
 		solo_dev->motion_mask |= (1 << ch);
@@ -73,15 +73,15 @@ static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
 	else
 		solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
 
-	spin_unlock(&solo_enc->lock);
+	spin_unlock(&solo_enc->slock);
 }
 
-/* Should be called with solo_enc->lock held */
+/* Should be called with solo_enc->slock held */
 static void solo_update_mode(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
-	assert_spin_locked(&solo_enc->lock);
+	assert_spin_locked(&solo_enc->slock);
 
 	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
 	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
@@ -101,14 +101,14 @@ static void solo_update_mode(struct solo_enc_dev *solo_enc)
 	}
 }
 
-/* Should be called with solo_enc->lock held */
+/* Should be called with solo_enc->slock held */
 static int solo_enc_on(struct solo_enc_dev *solo_enc)
 {
 	u8 ch = solo_enc->ch;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	u8 interval;
 
-	assert_spin_locked(&solo_enc->lock);
+	assert_spin_locked(&solo_enc->slock);
 
 	if (solo_enc->enc_on)
 		return 0;
@@ -175,7 +175,7 @@ static void solo_enc_off(struct solo_enc_dev *solo_enc)
 		solo_enc->kthread = NULL;
 	}
 
-	spin_lock(&solo_enc->lock);
+	spin_lock(&solo_enc->slock);
 	solo_dev->enc_bw_remain += solo_enc->bw_weight;
 	solo_enc->enc_on = 0;
 
@@ -185,7 +185,7 @@ static void solo_enc_off(struct solo_enc_dev *solo_enc)
 	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
 	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
 unlock:
-	spin_unlock(&solo_enc->lock);
+	spin_unlock(&solo_enc->slock);
 }
 
 static int solo_start_thread(struct solo_enc_dev *solo_enc)
@@ -699,7 +699,7 @@ static void solo_enc_thread_try(struct solo_enc_dev *solo_enc)
 	struct videobuf_buffer *vb;
 
 	for (;;) {
-		spin_lock(&solo_enc->lock);
+		spin_lock(&solo_enc->slock);
 
 		if (solo_enc->rd_idx == solo_dev->enc_wr_idx)
 			break;
@@ -715,13 +715,13 @@ static void solo_enc_thread_try(struct solo_enc_dev *solo_enc)
 
 		list_del(&vb->queue);
 
-		spin_unlock(&solo_enc->lock);
+		spin_unlock(&solo_enc->slock);
 
 		solo_enc_fillbuf(solo_enc, vb);
 	}
 
-	assert_spin_locked(&solo_enc->lock);
-	spin_unlock(&solo_enc->lock);
+	assert_spin_locked(&solo_enc->slock);
+	spin_unlock(&solo_enc->slock);
 }
 
 static int solo_enc_thread(void *data)
@@ -944,9 +944,9 @@ static ssize_t solo_enc_read(struct file *file, char __user *data,
 	if (!solo_enc->enc_on) {
 		int ret;
 
-		spin_lock(&solo_enc->lock);
+		spin_lock(&solo_enc->slock);
 		ret = solo_enc_on(solo_enc);
-		spin_unlock(&solo_enc->lock);
+		spin_unlock(&solo_enc->slock);
 		if (ret)
 			return ret;
 
@@ -1097,7 +1097,7 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	int ret;
 
-	spin_lock(&solo_enc->lock);
+	spin_lock(&solo_enc->slock);
 
 	ret = solo_enc_try_fmt_cap(file, priv, f);
 	if (ret)
@@ -1110,7 +1110,7 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 			ret = -EBUSY;
 	}
 	if (ret) {
-		spin_unlock(&solo_enc->lock);
+		spin_unlock(&solo_enc->slock);
 		return ret;
 	}
 
@@ -1126,7 +1126,7 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 		solo_enc->type = SOLO_ENC_TYPE_EXT;
 	ret = solo_enc_on(solo_enc);
 
-	spin_unlock(&solo_enc->lock);
+	spin_unlock(&solo_enc->slock);
 
 	if (ret)
 		return ret;
@@ -1183,9 +1183,9 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 
 	/* Make sure the encoder is on */
 	if (!solo_enc->enc_on) {
-		spin_lock(&solo_enc->lock);
+		spin_lock(&solo_enc->slock);
 		ret = solo_enc_on(solo_enc);
-		spin_unlock(&solo_enc->lock);
+		spin_unlock(&solo_enc->slock);
 		if (ret)
 			return ret;
 
@@ -1336,10 +1336,10 @@ static int solo_s_parm(struct file *file, void *priv,
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_captureparm *cp = &sp->parm.capture;
 
-	spin_lock(&solo_enc->lock);
+	spin_lock(&solo_enc->slock);
 
 	if (atomic_read(&solo_enc->readers) > 0) {
-		spin_unlock(&solo_enc->lock);
+		spin_unlock(&solo_enc->slock);
 		return -EBUSY;
 	}
 
@@ -1364,7 +1364,7 @@ static int solo_s_parm(struct file *file, void *priv,
 	solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
 	solo_update_mode(solo_enc);
 
-	spin_unlock(&solo_enc->lock);
+	spin_unlock(&solo_enc->slock);
 
 	return 0;
 }
@@ -1539,7 +1539,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	solo_enc->fmt = V4L2_PIX_FMT_MPEG;
 	solo_enc->type = SOLO_ENC_TYPE_STD;
 
-	spin_lock_init(&solo_enc->lock);
+	spin_lock_init(&solo_enc->slock);
 	init_waitqueue_head(&solo_enc->thread_wait);
 	atomic_set(&solo_enc->readers, 0);
 
@@ -1549,13 +1549,13 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	solo_enc->mode = SOLO_ENC_MODE_CIF;
 	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
 
-	spin_lock(&solo_enc->lock);
+	spin_lock(&solo_enc->slock);
 	solo_update_mode(solo_enc);
-	spin_unlock(&solo_enc->lock);
+	spin_unlock(&solo_enc->slock);
 
 	videobuf_queue_sg_init(&solo_enc->vidq, &solo_enc_video_qops,
 			       &solo_enc->solo_dev->pdev->dev,
-			       &solo_enc->lock,
+			       &solo_enc->slock,
 			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			       V4L2_FIELD_INTERLACED,
 			       sizeof(struct videobuf_buffer), solo_enc, NULL);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 13/20] solo6x10: convert encoder nodes to vb2.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (10 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 12/20] solo6x10: rename the spinlock 'lock' to 'slock' Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 14/20] solo6x10: convert the display node " Hans Verkuil
                     ` (6 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

As a consequence the ioctl op has been replaced by unlocked_ioctl.

Since we are now using the core lock the locking scheme has been
simplified as well.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/Kconfig    |    1 +
 drivers/staging/media/solo6x10/solo6x10.h |   11 +-
 drivers/staging/media/solo6x10/v4l2-enc.c |  425 +++++++++--------------------
 3 files changed, 138 insertions(+), 299 deletions(-)

diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig
index 63352de..f93b4ca 100644
--- a/drivers/staging/media/solo6x10/Kconfig
+++ b/drivers/staging/media/solo6x10/Kconfig
@@ -2,6 +2,7 @@ config SOLO6X10
 	tristate "Softlogic 6x10 MPEG codec cards"
 	depends on PCI && VIDEO_DEV && SND && I2C
 	select VIDEOBUF_DMA_SG
+	select VIDEOBUF2_DMA_SG
 	select SND_PCM
 	---help---
 	  This driver supports the Softlogic based MPEG-4 and h.264 codec
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 2ab64cf..05c9840 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -36,6 +36,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf-core.h>
+#include <media/videobuf2-core.h>
 #include "registers.h"
 
 #ifndef PCI_VENDOR_ID_SOFTLOGIC
@@ -153,6 +154,11 @@ enum solo_enc_types {
 	SOLO_ENC_TYPE_EXT,
 };
 
+struct solo_vb2_buf {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
 struct solo_enc_dev {
 	struct solo_dev		*solo_dev;
 	/* V4L2 Items */
@@ -160,8 +166,8 @@ struct solo_enc_dev {
 	struct video_device	*vfd;
 	/* General accounting */
 	wait_queue_head_t	thread_wait;
+	struct mutex		lock;
 	spinlock_t		slock;
-	atomic_t		readers;
 	u8			ch;
 	u8			mode, gop, qp, interlaced, interval;
 	u8			reset_gop;
@@ -174,9 +180,8 @@ struct solo_enc_dev {
 
 	u32			fmt;
 	u16			rd_idx;
-	u8			enc_on;
 	enum solo_enc_types	type;
-	struct videobuf_queue	vidq;
+	struct vb2_queue	vidq;
 	struct list_head	vidq_active;
 	struct task_struct	*kthread;
 	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 800719e..4fc8d84 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -24,7 +24,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-event.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
 #include "solo6x10.h"
 #include "tw28.h"
 #include "solo6x10-jpeg.h"
@@ -76,13 +76,10 @@ static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
 	spin_unlock(&solo_enc->slock);
 }
 
-/* Should be called with solo_enc->slock held */
 static void solo_update_mode(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
-	assert_spin_locked(&solo_enc->slock);
-
 	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
 	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
 
@@ -101,37 +98,24 @@ static void solo_update_mode(struct solo_enc_dev *solo_enc)
 	}
 }
 
-/* Should be called with solo_enc->slock held */
 static int solo_enc_on(struct solo_enc_dev *solo_enc)
 {
 	u8 ch = solo_enc->ch;
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	u8 interval;
 
-	assert_spin_locked(&solo_enc->slock);
-
-	if (solo_enc->enc_on)
-		return 0;
-
 	solo_update_mode(solo_enc);
 
-	/* Make sure to bw check on first reader */
-	if (!atomic_read(&solo_enc->readers)) {
-		if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
-			return -EBUSY;
-		else
-			solo_dev->enc_bw_remain -= solo_enc->bw_weight;
-	}
+	/* Make sure to do a bandwidth check */
+	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
+		return -EBUSY;
+	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
 
-	solo_enc->enc_on = 1;
 	solo_enc->rd_idx = solo_enc->solo_dev->enc_wr_idx;
 
 	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
 		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
 
-	if (atomic_inc_return(&solo_enc->readers) > 1)
-		return 0;
-
 	/* Disable all encoding for this channel */
 	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
 
@@ -167,25 +151,14 @@ static void solo_enc_off(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 
-	if (!solo_enc->enc_on)
-		return;
-
 	if (solo_enc->kthread) {
 		kthread_stop(solo_enc->kthread);
 		solo_enc->kthread = NULL;
 	}
 
-	spin_lock(&solo_enc->slock);
 	solo_dev->enc_bw_remain += solo_enc->bw_weight;
-	solo_enc->enc_on = 0;
-
-	if (atomic_dec_return(&solo_enc->readers) > 0)
-		goto unlock;
-
 	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
 	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
-unlock:
-	spin_unlock(&solo_enc->slock);
 }
 
 static int solo_start_thread(struct solo_enc_dev *solo_enc)
@@ -229,7 +202,7 @@ static void enc_write_sg(struct scatterlist *sglist, void *buf, int size)
 
 	for (sg = sglist; sg && size > 0; sg = sg_next(sg)) {
 		u8 *p = sg_virt(sg);
-		size_t len = sg_dma_len(sg);
+		size_t len = sg->length;
 		int i;
 
 		for (i = 0; i < len && size; i++, size--)
@@ -340,7 +313,7 @@ static int enc_get_jpeg_dma_sg(struct solo_dev *solo_dev,
 	((__off <= __chk) && ((__off + __range) >= __chk))
 
 static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
-			     struct videobuf_dmabuf *vbuf)
+			     struct vb2_dma_sg_desc *vbuf)
 {
 	struct scatterlist *sg;
 	void *src = jpeg_header;
@@ -348,7 +321,7 @@ static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
 	size_t to_copy = sizeof(jpeg_header);
 
 	for (sg = vbuf->sglist; sg && copied < to_copy; sg = sg_next(sg)) {
-		size_t this_copy = min(sg_dma_len(sg),
+		size_t this_copy = min(sg->length,
 				       (unsigned int)(to_copy - copied));
 		u8 *p = sg_virt(sg);
 
@@ -370,39 +343,45 @@ static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
 }
 
 static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *enc_buf,
-			  struct videobuf_buffer *vb,
-			  struct videobuf_dmabuf *vbuf)
+			  struct vb2_buffer *vb)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	int size = enc_buf->jpeg_size;
+	int ret;
+
+	vb2_set_plane_payload(vb, 0, size + sizeof(jpeg_header));
 
 	/* Copy the header first (direct write) */
 	solo_jpeg_header(solo_enc, vbuf);
 
-	vb->size = size + sizeof(jpeg_header);
-
+        dma_map_sg(&solo_enc->solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
 	/* Grab the jpeg frame */
-	return enc_get_jpeg_dma_sg(solo_dev, solo_enc->desc, vbuf->sglist,
+	ret = enc_get_jpeg_dma_sg(solo_dev, solo_enc->desc, vbuf->sglist,
 				   sizeof(jpeg_header),
 				   enc_buf->jpeg_off, size);
+        dma_unmap_sg(&solo_enc->solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
+	return ret;
 }
 
-static inline int vop_interlaced(__le32 *vh)
+static inline int vop_interlaced(const __le32 *vh)
 {
 	return (__le32_to_cpu(vh[0]) >> 30) & 1;
 }
 
-static inline u32 vop_size(__le32 *vh)
+static inline u32 vop_size(const __le32 *vh)
 {
 	return __le32_to_cpu(vh[0]) & 0xFFFFF;
 }
 
-static inline u8 vop_hsize(__le32 *vh)
+static inline u8 vop_hsize(const __le32 *vh)
 {
 	return (__le32_to_cpu(vh[1]) >> 8) & 0xFF;
 }
 
-static inline u8 vop_vsize(__le32 *vh)
+static inline u8 vop_vsize(const __le32 *vh)
 {
 	return __le32_to_cpu(vh[1]) & 0xFF;
 }
@@ -468,7 +447,7 @@ static void write_h264_end(u8 **out, unsigned *bits, int align)
 }
 
 static void mpeg4_write_vol(u8 **out, struct solo_dev *solo_dev,
-			    __le32 *vh, unsigned fps, unsigned interval)
+			    const __le32 *vh, unsigned fps, unsigned interval)
 {
 	static const u8 hdr[] = {
 		0, 0, 1, 0x00 /* video_object_start_code */,
@@ -521,7 +500,7 @@ static void mpeg4_write_vol(u8 **out, struct solo_dev *solo_dev,
 	write_mpeg4_end(out, &bits);
 }
 
-static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh)
+static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, const __le32 *vh)
 {
 	static const u8 sps[] = {
 		0, 0, 0, 1 /* start code */, 0x67, 66 /* profile_idc */,
@@ -570,10 +549,10 @@ static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh)
 }
 
 static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *enc_buf,
-			  struct videobuf_buffer *vb,
-			  struct videobuf_dmabuf *vbuf)
+			  struct vb2_buffer *vb)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 
 #define VH_WORDS 16
 #define MAX_VOL_HEADER_LENGTH 64
@@ -594,9 +573,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *en
 	if (WARN_ON_ONCE(vop_size(vh) > enc_buf->size))
 		return -EINVAL;
 
-	vb->width = vop_hsize(vh) << 4;
-	vb->height = vop_vsize(vh) << 4;
-	vb->size = vop_size(vh);
+	vb2_set_plane_payload(vb, 0, vop_size(vh));
 
 	/* If this is a key frame, add extra m4v header */
 	if (!enc_buf->vop) {
@@ -611,8 +588,10 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *en
 		skip = out - header;
 		enc_write_sg(vbuf->sglist, header, skip);
 		/* Adjust the dma buffer past this header */
-		vb->size += skip;
+		vb2_set_plane_payload(vb, 0, vop_size(vh) + skip);
 	}
+        dma_map_sg(&solo_enc->solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
 
 	/* Now get the actual mpeg payload */
 	frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
@@ -620,17 +599,20 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct solo_enc_buf *en
 
 	ret = enc_get_mpeg_dma_sg(solo_dev, solo_enc->desc, vbuf->sglist,
 				  skip, frame_off, frame_size);
+        dma_unmap_sg(&solo_enc->solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
+
 	WARN_ON_ONCE(ret);
 
 	return ret;
 }
 
 static void solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
-			    struct videobuf_buffer *vb)
+			    struct vb2_buffer *vb)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct solo_enc_buf *enc_buf = NULL;
-	struct videobuf_dmabuf *vbuf;
+	struct vb2_dma_sg_desc *vbuf;
 	int ret;
 	int error = 1;
 	u16 idx = solo_enc->rd_idx;
@@ -660,43 +642,38 @@ static void solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
 		goto buf_err;
 
 	if ((solo_enc->fmt == V4L2_PIX_FMT_MPEG &&
-	     vb->bsize < enc_buf->size) ||
+	     vb2_plane_size(vb, 0) < enc_buf->size) ||
 	    (solo_enc->fmt == V4L2_PIX_FMT_MJPEG &&
-	     vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
+	     vb2_plane_size(vb, 0) < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
 		WARN_ON_ONCE(1);
 		goto buf_err;
 	}
 
-	vbuf = videobuf_to_dma(vb);
+	vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	if (WARN_ON_ONCE(!vbuf))
 		goto buf_err;
 
 	if (solo_enc->fmt == V4L2_PIX_FMT_MPEG)
-		ret = solo_fill_mpeg(solo_enc, enc_buf, vb, vbuf);
+		ret = solo_fill_mpeg(solo_enc, enc_buf, vb);
 	else
-		ret = solo_fill_jpeg(solo_enc, enc_buf, vb, vbuf);
+		ret = solo_fill_jpeg(solo_enc, enc_buf, vb);
 
 	if (!ret)
 		error = 0;
 
 buf_err:
-	if (error) {
-		vb->state = VIDEOBUF_ERROR;
-	} else {
-		vb->field_count++;
-		vb->ts = enc_buf->ts;
-		vb->state = VIDEOBUF_DONE;
+	if (!error) {
+		vb->v4l2_buf.sequence++;
+		vb->v4l2_buf.timestamp = enc_buf->ts;
 	}
 
-	wake_up(&vb->done);
-
-	return;
+	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 }
 
 static void solo_enc_thread_try(struct solo_enc_dev *solo_enc)
 {
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct videobuf_buffer *vb;
+	struct solo_vb2_buf *vb;
 
 	for (;;) {
 		spin_lock(&solo_enc->slock);
@@ -708,16 +685,16 @@ static void solo_enc_thread_try(struct solo_enc_dev *solo_enc)
 			break;
 
 		vb = list_first_entry(&solo_enc->vidq_active,
-				      struct videobuf_buffer, queue);
+				      struct solo_vb2_buf, list);
 
-		if (!waitqueue_active(&vb->done))
-			break;
+		//if (!waitqueue_active(&vb->vb.vb2_queue->done_wq))
+		//	break;
 
-		list_del(&vb->queue);
+		list_del(&vb->list);
 
 		spin_unlock(&solo_enc->slock);
 
-		solo_enc_fillbuf(solo_enc, vb);
+		solo_enc_fillbuf(solo_enc, &vb->vb);
 	}
 
 	assert_spin_locked(&solo_enc->slock);
@@ -848,128 +825,61 @@ void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
 	return;
 }
 
-static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-			      unsigned int *size)
+static int solo_enc_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
-	*size = FRAME_BUF_SIZE;
+	sizes[0] = FRAME_BUF_SIZE;
+	*num_planes = 1;
 
-	if (*count < MIN_VID_BUFFERS)
-		*count = MIN_VID_BUFFERS;
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
 
 	return 0;
 }
 
-static int solo_enc_buf_prepare(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb,
-				enum v4l2_field field)
+static void solo_enc_buf_queue(struct vb2_buffer *vb)
 {
-	struct solo_enc_dev *solo_enc = vq->priv_data;
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
 
-	vb->size = FRAME_BUF_SIZE;
-	if (vb->baddr != 0 && vb->bsize < vb->size)
-		return -EINVAL;
-
-	/* These properties only change when queue is idle */
-	vb->width = solo_enc->width;
-	vb->height = solo_enc->height;
-	vb->field  = field;
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		int rc = videobuf_iolock(vq, vb, NULL);
-		if (rc < 0) {
-			struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-			videobuf_dma_unmap(vq->dev, dma);
-			videobuf_dma_free(dma);
-			vb->state = VIDEOBUF_NEEDS_INIT;
-			return rc;
-		}
-	}
-	vb->state = VIDEOBUF_PREPARED;
-
-	return 0;
+	spin_lock(&solo_enc->slock);
+	list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
+	spin_unlock(&solo_enc->slock);
+	wake_up_interruptible(&solo_enc->thread_wait);
 }
 
-static void solo_enc_buf_queue(struct videobuf_queue *vq,
-			       struct videobuf_buffer *vb)
+static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	struct solo_enc_dev *solo_enc = vq->priv_data;
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+	int ret;
 
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &solo_enc->vidq_active);
-	wake_up_interruptible(&solo_enc->thread_wait);
+	ret = solo_enc_on(solo_enc);
+	if (ret)
+		return ret;
+	return solo_start_thread(solo_enc);
 }
 
-static void solo_enc_buf_release(struct videobuf_queue *vq,
-				 struct videobuf_buffer *vb)
+static int solo_enc_stop_streaming(struct vb2_queue *q)
 {
-	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
 
-	videobuf_dma_unmap(vq->dev, dma);
-	videobuf_dma_free(dma);
-	vb->state = VIDEOBUF_NEEDS_INIT;
+	solo_enc_off(solo_enc);
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	return 0;
 }
 
-static struct videobuf_queue_ops solo_enc_video_qops = {
-	.buf_setup	= solo_enc_buf_setup,
-	.buf_prepare	= solo_enc_buf_prepare,
+static struct vb2_ops solo_enc_video_qops = {
+	.queue_setup	= solo_enc_queue_setup,
 	.buf_queue	= solo_enc_buf_queue,
-	.buf_release	= solo_enc_buf_release,
+	.start_streaming = solo_enc_start_streaming,
+	.stop_streaming = solo_enc_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
 };
 
-static unsigned int solo_enc_poll(struct file *file,
-				  struct poll_table_struct *wait)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	unsigned long req_events = poll_requested_events(wait);
-	unsigned res = v4l2_ctrl_poll(file, wait);
-
-	if (!(req_events & (POLLIN | POLLRDNORM)))
-		return res;
-	return videobuf_poll_stream(file, &solo_enc->vidq, wait);
-}
-
-static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	return videobuf_mmap_mapper(&solo_enc->vidq, vma);
-}
-
-static ssize_t solo_enc_read(struct file *file, char __user *data,
-			     size_t count, loff_t *ppos)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	/* Make sure the encoder is on */
-	if (!solo_enc->enc_on) {
-		int ret;
-
-		spin_lock(&solo_enc->slock);
-		ret = solo_enc_on(solo_enc);
-		spin_unlock(&solo_enc->slock);
-		if (ret)
-			return ret;
-
-		ret = solo_start_thread(solo_enc);
-		if (ret)
-			return ret;
-	}
-
-	return videobuf_read_stream(&solo_enc->vidq, data, count, ppos, 0,
-				    file->f_flags & O_NONBLOCK);
-}
-
-static int solo_enc_release(struct file *file)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	videobuf_stop(&solo_enc->vidq);
-	videobuf_mmap_free(&solo_enc->vidq);
-
-	solo_enc_off(solo_enc);
-	return v4l2_fh_release(file);
-}
-
 static int solo_enc_querycap(struct file *file, void  *priv,
 			     struct v4l2_capability *cap)
 {
@@ -1097,23 +1007,13 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	int ret;
 
-	spin_lock(&solo_enc->slock);
+	if (vb2_is_busy(&solo_enc->vidq))
+		return -EBUSY;
 
 	ret = solo_enc_try_fmt_cap(file, priv, f);
 	if (ret)
 		return ret;
 
-	/* We cannot change width/height in mid read */
-	if (!ret && atomic_read(&solo_enc->readers) > 0) {
-		if (pix->width != solo_enc->width ||
-		    pix->height != solo_enc->height)
-			ret = -EBUSY;
-	}
-	if (ret) {
-		spin_unlock(&solo_enc->slock);
-		return ret;
-	}
-
 	if (pix->width == solo_dev->video_hsize)
 		solo_enc->mode = SOLO_ENC_MODE_D1;
 	else
@@ -1122,16 +1022,9 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
 	/* This does not change the encoder at all */
 	solo_enc->fmt = pix->pixelformat;
 
-	if (pix->priv)
-		solo_enc->type = SOLO_ENC_TYPE_EXT;
-	ret = solo_enc_on(solo_enc);
-
-	spin_unlock(&solo_enc->slock);
-
-	if (ret)
-		return ret;
-
-	return solo_start_thread(solo_enc);
+//	if (pix->priv) /* FIXME */
+//		solo_enc->type = SOLO_ENC_TYPE_EXT;
+	return 0;
 }
 
 static int solo_enc_get_fmt_cap(struct file *file, void *priv,
@@ -1152,49 +1045,13 @@ static int solo_enc_get_fmt_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_enc_reqbufs(struct file *file, void *priv,
-			    struct v4l2_requestbuffers *req)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	return videobuf_reqbufs(&solo_enc->vidq, req);
-}
-
-static int solo_enc_querybuf(struct file *file, void *priv,
-			     struct v4l2_buffer *buf)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	return videobuf_querybuf(&solo_enc->vidq, buf);
-}
-
-static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	return videobuf_qbuf(&solo_enc->vidq, buf);
-}
-
 static int solo_enc_dqbuf(struct file *file, void *priv,
 			  struct v4l2_buffer *buf)
 {
 	struct solo_enc_dev *solo_enc = video_drvdata(file);
 	int ret;
 
-	/* Make sure the encoder is on */
-	if (!solo_enc->enc_on) {
-		spin_lock(&solo_enc->slock);
-		ret = solo_enc_on(solo_enc);
-		spin_unlock(&solo_enc->slock);
-		if (ret)
-			return ret;
-
-		ret = solo_start_thread(solo_enc);
-		if (ret)
-			return ret;
-	}
-
-	ret = videobuf_dqbuf(&solo_enc->vidq, buf, file->f_flags & O_NONBLOCK);
+	ret = vb2_ioctl_dqbuf(file, priv, buf);
 	if (ret)
 		return ret;
 
@@ -1211,8 +1068,8 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 
 	/* Check for key frame on mpeg data */
 	if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) {
-		struct videobuf_dmabuf *vbuf =
-				videobuf_to_dma(solo_enc->vidq.bufs[buf->index]);
+		struct vb2_dma_sg_desc *vbuf =
+			vb2_dma_sg_plane_desc(solo_enc->vidq.bufs[buf->index], 0);
 
 		if (vbuf) {
 			u8 *p = sg_virt(vbuf->sglist);
@@ -1226,28 +1083,6 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_enc_streamon(struct file *file, void *priv,
-			     enum v4l2_buf_type i)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamon(&solo_enc->vidq);
-}
-
-static int solo_enc_streamoff(struct file *file, void *priv,
-			      enum v4l2_buf_type i)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamoff(&solo_enc->vidq);
-}
-
 static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
 {
 	return 0;
@@ -1336,12 +1171,8 @@ static int solo_s_parm(struct file *file, void *priv,
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct v4l2_captureparm *cp = &sp->parm.capture;
 
-	spin_lock(&solo_enc->slock);
-
-	if (atomic_read(&solo_enc->readers) > 0) {
-		spin_unlock(&solo_enc->slock);
+	if (vb2_is_streaming(&solo_enc->vidq))
 		return -EBUSY;
-	}
 
 	if ((cp->timeperframe.numerator == 0) ||
 	    (cp->timeperframe.denominator == 0)) {
@@ -1364,8 +1195,6 @@ static int solo_s_parm(struct file *file, void *priv,
 	solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
 	solo_update_mode(solo_enc);
 
-	spin_unlock(&solo_enc->slock);
-
 	return 0;
 }
 
@@ -1412,11 +1241,11 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 static const struct v4l2_file_operations solo_enc_fops = {
 	.owner			= THIS_MODULE,
 	.open			= v4l2_fh_open,
-	.release		= solo_enc_release,
-	.read			= solo_enc_read,
-	.poll			= solo_enc_poll,
-	.mmap			= solo_enc_mmap,
-	.ioctl			= video_ioctl2,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
@@ -1432,12 +1261,12 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
 	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
 	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
 	/* Streaming I/O */
-	.vidioc_reqbufs			= solo_enc_reqbufs,
-	.vidioc_querybuf		= solo_enc_querybuf,
-	.vidioc_qbuf			= solo_enc_qbuf,
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
 	.vidioc_dqbuf			= solo_enc_dqbuf,
-	.vidioc_streamon		= solo_enc_streamon,
-	.vidioc_streamoff		= solo_enc_streamoff,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
 	/* Frame size and interval */
 	.vidioc_enum_framesizes		= solo_enum_framesizes,
 	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
@@ -1528,9 +1357,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
 	if (hdl->error) {
 		ret = hdl->error;
-		v4l2_ctrl_handler_free(hdl);
-		kfree(solo_enc);
-		return ERR_PTR(ret);
+		goto fail;
 	}
 
 	solo_enc->solo_dev = solo_dev;
@@ -1540,8 +1367,8 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	solo_enc->type = SOLO_ENC_TYPE_STD;
 
 	spin_lock_init(&solo_enc->slock);
+	mutex_init(&solo_enc->lock);
 	init_waitqueue_head(&solo_enc->thread_wait);
-	atomic_set(&solo_enc->readers, 0);
 
 	solo_enc->qp = SOLO_DEFAULT_QP;
 	solo_enc->gop = solo_dev->fps;
@@ -1549,37 +1376,37 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 	solo_enc->mode = SOLO_ENC_MODE_CIF;
 	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
 
-	spin_lock(&solo_enc->slock);
 	solo_update_mode(solo_enc);
-	spin_unlock(&solo_enc->slock);
 
-	videobuf_queue_sg_init(&solo_enc->vidq, &solo_enc_video_qops,
-			       &solo_enc->solo_dev->pdev->dev,
-			       &solo_enc->slock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       V4L2_FIELD_INTERLACED,
-			       sizeof(struct videobuf_buffer), solo_enc, NULL);
+	solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_enc->vidq.ops = &solo_enc_video_qops;
+	solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
+	solo_enc->vidq.drv_priv = solo_enc;
+	solo_enc->vidq.gfp_flags = __GFP_DMA32;
+	solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_enc->vidq.lock = &solo_enc->lock;
+	ret = vb2_queue_init(&solo_enc->vidq);
+	if (ret)
+		goto fail;
 
 	solo_enc->vfd = video_device_alloc();
 	if (!solo_enc->vfd) {
-		v4l2_ctrl_handler_free(hdl);
-		kfree(solo_enc);
-		return ERR_PTR(-ENOMEM);
+		ret = -ENOMEM;
+		goto fail;
 	}
 
 	*solo_enc->vfd = solo_enc_template;
 	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
 	solo_enc->vfd->ctrl_handler = hdl;
+	solo_enc->vfd->queue = &solo_enc->vidq;
+	solo_enc->vfd->lock = &solo_enc->lock;
 	set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
 	video_set_drvdata(solo_enc->vfd, solo_enc);
 	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
 				    video_nr);
-	if (ret < 0) {
-		video_device_release(solo_enc->vfd);
-		v4l2_ctrl_handler_free(hdl);
-		kfree(solo_enc);
-		return ERR_PTR(ret);
-	}
+	if (ret < 0)
+		goto fail;
 
 	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
 		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
@@ -1589,6 +1416,12 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
 		video_nr++;
 
 	return solo_enc;
+
+fail:
+	video_device_release(solo_enc->vfd);
+	v4l2_ctrl_handler_free(hdl);
+	kfree(solo_enc);
+	return ERR_PTR(ret);
 }
 
 static void solo_enc_free(struct solo_enc_dev *solo_enc, int ch)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 14/20] solo6x10: convert the display node to vb2.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (11 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 13/20] solo6x10: convert encoder nodes to vb2 Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 15/20] solo6x10: use monotonic timestamps Hans Verkuil
                     ` (5 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

As a consequence the ioctl op has been replaced by unlocked_ioctl.

Since we are now using the core lock the locking scheme has been
simplified as well.

The main reason for converting this driver to vb2 was that the locking
scheme in v4l2.c was hopeless. It was easier to just convert the driver
then to try and salvage a threading and videobuf nightmare.

The videobuf2 framework is far, far superior compared to the old videobuf.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/Kconfig    |    1 -
 drivers/staging/media/solo6x10/solo6x10.h |    4 +-
 drivers/staging/media/solo6x10/v4l2.c     |  281 ++++++++++-------------------
 3 files changed, 95 insertions(+), 191 deletions(-)

diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig
index f93b4ca..de50fc8 100644
--- a/drivers/staging/media/solo6x10/Kconfig
+++ b/drivers/staging/media/solo6x10/Kconfig
@@ -1,7 +1,6 @@
 config SOLO6X10
 	tristate "Softlogic 6x10 MPEG codec cards"
 	depends on PCI && VIDEO_DEV && SND && I2C
-	select VIDEOBUF_DMA_SG
 	select VIDEOBUF2_DMA_SG
 	select SND_PCM
 	---help---
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 05c9840..facd395 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -35,7 +35,6 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
-#include <media/videobuf-core.h>
 #include <media/videobuf2-core.h>
 #include "registers.h"
 
@@ -259,8 +258,9 @@ struct solo_dev {
 	int			g723_hw_idx;
 
 	/* Buffer handling */
-	struct videobuf_queue	vidq;
+	struct vb2_queue	vidq;
 	struct task_struct      *kthread;
+	struct mutex		lock;
 	spinlock_t		slock;
 	int			old_write;
 	struct list_head	vidq_active;
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index ea9bda0..8900015 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -24,7 +24,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-event.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
 #include "solo6x10.h"
 #include "tw28.h"
 
@@ -228,9 +228,9 @@ static int disp_push_desc(struct solo_dev *solo_dev, dma_addr_t dma_addr,
 }
 
 static void solo_fillbuf(struct solo_dev *solo_dev,
-			 struct videobuf_buffer *vb)
+			 struct vb2_buffer *vb)
 {
-	struct videobuf_dmabuf *vbuf;
+	struct vb2_dma_sg_desc *vbuf;
 	unsigned int fdma_addr;
 	int error = 1;
 	int i;
@@ -238,7 +238,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
 	dma_addr_t sg_dma;
 	int sg_size_left;
 
-	vbuf = videobuf_to_dma(vb);
+	vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	if (!vbuf)
 		goto finish_buf;
 
@@ -246,9 +246,9 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
 		int i;
 
 		/* Just blit to the entire sg list, ignoring size */
-		for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) {
+		for (sg = vbuf->sglist; sg; sg = sg_next(sg)) {
 			void *p = sg_virt(sg);
-			size_t len = sg_dma_len(sg);
+			size_t len = sg->length;
 
 			for (i = 0; i < len; i += 2) {
 				((u8 *)p)[i] = 0x80;
@@ -261,6 +261,8 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
 	}
 
 	disp_reset_desc(solo_dev);
+        dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
 	sg = vbuf->sglist;
 	sg_dma = sg_dma_address(sg);
 	sg_size_left = sg_dma_len(sg);
@@ -326,25 +328,25 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
 	}
 
 	error = disp_flush_descs(solo_dev);
+        dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+                        DMA_FROM_DEVICE);
 
 finish_buf:
-	if (error) {
-		vb->state = VIDEOBUF_ERROR;
-	} else {
-		vb->size = solo_vlines(solo_dev) * solo_bytesperline(solo_dev);
-		vb->state = VIDEOBUF_DONE;
-		vb->field_count++;
-		do_gettimeofday(&vb->ts);
+	if (!error) {
+		vb2_set_plane_payload(vb, 0,
+			solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
+		vb->v4l2_buf.sequence++;
+		do_gettimeofday(&vb->v4l2_buf.timestamp);
 	}
 
-	wake_up(&vb->done);
+	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 
 	return;
 }
 
 static void solo_thread_try(struct solo_dev *solo_dev)
 {
-	struct videobuf_buffer *vb;
+	struct solo_vb2_buf *vb;
 	unsigned int cur_write;
 
 	for (;;) {
@@ -353,11 +355,11 @@ static void solo_thread_try(struct solo_dev *solo_dev)
 		if (list_empty(&solo_dev->vidq_active))
 			break;
 
-		vb = list_first_entry(&solo_dev->vidq_active, struct videobuf_buffer,
-				      queue);
+		vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf,
+				      list);
 
-		if (!waitqueue_active(&vb->done))
-			break;
+		//if (!waitqueue_active(&vb->done))
+		//	break;
 
 		cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(solo_dev,
 						 SOLO_VI_STATUS0));
@@ -365,11 +367,11 @@ static void solo_thread_try(struct solo_dev *solo_dev)
 			break;
 
 		solo_dev->old_write = cur_write;
-		list_del(&vb->queue);
+		list_del(&vb->list);
 
 		spin_unlock(&solo_dev->slock);
 
-		solo_fillbuf(solo_dev, vb);
+		solo_fillbuf(solo_dev, &vb->vb);
 	}
 
 	assert_spin_locked(&solo_dev->slock);
@@ -412,114 +414,59 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
 	}
 }
 
-static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-			  unsigned int *size)
+static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct solo_dev *solo_dev = vq->priv_data;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
 
-	*size = solo_image_size(solo_dev);
+	sizes[0] = solo_image_size(solo_dev);
+	*num_planes = 1;
 
-	if (*count < MIN_VID_BUFFERS)
-		*count = MIN_VID_BUFFERS;
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
 
 	return 0;
 }
 
-static int solo_buf_prepare(struct videobuf_queue *vq,
-			    struct videobuf_buffer *vb, enum v4l2_field field)
+static int solo_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	struct solo_dev *solo_dev = vq->priv_data;
-
-	vb->size = solo_image_size(solo_dev);
-	if (vb->baddr != 0 && vb->bsize < vb->size)
-		return -EINVAL;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
 
-	/* XXX: These properties only change when queue is idle */
-	vb->width  = solo_dev->video_hsize;
-	vb->height = solo_vlines(solo_dev);
-	vb->bytesperline = solo_bytesperline(solo_dev);
-	vb->field  = field;
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		int rc = videobuf_iolock(vq, vb, NULL);
-		if (rc < 0) {
-			struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-			videobuf_dma_unmap(vq->dev, dma);
-			videobuf_dma_free(dma);
-			vb->state = VIDEOBUF_NEEDS_INIT;
-			return rc;
-		}
-	}
-	vb->state = VIDEOBUF_PREPARED;
-
-	return 0;
+	return solo_start_thread(solo_dev);
 }
 
-static void solo_buf_queue(struct videobuf_queue *vq,
-			   struct videobuf_buffer *vb)
+static int solo_stop_streaming(struct vb2_queue *q)
 {
-	struct solo_dev *solo_dev = vq->priv_data;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
 
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &solo_dev->vidq_active);
-	wake_up_interruptible(&solo_dev->disp_thread_wait);
+	solo_stop_thread(solo_dev);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
+	return 0;
 }
 
-static void solo_buf_release(struct videobuf_queue *vq,
-			     struct videobuf_buffer *vb)
+static void solo_buf_queue(struct vb2_buffer *vb)
 {
-	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
 
-	videobuf_dma_unmap(vq->dev, dma);
-	videobuf_dma_free(dma);
-	vb->state = VIDEOBUF_NEEDS_INIT;
+	spin_lock(&solo_dev->slock);
+	list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
+	spin_unlock(&solo_dev->slock);
+	wake_up_interruptible(&solo_dev->disp_thread_wait);
 }
 
-static struct videobuf_queue_ops solo_video_qops = {
-	.buf_setup	= solo_buf_setup,
-	.buf_prepare	= solo_buf_prepare,
+static struct vb2_ops solo_video_qops = {
+	.queue_setup	= solo_queue_setup,
 	.buf_queue	= solo_buf_queue,
-	.buf_release	= solo_buf_release,
+	.start_streaming = solo_start_streaming,
+	.stop_streaming = solo_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
 };
 
-static unsigned int solo_v4l2_poll(struct file *file,
-				   struct poll_table_struct *wait)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	unsigned long req_events = poll_requested_events(wait);
-	unsigned res = v4l2_ctrl_poll(file, wait);
-
-	if (!(req_events & (POLLIN | POLLRDNORM)))
-		return res;
-	return res | videobuf_poll_stream(file, &solo_dev->vidq, wait);
-}
-
-static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_mmap_mapper(&solo_dev->vidq, vma);
-}
-
-static ssize_t solo_v4l2_read(struct file *file, char __user *data,
-			      size_t count, loff_t *ppos)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_read_stream(&solo_dev->vidq, data, count, ppos, 0,
-				    file->f_flags & O_NONBLOCK);
-}
-
-static int solo_v4l2_release(struct file *file)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	videobuf_stop(&solo_dev->vidq);
-	videobuf_mmap_free(&solo_dev->vidq);
-	solo_stop_thread(solo_dev);
-	return v4l2_fh_release(file);
-}
-
 static int solo_querycap(struct file *file, void  *priv,
 			 struct v4l2_capability *cap)
 {
@@ -642,7 +589,7 @@ static int solo_set_fmt_cap(struct file *file, void *priv,
 {
 	struct solo_dev *solo_dev = video_drvdata(file);
 
-	if (videobuf_queue_is_busy(&solo_dev->vidq))
+	if (vb2_is_busy(&solo_dev->vidq))
 		return -EBUSY;
 
 	/* For right now, if it doesn't match our running config,
@@ -668,60 +615,6 @@ static int solo_get_fmt_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_reqbufs(struct file *file, void *priv,
-			struct v4l2_requestbuffers *req)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_reqbufs(&solo_dev->vidq, req);
-}
-
-static int solo_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_querybuf(&solo_dev->vidq, buf);
-}
-
-static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_qbuf(&solo_dev->vidq, buf);
-}
-
-static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	return videobuf_dqbuf(&solo_dev->vidq, buf, file->f_flags & O_NONBLOCK);
-}
-
-static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	int ret;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	ret = solo_start_thread(solo_dev);
-	if (ret)
-		return ret;
-
-	return videobuf_streamon(&solo_dev->vidq);
-}
-
-static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamoff(&solo_dev->vidq);
-}
-
 static int solo_s_std(struct file *file, void *priv, v4l2_std_id *i)
 {
 	return 0;
@@ -759,11 +652,11 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 static const struct v4l2_file_operations solo_v4l2_fops = {
 	.owner			= THIS_MODULE,
 	.open			= v4l2_fh_open,
-	.release		= solo_v4l2_release,
-	.read			= solo_v4l2_read,
-	.poll			= solo_v4l2_poll,
-	.mmap			= solo_v4l2_mmap,
-	.ioctl			= video_ioctl2,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
@@ -779,12 +672,12 @@ static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
 	.vidioc_s_fmt_vid_cap		= solo_set_fmt_cap,
 	.vidioc_g_fmt_vid_cap		= solo_get_fmt_cap,
 	/* Streaming I/O */
-	.vidioc_reqbufs			= solo_reqbufs,
-	.vidioc_querybuf		= solo_querybuf,
-	.vidioc_qbuf			= solo_qbuf,
-	.vidioc_dqbuf			= solo_dqbuf,
-	.vidioc_streamon		= solo_streamon,
-	.vidioc_streamoff		= solo_streamoff,
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
 	/* Logging and events */
 	.vidioc_log_status		= v4l2_ctrl_log_status,
 	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
@@ -821,6 +714,9 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 	int i;
 
 	init_waitqueue_head(&solo_dev->disp_thread_wait);
+	spin_lock_init(&solo_dev->slock);
+	mutex_init(&solo_dev->lock);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
 
 	solo_dev->vfd = video_device_alloc();
 	if (!solo_dev->vfd)
@@ -828,22 +724,29 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 
 	*solo_dev->vfd = solo_v4l2_template;
 	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_dev->vfd->queue = &solo_dev->vidq;
+	solo_dev->vfd->lock = &solo_dev->lock;
 	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
 	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
-	if (solo_dev->disp_hdl.error)
-		return solo_dev->disp_hdl.error;
+	if (solo_dev->disp_hdl.error) {
+		ret = solo_dev->disp_hdl.error;
+		goto fail;
+	}
 	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
 	set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
 	video_set_drvdata(solo_dev->vfd, solo_dev);
 
-	spin_lock_init(&solo_dev->slock);
-	INIT_LIST_HEAD(&solo_dev->vidq_active);
-
-	videobuf_queue_sg_init(&solo_dev->vidq, &solo_video_qops,
-			       &solo_dev->pdev->dev, &solo_dev->slock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       V4L2_FIELD_INTERLACED,
-			       sizeof(struct videobuf_buffer), solo_dev, NULL);
+	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_dev->vidq.ops = &solo_video_qops;
+	solo_dev->vidq.mem_ops = &vb2_dma_sg_memops;
+	solo_dev->vidq.drv_priv = solo_dev;
+	solo_dev->vidq.gfp_flags = __GFP_DMA32;
+	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_dev->vidq.lock = &solo_dev->lock;
+	ret = vb2_queue_init(&solo_dev->vidq);
+	if (ret < 0)
+		goto fail;
 
 	/* Cycle all the channels and clear */
 	for (i = 0; i < solo_dev->nr_chans; i++) {
@@ -860,11 +763,8 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
 
 	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
-	if (ret < 0) {
-		video_device_release(solo_dev->vfd);
-		solo_dev->vfd = NULL;
-		return ret;
-	}
+	if (ret < 0)
+		goto fail;
 
 	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
 		 SOLO6X10_NAME, solo_dev->vfd->num);
@@ -877,6 +777,11 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
 		 solo_dev->nr_chans, solo_dev->nr_ext);
 
 	return 0;
+
+fail:
+	video_device_release(solo_dev->vfd);
+	solo_dev->vfd = NULL;
+	return ret;
 }
 
 void solo_v4l2_exit(struct solo_dev *solo_dev)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 15/20] solo6x10: use monotonic timestamps.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (12 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 14/20] solo6x10: convert the display node " Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 16/20] solo6x10: drop video_type and add proper s_std support Hans Verkuil
                     ` (4 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/v4l2-enc.c |    2 +-
 drivers/staging/media/solo6x10/v4l2.c     |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 4fc8d84..fd9cf4f 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -814,7 +814,7 @@ void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
 		enc_buf->jpeg_size = jpeg_size;
 		enc_buf->type = enc_type;
 
-		do_gettimeofday(&enc_buf->ts);
+		v4l2_get_timestamp(&enc_buf->ts);
 
 		solo_dev->enc_wr_idx = (solo_dev->enc_wr_idx + 1) %
 					SOLO_NR_RING_BUFS;
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index 8900015..8a4194b 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -336,7 +336,7 @@ finish_buf:
 		vb2_set_plane_payload(vb, 0,
 			solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
 		vb->v4l2_buf.sequence++;
-		do_gettimeofday(&vb->v4l2_buf.timestamp);
+		v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
 	}
 
 	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 16/20] solo6x10: drop video_type and add proper s_std support.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (13 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 15/20] solo6x10: use monotonic timestamps Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 17/20] solo6x10: update buffer flags to fix clash with existing flags Hans Verkuil
                     ` (3 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/disp.c     |    8 +----
 drivers/staging/media/solo6x10/solo6x10.h |    3 ++
 drivers/staging/media/solo6x10/v4l2-enc.c |   33 +++++++++++++--------
 drivers/staging/media/solo6x10/v4l2.c     |   45 ++++++++++++++++++++++-------
 4 files changed, 60 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/solo6x10/disp.c b/drivers/staging/media/solo6x10/disp.c
index 884c0eb..b91a6e2 100644
--- a/drivers/staging/media/solo6x10/disp.c
+++ b/drivers/staging/media/solo6x10/disp.c
@@ -33,10 +33,6 @@
 #define SOLO_MOT_FLAG_SIZE		512
 #define SOLO_MOT_FLAG_AREA		(SOLO_MOT_FLAG_SIZE * 32)
 
-static unsigned video_type;
-module_param(video_type, uint, 0644);
-MODULE_PARM_DESC(video_type, "video_type (0 = NTSC/Default, 1 = PAL)");
-
 static void solo_vin_config(struct solo_dev *solo_dev)
 {
 	solo_dev->vin_hstart = 8;
@@ -214,12 +210,10 @@ int solo_disp_init(struct solo_dev *solo_dev)
 	int i;
 
 	solo_dev->video_hsize = 704;
-	if (video_type == 0) {
-		solo_dev->video_type = SOLO_VO_FMT_TYPE_NTSC;
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
 		solo_dev->video_vsize = 240;
 		solo_dev->fps = 30;
 	} else {
-		solo_dev->video_type = SOLO_VO_FMT_TYPE_PAL;
 		solo_dev->video_vsize = 288;
 		solo_dev->fps = 25;
 	}
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index facd395..d24b3cd 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -357,6 +357,9 @@ void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr,
 int solo_p2m_dma_desc(struct solo_dev *solo_dev, u8 id,
 		      struct p2m_desc *desc, int desc_count);
 
+/* Global s_std ioctl */
+int solo_set_video_type(struct solo_dev *solo_dev, bool type);
+
 /* Set the threshold for motion detection */
 void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
 #define SOLO_DEF_MOT_THRESH		0x0300
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index fd9cf4f..5445e6f 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -909,11 +909,7 @@ static int solo_enc_enum_input(struct file *file, void *priv,
 	snprintf(input->name, sizeof(input->name), "Encoder %d",
 		 solo_enc->ch + 1);
 	input->type = V4L2_INPUT_TYPE_CAMERA;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		input->std = V4L2_STD_NTSC_M;
-	else
-		input->std = V4L2_STD_PAL_B;
+	input->std = solo_enc->vfd->tvnorms;
 
 	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
 		input->status = V4L2_IN_ST_NO_SIGNAL;
@@ -1083,11 +1079,25 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
+static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
 {
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
 	return 0;
 }
 
+static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+
+	return solo_set_video_type(solo_enc->solo_dev, *std & V4L2_STD_PAL);
+}
+
 static int solo_enum_framesizes(struct file *file, void *priv,
 				struct v4l2_frmsizeenum *fsize)
 {
@@ -1135,14 +1145,14 @@ static int solo_enum_frameintervals(struct file *file, void *priv,
 
 	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
 
+	fintv->stepwise.min.numerator = 1;
 	fintv->stepwise.min.denominator = solo_dev->fps;
-	fintv->stepwise.min.numerator = 15;
 
+	fintv->stepwise.max.numerator = 15;
 	fintv->stepwise.max.denominator = solo_dev->fps;
-	fintv->stepwise.max.numerator = 1;
 
 	fintv->stepwise.step.numerator = 1;
-	fintv->stepwise.step.denominator = 1;
+	fintv->stepwise.step.denominator = solo_dev->fps;
 
 	return 0;
 }
@@ -1251,6 +1261,7 @@ static const struct v4l2_file_operations solo_enc_fops = {
 static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
 	.vidioc_querycap		= solo_enc_querycap,
 	.vidioc_s_std			= solo_enc_s_std,
+	.vidioc_g_std			= solo_enc_g_std,
 	/* Input callbacks */
 	.vidioc_enum_input		= solo_enc_enum_input,
 	.vidioc_s_input			= solo_enc_set_input,
@@ -1285,9 +1296,7 @@ static struct video_device solo_enc_template = {
 	.ioctl_ops		= &solo_enc_ioctl_ops,
 	.minor			= -1,
 	.release		= video_device_release,
-
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL_B,
-	.current_norm		= V4L2_STD_NTSC_M,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
 };
 
 static const struct v4l2_ctrl_ops solo_ctrl_ops = {
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index 8a4194b..a965b63 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -527,12 +527,7 @@ static int solo_enum_input(struct file *file, void *priv,
 	}
 
 	input->type = V4L2_INPUT_TYPE_CAMERA;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		input->std = V4L2_STD_NTSC_M;
-	else
-		input->std = V4L2_STD_PAL_B;
-
+	input->std = solo_dev->vfd->tvnorms;
 	return 0;
 }
 
@@ -615,11 +610,42 @@ static int solo_get_fmt_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int solo_s_std(struct file *file, void *priv, v4l2_std_id *i)
+static int solo_g_std(struct file *file, void *priv, v4l2_std_id *i)
 {
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
 	return 0;
 }
 
+int solo_set_video_type(struct solo_dev *solo_dev, bool type)
+{
+	int i;
+
+	/* Make sure all video nodes are idle */
+	if (vb2_is_busy(&solo_dev->vidq))
+		return -EBUSY;
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		if (vb2_is_busy(&solo_dev->v4l2_enc[i]->vidq))
+			return -EBUSY;
+	solo_dev->video_type = type;
+	/* Reconfigure for the new standard */
+	solo_disp_init(solo_dev);
+	solo_enc_init(solo_dev);
+	solo_tw28_init(solo_dev);
+	return solo_v4l2_set_ch(solo_dev, solo_dev->cur_disp_ch);
+}
+
+static int solo_s_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	return solo_set_video_type(solo_dev, *std & V4L2_STD_PAL);
+}
+
 static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct solo_dev *solo_dev =
@@ -662,6 +688,7 @@ static const struct v4l2_file_operations solo_v4l2_fops = {
 static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
 	.vidioc_querycap		= solo_querycap,
 	.vidioc_s_std			= solo_s_std,
+	.vidioc_g_std			= solo_g_std,
 	/* Input callbacks */
 	.vidioc_enum_input		= solo_enum_input,
 	.vidioc_s_input			= solo_set_input,
@@ -690,9 +717,7 @@ static struct video_device solo_v4l2_template = {
 	.ioctl_ops		= &solo_v4l2_ioctl_ops,
 	.minor			= -1,
 	.release		= video_device_release,
-
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL_B,
-	.current_norm		= V4L2_STD_NTSC_M,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
 };
 
 static const struct v4l2_ctrl_ops solo_ctrl_ops = {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 17/20] solo6x10: update buffer flags to fix clash with existing flags.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (14 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 16/20] solo6x10: drop video_type and add proper s_std support Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 18/20] solo6x10: use correct __GFP_DMA32 flags Hans Verkuil
                     ` (2 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/solo6x10.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index d24b3cd..e404ec7 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -112,8 +112,8 @@
 #define SOLO_CLOCK_MHZ			108
 
 #ifndef V4L2_BUF_FLAG_MOTION_ON
-#define V4L2_BUF_FLAG_MOTION_ON		0x0400
-#define V4L2_BUF_FLAG_MOTION_DETECTED	0x0800
+#define V4L2_BUF_FLAG_MOTION_ON		0x10000
+#define V4L2_BUF_FLAG_MOTION_DETECTED	0x20000
 #endif
 
 #ifndef V4L2_CID_MOTION_ENABLE
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 18/20] solo6x10: use correct __GFP_DMA32 flags.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (15 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 17/20] solo6x10: update buffer flags to fix clash with existing flags Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 19/20] solo6x10: small big-endian fix Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 20/20] solo6x10: also stop DMA if the SOLO_PCI_ERR_P2M_DESC is raised Hans Verkuil
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/enc.c |    4 ++--
 drivers/staging/media/solo6x10/p2m.c |    6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/media/solo6x10/enc.c b/drivers/staging/media/solo6x10/enc.c
index de50259..667c20a6 100644
--- a/drivers/staging/media/solo6x10/enc.c
+++ b/drivers/staging/media/solo6x10/enc.c
@@ -99,7 +99,7 @@ static void solo_capture_config(struct solo_dev *solo_dev)
 	solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, 0);
 
 	/* Clear OSG buffer */
-	buf = kzalloc(OSG_BUFFER_SIZE, GFP_KERNEL);
+	buf = kzalloc(OSG_BUFFER_SIZE, GFP_KERNEL | __GFP_DMA32);
 	if (!buf)
 		return;
 
@@ -130,7 +130,7 @@ int solo_osd_print(struct solo_enc_dev *solo_enc)
 		return 0;
 	}
 
-	buf = kzalloc(SOLO_EOSD_EXT_SIZE, GFP_KERNEL);
+	buf = kzalloc(SOLO_EOSD_EXT_SIZE, GFP_KERNEL | __GFP_DMA32);
 	if (!buf)
 		return -ENOMEM;
 
diff --git a/drivers/staging/media/solo6x10/p2m.c b/drivers/staging/media/solo6x10/p2m.c
index 58ab61b..65911fa 100644
--- a/drivers/staging/media/solo6x10/p2m.c
+++ b/drivers/staging/media/solo6x10/p2m.c
@@ -50,7 +50,7 @@ int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr,
 int solo_p2m_dma_t(struct solo_dev *solo_dev, u8 id, int wr,
 		   dma_addr_t dma_addr, u32 ext_addr, u32 size)
 {
-	struct p2m_desc *desc = kzalloc(sizeof(*desc) * 2, GFP_DMA);
+	struct p2m_desc *desc = kzalloc(sizeof(*desc) * 2, GFP_KERNEL | __GFP_DMA32);
 	int ret;
 
 	if (desc == NULL)
@@ -194,13 +194,13 @@ static unsigned long long p2m_test(struct solo_dev *solo_dev, u8 id,
 	int i;
 	unsigned long long err_cnt = 0;
 
-	wr_buf = kmalloc(size, GFP_KERNEL);
+	wr_buf = kmalloc(size, GFP_KERNEL | __GFP_DMA32);
 	if (!wr_buf) {
 		printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n");
 		return size;
 	}
 
-	rd_buf = kmalloc(size, GFP_KERNEL);
+	rd_buf = kmalloc(size, GFP_KERNEL | __GFP_DMA32);
 	if (!rd_buf) {
 		printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n");
 		kfree(wr_buf);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 19/20] solo6x10: small big-endian fix.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (16 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 18/20] solo6x10: use correct __GFP_DMA32 flags Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  2013-03-02 23:45   ` [RFC PATCH 20/20] solo6x10: also stop DMA if the SOLO_PCI_ERR_P2M_DESC is raised Hans Verkuil
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/p2m.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/solo6x10/p2m.c b/drivers/staging/media/solo6x10/p2m.c
index 65911fa..1b5b129 100644
--- a/drivers/staging/media/solo6x10/p2m.c
+++ b/drivers/staging/media/solo6x10/p2m.c
@@ -261,7 +261,7 @@ void solo_p2m_error_isr(struct solo_dev *solo_dev, u32 status)
 	struct solo_p2m_dev *p2m_dev;
 	int i;
 
-	if (!(status & SOLO_PCI_ERR_P2M))
+	if (!(status & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC)))
 		return;
 
 	for (i = 0; i < SOLO_NR_P2M; i++) {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [RFC PATCH 20/20] solo6x10: also stop DMA if the SOLO_PCI_ERR_P2M_DESC is raised.
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
                     ` (17 preceding siblings ...)
  2013-03-02 23:45   ` [RFC PATCH 19/20] solo6x10: small big-endian fix Hans Verkuil
@ 2013-03-02 23:45   ` Hans Verkuil
  18 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2013-03-02 23:45 UTC (permalink / raw)
  To: linux-media; +Cc: Ismael Luceno, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Otherwise the computer will hang.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/solo6x10/disp.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/solo6x10/disp.c b/drivers/staging/media/solo6x10/disp.c
index b91a6e2..224aa46 100644
--- a/drivers/staging/media/solo6x10/disp.c
+++ b/drivers/staging/media/solo6x10/disp.c
@@ -149,7 +149,7 @@ static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
 	int ret = 0;
 
 	for (i = 0; i < sizeof(buf) >> 1; i++)
-		buf[i] = val;
+		buf[i] = cpu_to_le16(val);
 
 	for (i = 0; i < reg_size; i += sizeof(buf))
 		ret |= solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_VIN, 1, buf,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul
  2013-03-02 23:45 [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Hans Verkuil
  2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
@ 2013-03-07 18:46 ` Ismael Luceno
  1 sibling, 0 replies; 22+ messages in thread
From: Ismael Luceno @ 2013-03-07 18:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

On Sun,  3 Mar 2013 00:45:16 +0100
Hans Verkuil <hverkuil@xs4all.nl> wrote: 
> 3) What is the meaning of this snippet of code in v4l2-enc.c?
> 
> 	if (pix->priv)
> 		solo_enc->type = SOLO_ENC_TYPE_EXT;
> 
>    I've commented it out since it is completely undocumented and no
> driver should assume that priv is non-zero anymore, precisely because
> of issues like this. Ismael, do you know what the difference is
> between SOLO_ENC_TYPE_STD and SOLO_ENC_TYPE_EXT?

When written to the first bit of the 0x480-0x4BC registers
(SOLO_CAP_CH_COMP_ENA_E(n)), it enables the encoding of the respective
extended channel.

It's a bad name :/.

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-03-07 18:52 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-02 23:45 [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Hans Verkuil
2013-03-02 23:45 ` [RFC PATCH 01/20] videobuf2: add gfp_flags Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 02/20] vb2-dma-sg: add debug module option Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 03/20] solo6x10: fix querycap Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 04/20] solo6x10: add v4l2_device Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 05/20] solo6x10: add control framework Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 06/20] solo6x10: fix scheduling while atomic error Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 07/20] solo6x10: fix various format-related compliancy issues Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 08/20] solo6x10: add support for prio and control event handling Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 09/20] solo6x10: move global fields in solo_enc_fh to solo_enc_dev Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 10/20] solo6x10: move global fields in solo_dev_fh to solo_dev Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 11/20] solo6x10: add missing size-- to enc_write_sg Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 12/20] solo6x10: rename the spinlock 'lock' to 'slock' Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 13/20] solo6x10: convert encoder nodes to vb2 Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 14/20] solo6x10: convert the display node " Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 15/20] solo6x10: use monotonic timestamps Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 16/20] solo6x10: drop video_type and add proper s_std support Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 17/20] solo6x10: update buffer flags to fix clash with existing flags Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 18/20] solo6x10: use correct __GFP_DMA32 flags Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 19/20] solo6x10: small big-endian fix Hans Verkuil
2013-03-02 23:45   ` [RFC PATCH 20/20] solo6x10: also stop DMA if the SOLO_PCI_ERR_P2M_DESC is raised Hans Verkuil
2013-03-07 18:46 ` [RFC PATCH 00/20] solo6x10: V4L2 compliancy fixes and major overhaul Ismael Luceno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox