linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/16] saa7134: cleanup
@ 2013-06-02 10:55 Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 01/16] saa7134: remove radio/type field from saa7134_fh Hans Verkuil
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media

This patch series cleans up saa7134, updating it to the latest frameworks
(except for vb2). Tested with a Beholder BeholdTV M6 empress card.

There is also one small v4l2-ctrls fix in the patch series and the
saa6752hs is moved to media/i2c, since it really has nothing to do with
the saa7134 driver.

This patch series sits on top of the "Control framework conversions"
patch series since it requires the saa6752hs patch from that series:

http://www.mail-archive.com/linux-media@vger.kernel.org/msg62772.html

Still to do: test the saa7134+saa6588 combo.

Regards,

	Hans


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

* [RFC PATCH 01/16] saa7134: remove radio/type field from saa7134_fh
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 02/16] saa7134: move the overlay fields from saa7134_fh to saa7134_dev Hans Verkuil
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

This information is already available in vfl_type in video_device.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-video.c |   89 +++++++++++------------------
 drivers/media/pci/saa7134/saa7134.h       |    2 -
 2 files changed, 32 insertions(+), 59 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index cc40938..910854b 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1287,15 +1287,17 @@ static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
 
 /* ------------------------------------------------------------------ */
 
-static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh)
+static struct videobuf_queue *saa7134_queue(struct file *file)
 {
-	struct videobuf_queue* q = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct saa7134_fh *fh = file->private_data;
+	struct videobuf_queue *q = NULL;
 
-	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
 		q = &fh->cap;
 		break;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
+	case VFL_TYPE_VBI:
 		q = &fh->vbi;
 		break;
 	default:
@@ -1304,12 +1306,14 @@ static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh)
 	return q;
 }
 
-static int saa7134_resource(struct saa7134_fh *fh)
+static int saa7134_resource(struct file *file)
 {
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	struct video_device *vdev = video_devdata(file);
+
+	if (vdev->vfl_type == VFL_TYPE_GRABBER)
 		return RESOURCE_VIDEO;
 
-	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+	if (vdev->vfl_type == VFL_TYPE_VBI)
 		return RESOURCE_VBI;
 
 	BUG();
@@ -1321,23 +1325,6 @@ static int video_open(struct file *file)
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh;
-	enum v4l2_buf_type type = 0;
-	int radio = 0;
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
-		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		break;
-	case VFL_TYPE_VBI:
-		type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		break;
-	case VFL_TYPE_RADIO:
-		radio = 1;
-		break;
-	}
-
-	dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev),
-		radio, v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
@@ -1347,8 +1334,6 @@ static int video_open(struct file *file)
 	v4l2_fh_init(&fh->fh, vdev);
 	file->private_data = fh;
 	fh->dev      = dev;
-	fh->radio    = radio;
-	fh->type     = type;
 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 	fh->width    = 720;
 	fh->height   = 576;
@@ -1368,7 +1353,7 @@ static int video_open(struct file *file)
 	saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
 	saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
 
-	if (fh->radio) {
+	if (vdev->vfl_type == VFL_TYPE_RADIO) {
 		/* switch to radio mode */
 		saa7134_tvaudio_setinput(dev,&card(dev).radio);
 		saa_call_all(dev, tuner, s_radio);
@@ -1384,19 +1369,20 @@ static int video_open(struct file *file)
 static ssize_t
 video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct saa7134_fh *fh = file->private_data;
 
-	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
 		if (res_locked(fh->dev,RESOURCE_VIDEO))
 			return -EBUSY;
-		return videobuf_read_one(saa7134_queue(fh),
+		return videobuf_read_one(saa7134_queue(file),
 					 data, count, ppos,
 					 file->f_flags & O_NONBLOCK);
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
+	case VFL_TYPE_VBI:
 		if (!res_get(fh->dev,fh,RESOURCE_VBI))
 			return -EBUSY;
-		return videobuf_read_stream(saa7134_queue(fh),
+		return videobuf_read_stream(saa7134_queue(file),
 					    data, count, ppos, 1,
 					    file->f_flags & O_NONBLOCK);
 		break;
@@ -1409,11 +1395,12 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 static unsigned int
 video_poll(struct file *file, struct poll_table_struct *wait)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct saa7134_fh *fh = file->private_data;
 	struct videobuf_buffer *buf = NULL;
 	unsigned int rc = 0;
 
-	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
+	if (vdev->vfl_type == VFL_TYPE_VBI)
 		return videobuf_poll_stream(file, &fh->vbi, wait);
 
 	if (res_check(fh,RESOURCE_VIDEO)) {
@@ -1451,6 +1438,7 @@ err:
 
 static int video_release(struct file *file)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct saa7134_fh  *fh  = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
 	struct saa6588_command cmd;
@@ -1489,7 +1477,7 @@ static int video_release(struct file *file)
 	saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
 
 	saa_call_all(dev, core, s_power, 0);
-	if (fh->radio)
+	if (vdev->vfl_type == VFL_TYPE_RADIO)
 		saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
 	/* free stuff */
@@ -1507,9 +1495,7 @@ static int video_release(struct file *file)
 
 static int video_mmap(struct file *file, struct vm_area_struct * vma)
 {
-	struct saa7134_fh *fh = file->private_data;
-
-	return videobuf_mmap_mapper(saa7134_queue(fh), vma);
+	return videobuf_mmap_mapper(saa7134_queue(file), vma);
 }
 
 static ssize_t radio_read(struct file *file, char __user *data,
@@ -2057,7 +2043,6 @@ static int saa7134_g_frequency(struct file *file, void *priv,
 	if (0 != f->tuner)
 		return -EINVAL;
 
-	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	saa_call_all(dev, tuner, g_frequency, f);
 
 	return 0;
@@ -2071,10 +2056,6 @@ static int saa7134_s_frequency(struct file *file, void *priv,
 
 	if (0 != f->tuner)
 		return -EINVAL;
-	if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
-		return -EINVAL;
-	if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
-		return -EINVAL;
 	mutex_lock(&dev->lock);
 
 	saa_call_all(dev, tuner, s_frequency, f);
@@ -2186,27 +2167,23 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on)
 static int saa7134_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
 {
-	struct saa7134_fh *fh = priv;
-	return videobuf_reqbufs(saa7134_queue(fh), p);
+	return videobuf_reqbufs(saa7134_queue(file), p);
 }
 
 static int saa7134_querybuf(struct file *file, void *priv,
 					struct v4l2_buffer *b)
 {
-	struct saa7134_fh *fh = priv;
-	return videobuf_querybuf(saa7134_queue(fh), b);
+	return videobuf_querybuf(saa7134_queue(file), b);
 }
 
 static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-	struct saa7134_fh *fh = priv;
-	return videobuf_qbuf(saa7134_queue(fh), b);
+	return videobuf_qbuf(saa7134_queue(file), b);
 }
 
 static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-	struct saa7134_fh *fh = priv;
-	return videobuf_dqbuf(saa7134_queue(fh), b,
+	return videobuf_dqbuf(saa7134_queue(file), b,
 				file->f_flags & O_NONBLOCK);
 }
 
@@ -2215,7 +2192,7 @@ static int saa7134_streamon(struct file *file, void *priv,
 {
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
-	int res = saa7134_resource(fh);
+	int res = saa7134_resource(file);
 
 	if (!res_get(dev, fh, res))
 		return -EBUSY;
@@ -2231,7 +2208,7 @@ static int saa7134_streamon(struct file *file, void *priv,
 			   PM_QOS_CPU_DMA_LATENCY,
 			   20);
 
-	return videobuf_streamon(saa7134_queue(fh));
+	return videobuf_streamon(saa7134_queue(file));
 }
 
 static int saa7134_streamoff(struct file *file, void *priv,
@@ -2240,11 +2217,11 @@ static int saa7134_streamoff(struct file *file, void *priv,
 	int err;
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
-	int res = saa7134_resource(fh);
+	int res = saa7134_resource(file);
 
 	pm_qos_remove_request(&fh->qos_request);
 
-	err = videobuf_streamoff(saa7134_queue(fh));
+	err = videobuf_streamoff(saa7134_queue(file));
 	if (err < 0)
 		return err;
 	res_free(dev, fh, res);
@@ -2287,9 +2264,7 @@ static int radio_g_tuner(struct file *file, void *priv,
 	if (0 != t->index)
 		return -EINVAL;
 
-	memset(t, 0, sizeof(*t));
 	strcpy(t->name, "Radio");
-	t->type = V4L2_TUNER_RADIO;
 
 	saa_call_all(dev, tuner, g_tuner, t);
 	t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index d2ad16c..a103678 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -471,8 +471,6 @@ struct saa7134_dmaqueue {
 struct saa7134_fh {
 	struct v4l2_fh             fh;
 	struct saa7134_dev         *dev;
-	unsigned int               radio;
-	enum v4l2_buf_type         type;
 	unsigned int               resources;
 	struct pm_qos_request	   qos_request;
 
-- 
1.7.10.4


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

* [RFC PATCH 02/16] saa7134: move the overlay fields from saa7134_fh to saa7134_dev.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 01/16] saa7134: remove radio/type field from saa7134_fh Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 03/16] saa7134: move fmt/width/height " Hans Verkuil
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

This is global data, not per-filehandle data.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-video.c |   33 +++++++++++++++--------------
 drivers/media/pci/saa7134/saa7134.h       |    9 ++++----
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 910854b..f7662a5 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -872,20 +872,20 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
 	unsigned long base,control,bpl;
 	int err;
 
-	err = verify_preview(dev,&fh->win);
+	err = verify_preview(dev, &dev->win);
 	if (0 != err)
 		return err;
 
-	dev->ovfield = fh->win.field;
+	dev->ovfield = dev->win.field;
 	dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
-		fh->win.w.width,fh->win.w.height,
-		fh->win.w.left,fh->win.w.top,
-		dev->ovfmt->name,v4l2_field_names[dev->ovfield]);
+		dev->win.w.width, dev->win.w.height,
+		dev->win.w.left, dev->win.w.top,
+		dev->ovfmt->name, v4l2_field_names[dev->ovfield]);
 
 	/* setup window + clipping */
-	set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height,
+	set_size(dev, TASK_B, dev->win.w.width, dev->win.w.height,
 		 V4L2_FIELD_HAS_BOTH(dev->ovfield));
-	setup_clipping(dev,fh->clips,fh->nclips,
+	setup_clipping(dev, dev->clips, dev->nclips,
 		       V4L2_FIELD_HAS_BOTH(dev->ovfield));
 	if (dev->ovfmt->yuv)
 		saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03);
@@ -895,8 +895,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
 
 	/* dma: setup channel 1 (= Video Task B) */
 	base  = (unsigned long)dev->ovbuf.base;
-	base += dev->ovbuf.fmt.bytesperline * fh->win.w.top;
-	base += dev->ovfmt->depth/8         * fh->win.w.left;
+	base += dev->ovbuf.fmt.bytesperline * dev->win.w.top;
+	base += dev->ovfmt->depth/8         * dev->win.w.left;
 	bpl   = dev->ovbuf.fmt.bytesperline;
 	control = SAA7134_RS_CONTROL_BURST_16;
 	if (dev->ovfmt->bswap)
@@ -1572,12 +1572,13 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
 	struct saa7134_fh *fh = priv;
+	struct saa7134_dev *dev = fh->dev;
 
 	if (saa7134_no_overlay > 0) {
 		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
-	f->fmt.win = fh->win;
+	f->fmt.win = dev->win;
 
 	return 0;
 }
@@ -1682,14 +1683,14 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 
 	mutex_lock(&dev->lock);
 
-	fh->win    = f->fmt.win;
-	fh->nclips = f->fmt.win.clipcount;
+	dev->win    = f->fmt.win;
+	dev->nclips = f->fmt.win.clipcount;
 
-	if (fh->nclips > 8)
-		fh->nclips = 8;
+	if (dev->nclips > 8)
+		dev->nclips = 8;
 
-	if (copy_from_user(fh->clips, f->fmt.win.clips,
-			   sizeof(struct v4l2_clip)*fh->nclips)) {
+	if (copy_from_user(dev->clips, f->fmt.win.clips,
+			   sizeof(struct v4l2_clip) * dev->nclips)) {
 		mutex_unlock(&dev->lock);
 		return -EFAULT;
 	}
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index a103678..fa21d14 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -474,11 +474,6 @@ struct saa7134_fh {
 	unsigned int               resources;
 	struct pm_qos_request	   qos_request;
 
-	/* video overlay */
-	struct v4l2_window         win;
-	struct v4l2_clip           clips[8];
-	unsigned int               nclips;
-
 	/* video capture */
 	struct saa7134_format      *fmt;
 	unsigned int               width,height;
@@ -590,6 +585,10 @@ struct saa7134_dev {
 	struct saa7134_format      *ovfmt;
 	unsigned int               ovenable;
 	enum v4l2_field            ovfield;
+	struct v4l2_window         win;
+	struct v4l2_clip           clips[8];
+	unsigned int               nclips;
+
 
 	/* video+ts+vbi capture */
 	struct saa7134_dmaqueue    video_q;
-- 
1.7.10.4


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

* [RFC PATCH 03/16] saa7134: move fmt/width/height from saa7134_fh to saa7134_dev
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 01/16] saa7134: remove radio/type field from saa7134_fh Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 02/16] saa7134: move the overlay fields from saa7134_fh to saa7134_dev Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 04/16] saa7134: move qos_request " Hans Verkuil
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

These fields are global, not per-filehandle.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-video.c |   57 +++++++++++++++--------------
 drivers/media/pci/saa7134/saa7134.h       |    4 +-
 2 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index f7662a5..9c45dd9 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1024,38 +1024,38 @@ static int buffer_prepare(struct videobuf_queue *q,
 	int err;
 
 	/* sanity checks */
-	if (NULL == fh->fmt)
+	if (NULL == dev->fmt)
 		return -EINVAL;
-	if (fh->width    < 48 ||
-	    fh->height   < 32 ||
-	    fh->width/4  > dev->crop_current.width  ||
-	    fh->height/4 > dev->crop_current.height ||
-	    fh->width    > dev->crop_bounds.width  ||
-	    fh->height   > dev->crop_bounds.height)
+	if (dev->width    < 48 ||
+	    dev->height   < 32 ||
+	    dev->width/4  > dev->crop_current.width  ||
+	    dev->height/4 > dev->crop_current.height ||
+	    dev->width    > dev->crop_bounds.width  ||
+	    dev->height   > dev->crop_bounds.height)
 		return -EINVAL;
-	size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+	size = (dev->width * dev->height * dev->fmt->depth) >> 3;
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
 
 	dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
-		vb->i,fh->width,fh->height,size,v4l2_field_names[field],
-		fh->fmt->name);
-	if (buf->vb.width  != fh->width  ||
-	    buf->vb.height != fh->height ||
+		vb->i, dev->width, dev->height, size, v4l2_field_names[field],
+		dev->fmt->name);
+	if (buf->vb.width  != dev->width  ||
+	    buf->vb.height != dev->height ||
 	    buf->vb.size   != size       ||
 	    buf->vb.field  != field      ||
-	    buf->fmt       != fh->fmt) {
+	    buf->fmt       != dev->fmt) {
 		saa7134_dma_free(q,buf);
 	}
 
 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
 		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 
-		buf->vb.width  = fh->width;
-		buf->vb.height = fh->height;
+		buf->vb.width  = dev->width;
+		buf->vb.height = dev->height;
 		buf->vb.size   = size;
 		buf->vb.field  = field;
-		buf->fmt       = fh->fmt;
+		buf->fmt       = dev->fmt;
 		buf->pt        = &fh->pt_cap;
 		dev->video_q.curr = NULL;
 
@@ -1082,8 +1082,9 @@ static int
 buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
 	struct saa7134_fh *fh = q->priv_data;
+	struct saa7134_dev *dev = fh->dev;
 
-	*size = fh->fmt->depth * fh->width * fh->height >> 3;
+	*size = dev->fmt->depth * dev->width * dev->height >> 3;
 	if (0 == *count)
 		*count = gbuffers;
 	*count = saa7134_buffer_count(*size,*count);
@@ -1334,9 +1335,6 @@ static int video_open(struct file *file)
 	v4l2_fh_init(&fh->fh, vdev);
 	file->private_data = fh;
 	fh->dev      = dev;
-	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-	fh->width    = 720;
-	fh->height   = 576;
 
 	videobuf_queue_sg_init(&fh->cap, &video_qops,
 			    &dev->pci->dev, &dev->slock,
@@ -1556,13 +1554,14 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
 	struct saa7134_fh *fh = priv;
+	struct saa7134_dev *dev = fh->dev;
 
-	f->fmt.pix.width        = fh->width;
-	f->fmt.pix.height       = fh->height;
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
 	f->fmt.pix.field        = fh->cap.field;
-	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.pixelformat  = dev->fmt->fourcc;
 	f->fmt.pix.bytesperline =
-		(f->fmt.pix.width * fh->fmt->depth) >> 3;
+		(f->fmt.pix.width * dev->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
 	return 0;
@@ -1652,15 +1651,16 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
 	struct saa7134_fh *fh = priv;
+	struct saa7134_dev *dev = fh->dev;
 	int err;
 
 	err = saa7134_try_fmt_vid_cap(file, priv, f);
 	if (0 != err)
 		return err;
 
-	fh->fmt       = format_by_fourcc(f->fmt.pix.pixelformat);
-	fh->width     = f->fmt.pix.width;
-	fh->height    = f->fmt.pix.height;
+	dev->fmt       = format_by_fourcc(f->fmt.pix.pixelformat);
+	dev->width     = f->fmt.pix.width;
+	dev->height    = f->fmt.pix.height;
 	fh->cap.field = f->fmt.pix.field;
 	return 0;
 }
@@ -2456,6 +2456,9 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 	dev->video_q.timeout.function = saa7134_buffer_timeout;
 	dev->video_q.timeout.data     = (unsigned long)(&dev->video_q);
 	dev->video_q.dev              = dev;
+	dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+	dev->width    = 720;
+	dev->height   = 576;
 
 	if (saa7134_boards[dev->board].video_out)
 		saa7134_videoport_init(dev);
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index fa21d14..8a62ff7 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -475,8 +475,6 @@ struct saa7134_fh {
 	struct pm_qos_request	   qos_request;
 
 	/* video capture */
-	struct saa7134_format      *fmt;
-	unsigned int               width,height;
 	struct videobuf_queue      cap;
 	struct saa7134_pgtable     pt_cap;
 
@@ -595,6 +593,8 @@ struct saa7134_dev {
 	struct saa7134_dmaqueue    vbi_q;
 	unsigned int               video_fieldcount;
 	unsigned int               vbi_fieldcount;
+	struct saa7134_format      *fmt;
+	unsigned int               width, height;
 
 	/* various v4l controls */
 	struct saa7134_tvnorm      *tvnorm;              /* video */
-- 
1.7.10.4


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

* [RFC PATCH 04/16] saa7134: move qos_request from saa7134_fh to saa7134_dev.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (2 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 03/16] saa7134: move fmt/width/height " Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 05/16] saa7134: move the queue data " Hans Verkuil
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

This is a global field, not a per-filehandle field.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-video.c |    4 ++--
 drivers/media/pci/saa7134/saa7134.h       |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 9c45dd9..2f6ba71 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -2205,7 +2205,7 @@ static int saa7134_streamon(struct file *file, void *priv,
 	 * Unfortunately, I lack register-level documentation to check the
 	 * Linux FIFO setup and confirm the perfect value.
 	 */
-	pm_qos_add_request(&fh->qos_request,
+	pm_qos_add_request(&dev->qos_request,
 			   PM_QOS_CPU_DMA_LATENCY,
 			   20);
 
@@ -2220,7 +2220,7 @@ static int saa7134_streamoff(struct file *file, void *priv,
 	struct saa7134_dev *dev = fh->dev;
 	int res = saa7134_resource(file);
 
-	pm_qos_remove_request(&fh->qos_request);
+	pm_qos_remove_request(&dev->qos_request);
 
 	err = videobuf_streamoff(saa7134_queue(file));
 	if (err < 0)
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 8a62ff7..8d1453a 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -472,7 +472,6 @@ struct saa7134_fh {
 	struct v4l2_fh             fh;
 	struct saa7134_dev         *dev;
 	unsigned int               resources;
-	struct pm_qos_request	   qos_request;
 
 	/* video capture */
 	struct videobuf_queue      cap;
@@ -595,6 +594,7 @@ struct saa7134_dev {
 	unsigned int               vbi_fieldcount;
 	struct saa7134_format      *fmt;
 	unsigned int               width, height;
+	struct pm_qos_request	   qos_request;
 
 	/* various v4l controls */
 	struct saa7134_tvnorm      *tvnorm;              /* video */
-- 
1.7.10.4


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

* [RFC PATCH 05/16] saa7134: move the queue data from saa7134_fh to saa7134_dev.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (3 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 04/16] saa7134: move qos_request " Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 06/16] saa7134: fix format-related compliance issues Hans Verkuil
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

These fields are global, not per-filehandle.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-core.c  |    1 +
 drivers/media/pci/saa7134/saa7134-vbi.c   |   11 ++--
 drivers/media/pci/saa7134/saa7134-video.c |  102 +++++++++++++++--------------
 drivers/media/pci/saa7134/saa7134.h       |   13 ++--
 4 files changed, 63 insertions(+), 64 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 45f0aca..e256f4a 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -751,6 +751,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
 	saa7134_input_fini(dev);
 	saa7134_vbi_fini(dev);
 	saa7134_tvaudio_fini(dev);
+	saa7134_video_fini(dev);
 	return 0;
 }
 
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index e9aa94b..d4da18d 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -117,8 +117,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 			  struct videobuf_buffer *vb,
 			  enum v4l2_field field)
 {
-	struct saa7134_fh *fh   = q->priv_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = q->priv_data;
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 	struct saa7134_tvnorm *norm = dev->tvnorm;
 	unsigned int lines, llength, size;
@@ -141,7 +140,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 		buf->vb.width  = llength;
 		buf->vb.height = lines;
 		buf->vb.size   = size;
-		buf->pt        = &fh->pt_vbi;
+		buf->pt        = &dev->pt_vbi;
 
 		err = videobuf_iolock(q,&buf->vb,NULL);
 		if (err)
@@ -166,8 +165,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 static int
 buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
-	struct saa7134_fh *fh   = q->priv_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = q->priv_data;
 	int llength,lines;
 
 	lines   = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
@@ -181,8 +179,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 
 static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct saa7134_fh *fh = q->priv_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = q->priv_data;
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 
 	saa7134_buffer_queue(dev,&dev->vbi_q,buf);
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 2f6ba71..9465a1d 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1017,8 +1017,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 			  struct videobuf_buffer *vb,
 			  enum v4l2_field field)
 {
-	struct saa7134_fh *fh = q->priv_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = q->priv_data;
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 	unsigned int size;
 	int err;
@@ -1056,7 +1055,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 		buf->vb.size   = size;
 		buf->vb.field  = field;
 		buf->fmt       = dev->fmt;
-		buf->pt        = &fh->pt_cap;
+		buf->pt        = &dev->pt_cap;
 		dev->video_q.curr = NULL;
 
 		err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
@@ -1081,8 +1080,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 static int
 buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
-	struct saa7134_fh *fh = q->priv_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = q->priv_data;
 
 	*size = dev->fmt->depth * dev->width * dev->height >> 3;
 	if (0 == *count)
@@ -1093,10 +1091,10 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 
 static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct saa7134_fh *fh = q->priv_data;
+	struct saa7134_dev *dev = q->priv_data;
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 
-	saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);
+	saa7134_buffer_queue(dev, &dev->video_q, buf);
 }
 
 static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
@@ -1292,14 +1290,15 @@ static struct videobuf_queue *saa7134_queue(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_fh *fh = file->private_data;
+	struct saa7134_dev *dev = fh->dev;
 	struct videobuf_queue *q = NULL;
 
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_GRABBER:
-		q = &fh->cap;
+		q = &dev->cap;
 		break;
 	case VFL_TYPE_VBI:
-		q = &fh->vbi;
+		q = &dev->vbi;
 		break;
 	default:
 		BUG();
@@ -1336,21 +1335,6 @@ static int video_open(struct file *file)
 	file->private_data = fh;
 	fh->dev      = dev;
 
-	videobuf_queue_sg_init(&fh->cap, &video_qops,
-			    &dev->pci->dev, &dev->slock,
-			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			    V4L2_FIELD_INTERLACED,
-			    sizeof(struct saa7134_buf),
-			    fh, NULL);
-	videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
-			    &dev->pci->dev, &dev->slock,
-			    V4L2_BUF_TYPE_VBI_CAPTURE,
-			    V4L2_FIELD_SEQ_TB,
-			    sizeof(struct saa7134_buf),
-			    fh, NULL);
-	saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
-	saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
-
 	if (vdev->vfl_type == VFL_TYPE_RADIO) {
 		/* switch to radio mode */
 		saa7134_tvaudio_setinput(dev,&card(dev).radio);
@@ -1395,28 +1379,30 @@ video_poll(struct file *file, struct poll_table_struct *wait)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_fh *fh = file->private_data;
+	struct saa7134_dev *dev = fh->dev;
 	struct videobuf_buffer *buf = NULL;
 	unsigned int rc = 0;
 
 	if (vdev->vfl_type == VFL_TYPE_VBI)
-		return videobuf_poll_stream(file, &fh->vbi, wait);
+		return videobuf_poll_stream(file, &dev->vbi, wait);
 
 	if (res_check(fh,RESOURCE_VIDEO)) {
-		mutex_lock(&fh->cap.vb_lock);
-		if (!list_empty(&fh->cap.stream))
-			buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
+		mutex_lock(&dev->cap.vb_lock);
+		if (!list_empty(&dev->cap.stream))
+			buf = list_entry(dev->cap.stream.next, struct videobuf_buffer, stream);
 	} else {
-		mutex_lock(&fh->cap.vb_lock);
-		if (UNSET == fh->cap.read_off) {
+		mutex_lock(&dev->cap.vb_lock);
+		if (UNSET == dev->cap.read_off) {
 			/* need to capture a new frame */
 			if (res_locked(fh->dev,RESOURCE_VIDEO))
 				goto err;
-			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))
+			if (0 != dev->cap.ops->buf_prepare(&dev->cap,
+					dev->cap.read_buf, dev->cap.field))
 				goto err;
-			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
-			fh->cap.read_off = 0;
+			dev->cap.ops->buf_queue(&dev->cap, dev->cap.read_buf);
+			dev->cap.read_off = 0;
 		}
-		buf = fh->cap.read_buf;
+		buf = dev->cap.read_buf;
 	}
 
 	if (!buf)
@@ -1426,11 +1412,11 @@ video_poll(struct file *file, struct poll_table_struct *wait)
 	if (buf->state == VIDEOBUF_DONE ||
 	    buf->state == VIDEOBUF_ERROR)
 		rc = POLLIN|POLLRDNORM;
-	mutex_unlock(&fh->cap.vb_lock);
+	mutex_unlock(&dev->cap.vb_lock);
 	return rc;
 
 err:
-	mutex_unlock(&fh->cap.vb_lock);
+	mutex_unlock(&dev->cap.vb_lock);
 	return POLLERR;
 }
 
@@ -1454,18 +1440,20 @@ static int video_release(struct file *file)
 
 	/* stop video capture */
 	if (res_check(fh, RESOURCE_VIDEO)) {
-		videobuf_streamoff(&fh->cap);
+		videobuf_streamoff(&dev->cap);
 		res_free(dev,fh,RESOURCE_VIDEO);
+		videobuf_mmap_free(&dev->cap);
 	}
-	if (fh->cap.read_buf) {
-		buffer_release(&fh->cap,fh->cap.read_buf);
-		kfree(fh->cap.read_buf);
+	if (dev->cap.read_buf) {
+		buffer_release(&dev->cap, dev->cap.read_buf);
+		kfree(dev->cap.read_buf);
 	}
 
 	/* stop vbi capture */
 	if (res_check(fh, RESOURCE_VBI)) {
-		videobuf_stop(&fh->vbi);
+		videobuf_stop(&dev->vbi);
 		res_free(dev,fh,RESOURCE_VBI);
+		videobuf_mmap_free(&dev->vbi);
 	}
 
 	/* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
@@ -1478,12 +1466,6 @@ static int video_release(struct file *file)
 	if (vdev->vfl_type == VFL_TYPE_RADIO)
 		saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
-	/* free stuff */
-	videobuf_mmap_free(&fh->cap);
-	videobuf_mmap_free(&fh->vbi);
-	saa7134_pgtable_free(dev->pci,&fh->pt_cap);
-	saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
-
 	v4l2_fh_del(&fh->fh);
 	v4l2_fh_exit(&fh->fh);
 	file->private_data = NULL;
@@ -1558,7 +1540,7 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
 
 	f->fmt.pix.width        = dev->width;
 	f->fmt.pix.height       = dev->height;
-	f->fmt.pix.field        = fh->cap.field;
+	f->fmt.pix.field        = dev->cap.field;
 	f->fmt.pix.pixelformat  = dev->fmt->fourcc;
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -1661,7 +1643,7 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
 	dev->fmt       = format_by_fourcc(f->fmt.pix.pixelformat);
 	dev->width     = f->fmt.pix.width;
 	dev->height    = f->fmt.pix.height;
-	fh->cap.field = f->fmt.pix.field;
+	dev->cap.field = f->fmt.pix.field;
 	return 0;
 }
 
@@ -2463,9 +2445,31 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 	if (saa7134_boards[dev->board].video_out)
 		saa7134_videoport_init(dev);
 
+	videobuf_queue_sg_init(&dev->cap, &video_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct saa7134_buf),
+			    dev, NULL);
+	videobuf_queue_sg_init(&dev->vbi, &saa7134_vbi_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB,
+			    sizeof(struct saa7134_buf),
+			    dev, NULL);
+	saa7134_pgtable_alloc(dev->pci, &dev->pt_cap);
+	saa7134_pgtable_alloc(dev->pci, &dev->pt_vbi);
+
 	return 0;
 }
 
+void saa7134_video_fini(struct saa7134_dev *dev)
+{
+	/* free stuff */
+	saa7134_pgtable_free(dev->pci, &dev->pt_cap);
+	saa7134_pgtable_free(dev->pci, &dev->pt_vbi);
+}
+
 int saa7134_videoport_init(struct saa7134_dev *dev)
 {
 	/* enable video output */
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 8d1453a..96b7ccf 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -472,14 +472,6 @@ struct saa7134_fh {
 	struct v4l2_fh             fh;
 	struct saa7134_dev         *dev;
 	unsigned int               resources;
-
-	/* video capture */
-	struct videobuf_queue      cap;
-	struct saa7134_pgtable     pt_cap;
-
-	/* vbi capture */
-	struct videobuf_queue      vbi;
-	struct saa7134_pgtable     pt_vbi;
 };
 
 /* dmasound dsp status */
@@ -589,7 +581,11 @@ struct saa7134_dev {
 
 	/* video+ts+vbi capture */
 	struct saa7134_dmaqueue    video_q;
+	struct videobuf_queue      cap;
+	struct saa7134_pgtable     pt_cap;
 	struct saa7134_dmaqueue    vbi_q;
+	struct videobuf_queue      vbi;
+	struct saa7134_pgtable     pt_vbi;
 	unsigned int               video_fieldcount;
 	unsigned int               vbi_fieldcount;
 	struct saa7134_format      *fmt;
@@ -773,6 +769,7 @@ int saa7134_video_init1(struct saa7134_dev *dev);
 int saa7134_video_init2(struct saa7134_dev *dev);
 void saa7134_irq_video_signalchange(struct saa7134_dev *dev);
 void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
+void saa7134_video_fini(struct saa7134_dev *dev);
 
 
 /* ----------------------------------------------------------- */
-- 
1.7.10.4


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

* [RFC PATCH 06/16] saa7134: fix format-related compliance issues.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (4 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 05/16] saa7134: move the queue data " Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 07/16] saa7134: convert to the control framework Hans Verkuil
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

- map overlay format values to the supported ranges
- set colorspace
- zero priv field
- fix cliplist handling
- fix field handling
- initialize ovbuf values

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-video.c |   74 ++++++++++++++++++++---------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 9465a1d..555e62c 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -825,20 +825,22 @@ static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips,
 	return 0;
 }
 
-static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
+static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool try)
 {
 	enum v4l2_field field;
 	int maxw, maxh;
 
-	if (NULL == dev->ovbuf.base)
+	if (!try && (dev->ovbuf.base == NULL || dev->ovfmt == NULL))
 		return -EINVAL;
-	if (NULL == dev->ovfmt)
-		return -EINVAL;
-	if (win->w.width < 48 || win->w.height <  32)
-		return -EINVAL;
-	if (win->clipcount > 2048)
-		return -EINVAL;
-
+	if (win->w.width < 48)
+		win->w.width = 48;
+	if (win->w.height < 32)
+		win->w.height = 32;
+	if (win->clipcount > 8)
+		win->clipcount = 8;
+
+	win->chromakey = 0;
+	win->global_alpha = 0;
 	field = win->field;
 	maxw  = dev->crop_current.width;
 	maxh  = dev->crop_current.height;
@@ -853,10 +855,9 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
 	case V4L2_FIELD_BOTTOM:
 		maxh = maxh / 2;
 		break;
-	case V4L2_FIELD_INTERLACED:
-		break;
 	default:
-		return -EINVAL;
+		field = V4L2_FIELD_INTERLACED;
+		break;
 	}
 
 	win->field = field;
@@ -872,7 +873,7 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
 	unsigned long base,control,bpl;
 	int err;
 
-	err = verify_preview(dev, &dev->win);
+	err = verify_preview(dev, &dev->win, false);
 	if (0 != err)
 		return err;
 
@@ -1546,6 +1547,8 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
 		(f->fmt.pix.width * dev->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1554,14 +1557,32 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
 {
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
+	struct v4l2_clip *clips = f->fmt.win.clips;
+	u32 clipcount = f->fmt.win.clipcount;
+	int err = 0;
+	int i;
 
 	if (saa7134_no_overlay > 0) {
 		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
+	mutex_lock(&dev->lock);
 	f->fmt.win = dev->win;
+	f->fmt.win.clips = clips;
+	if (clips == NULL)
+		clipcount = 0;
+	if (dev->nclips < clipcount)
+		clipcount = dev->nclips;
+	f->fmt.win.clipcount = clipcount;
+
+	for (i = 0; !err && i < clipcount; i++) {
+		if (copy_to_user(&f->fmt.win.clips[i].c, &dev->clips[i].c,
+					sizeof(struct v4l2_rect)))
+			err = -EFAULT;
+	}
+	mutex_unlock(&dev->lock);
 
-	return 0;
+	return err;
 }
 
 static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
@@ -1591,10 +1612,9 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
 	case V4L2_FIELD_BOTTOM:
 		maxh = maxh / 2;
 		break;
-	case V4L2_FIELD_INTERLACED:
-		break;
 	default:
-		return -EINVAL;
+		field = V4L2_FIELD_INTERLACED;
+		break;
 	}
 
 	f->fmt.pix.field = field;
@@ -1611,6 +1631,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1626,7 +1648,9 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
 		return -EINVAL;
 	}
 
-	return verify_preview(dev, &f->fmt.win);
+	if (f->fmt.win.clips == NULL)
+		f->fmt.win.clipcount = 0;
+	return verify_preview(dev, &f->fmt.win, true);
 }
 
 static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
@@ -1659,7 +1683,9 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
-	err = verify_preview(dev, &f->fmt.win);
+	if (f->fmt.win.clips == NULL)
+		f->fmt.win.clipcount = 0;
+	err = verify_preview(dev, &f->fmt.win, true);
 	if (0 != err)
 		return err;
 
@@ -1668,9 +1694,6 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 	dev->win    = f->fmt.win;
 	dev->nclips = f->fmt.win.clipcount;
 
-	if (dev->nclips > 8)
-		dev->nclips = 8;
-
 	if (copy_from_user(dev->clips, f->fmt.win.clips,
 			   sizeof(struct v4l2_clip) * dev->nclips)) {
 		mutex_unlock(&dev->lock);
@@ -2441,6 +2464,13 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 	dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 	dev->width    = 720;
 	dev->height   = 576;
+	dev->win.w.width = dev->width;
+	dev->win.w.height = dev->height;
+	dev->win.field = V4L2_FIELD_INTERLACED;
+	dev->ovbuf.fmt.width = dev->width;
+	dev->ovbuf.fmt.height = dev->height;
+	dev->ovbuf.fmt.pixelformat = dev->fmt->fourcc;
+	dev->ovbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	if (saa7134_boards[dev->board].video_out)
 		saa7134_videoport_init(dev);
-- 
1.7.10.4


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

* [RFC PATCH 07/16] saa7134: convert to the control framework.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (5 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 06/16] saa7134: fix format-related compliance issues Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:55 ` [RFC PATCH 08/16] v4l2-ctrls: V4L2_CTRL_CLASS_FM_RX controls are also valid radio controls Hans Verkuil
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-core.c    |    9 +-
 drivers/media/pci/saa7134/saa7134-empress.c |  142 ++--------
 drivers/media/pci/saa7134/saa7134-video.c   |  395 ++++++++-------------------
 drivers/media/pci/saa7134/saa7134.h         |   13 +-
 include/uapi/linux/v4l2-controls.h          |    4 +
 5 files changed, 163 insertions(+), 400 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index e256f4a..c4bdf45 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -1009,13 +1009,13 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 
 	/* load i2c helpers */
 	if (card_is_empress(dev)) {
-		struct v4l2_subdev *sd =
+		dev->empress_sd =
 			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs",
 				saa7134_boards[dev->board].empress_addr, NULL);
 
-		if (sd)
-			sd->grp_id = GRP_EMPRESS;
+		if (dev->empress_sd)
+			dev->empress_sd->grp_id = GRP_EMPRESS;
 	}
 
 	if (saa7134_boards[dev->board].rds_addr) {
@@ -1047,6 +1047,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 		printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
 
 	dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
+	dev->video_dev->ctrl_handler = &dev->ctrl_handler;
 	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
 				    video_nr[dev->nr]);
 	if (err < 0) {
@@ -1058,6 +1059,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 	       dev->name, video_device_node_name(dev->video_dev));
 
 	dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
+	dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
 
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[dev->nr]);
@@ -1068,6 +1070,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 
 	if (card_has_radio(dev)) {
 		dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
+		dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
 					    radio_nr[dev->nr]);
 		if (err < 0)
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 66a7081..edf4221 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -306,113 +306,6 @@ static int empress_streamoff(struct file *file, void *priv,
 	return videobuf_streamoff(&dev->empress_tsq);
 }
 
-static int empress_s_ext_ctrls(struct file *file, void *priv,
-			       struct v4l2_ext_controls *ctrls)
-{
-	struct saa7134_dev *dev = file->private_data;
-	int err;
-
-	/* count == 0 is abused in saa6752hs.c, so that special
-		case is handled here explicitly. */
-	if (ctrls->count == 0)
-		return 0;
-
-	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-
-	err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
-	ts_init_encoder(dev);
-
-	return err;
-}
-
-static int empress_g_ext_ctrls(struct file *file, void *priv,
-			       struct v4l2_ext_controls *ctrls)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-	return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
-}
-
-static int empress_g_ctrl(struct file *file, void *priv,
-					struct v4l2_control *c)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	return saa7134_g_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_s_ctrl(struct file *file, void *priv,
-					struct v4l2_control *c)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	return saa7134_s_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *c)
-{
-	/* Must be sorted from low to high control ID! */
-	static const u32 user_ctrls[] = {
-		V4L2_CID_USER_CLASS,
-		V4L2_CID_BRIGHTNESS,
-		V4L2_CID_CONTRAST,
-		V4L2_CID_SATURATION,
-		V4L2_CID_HUE,
-		V4L2_CID_AUDIO_VOLUME,
-		V4L2_CID_AUDIO_MUTE,
-		V4L2_CID_HFLIP,
-		0
-	};
-
-	/* Must be sorted from low to high control ID! */
-	static const u32 mpeg_ctrls[] = {
-		V4L2_CID_MPEG_CLASS,
-		V4L2_CID_MPEG_STREAM_TYPE,
-		V4L2_CID_MPEG_STREAM_PID_PMT,
-		V4L2_CID_MPEG_STREAM_PID_AUDIO,
-		V4L2_CID_MPEG_STREAM_PID_VIDEO,
-		V4L2_CID_MPEG_STREAM_PID_PCR,
-		V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
-		V4L2_CID_MPEG_AUDIO_ENCODING,
-		V4L2_CID_MPEG_AUDIO_L2_BITRATE,
-		V4L2_CID_MPEG_VIDEO_ENCODING,
-		V4L2_CID_MPEG_VIDEO_ASPECT,
-		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-		V4L2_CID_MPEG_VIDEO_BITRATE,
-		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-		0
-	};
-	static const u32 *ctrl_classes[] = {
-		user_ctrls,
-		mpeg_ctrls,
-		NULL
-	};
-	struct saa7134_dev *dev = file->private_data;
-
-	c->id = v4l2_ctrl_next(ctrl_classes, c->id);
-	if (c->id == 0)
-		return -EINVAL;
-	if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
-		return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
-	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
-		return saa7134_queryctrl(file, priv, c);
-	return saa_call_empress(dev, core, queryctrl, c);
-}
-
-static int empress_querymenu(struct file *file, void *priv,
-					struct v4l2_querymenu *c)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-	return saa_call_empress(dev, core, querymenu, c);
-}
-
 static int empress_g_chip_ident(struct file *file, void *fh,
 	       struct v4l2_dbg_chip_ident *chip)
 {
@@ -466,15 +359,9 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
 	.vidioc_dqbuf			= empress_dqbuf,
 	.vidioc_streamon		= empress_streamon,
 	.vidioc_streamoff		= empress_streamoff,
-	.vidioc_s_ext_ctrls		= empress_s_ext_ctrls,
-	.vidioc_g_ext_ctrls		= empress_g_ext_ctrls,
 	.vidioc_enum_input		= empress_enum_input,
 	.vidioc_g_input			= empress_g_input,
 	.vidioc_s_input			= empress_s_input,
-	.vidioc_queryctrl		= empress_queryctrl,
-	.vidioc_querymenu		= empress_querymenu,
-	.vidioc_g_ctrl			= empress_g_ctrl,
-	.vidioc_s_ctrl			= empress_s_ctrl,
 	.vidioc_g_chip_ident 		= empress_g_chip_ident,
 	.vidioc_s_std			= empress_s_std,
 	.vidioc_g_std			= empress_g_std,
@@ -508,9 +395,26 @@ static void empress_signal_change(struct saa7134_dev *dev)
 	schedule_work(&dev->empress_workqueue);
 }
 
+static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_HUE:
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_PRIVATE_INVERT:
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		return true;
+	default:
+		return false;
+	}
+}
 
 static int empress_init(struct saa7134_dev *dev)
 {
+	struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
 	int err;
 
 	dprintk("%s: %s\n",dev->name,__func__);
@@ -518,11 +422,20 @@ static int empress_init(struct saa7134_dev *dev)
 	if (NULL == dev->empress_dev)
 		return -ENOMEM;
 	*(dev->empress_dev) = saa7134_empress_template;
-	dev->empress_dev->parent  = &dev->pci->dev;
+	dev->empress_dev->v4l2_dev  = &dev->v4l2_dev;
 	dev->empress_dev->release = video_device_release;
 	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
 		 "%s empress (%s)", dev->name,
 		 saa7134_boards[dev->board].name);
+	v4l2_ctrl_handler_init(hdl, 21);
+	v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
+	if (dev->empress_sd)
+		v4l2_ctrl_add_handler(hdl, dev->empress_sd->ctrl_handler, NULL);
+	if (hdl->error) {
+		video_device_release(dev->empress_dev);
+		return hdl->error;
+	}
+	dev->empress_dev->ctrl_handler = hdl;
 
 	INIT_WORK(&dev->empress_workqueue, empress_signal_update);
 
@@ -558,6 +471,7 @@ static int empress_fini(struct saa7134_dev *dev)
 		return 0;
 	flush_work(&dev->empress_workqueue);
 	video_unregister_device(dev->empress_dev);
+	v4l2_ctrl_handler_free(&dev->empress_ctrl_handler);
 	dev->empress_dev = NULL;
 	return 0;
 }
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 555e62c..6ca00fa 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -369,117 +369,6 @@ static struct saa7134_tvnorm tvnorms[] = {
 };
 #define TVNORMS ARRAY_SIZE(tvnorms)
 
-#define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 4)
-
-static const struct v4l2_queryctrl no_ctrl = {
-	.name  = "42",
-	.flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl video_ctrls[] = {
-	/* --- video --- */
-	{
-		.id            = V4L2_CID_BRIGHTNESS,
-		.name          = "Brightness",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 128,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_CONTRAST,
-		.name          = "Contrast",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 68,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_SATURATION,
-		.name          = "Saturation",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 64,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_HUE,
-		.name          = "Hue",
-		.minimum       = -128,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_HFLIP,
-		.name          = "Mirror",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},
-	/* --- audio --- */
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = -15,
-		.maximum       = 15,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-	/* --- private --- */
-	{
-		.id            = V4L2_CID_PRIVATE_INVERT,
-		.name          = "Invert",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_Y_ODD,
-		.name          = "y offset odd field",
-		.minimum       = 0,
-		.maximum       = 128,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_Y_EVEN,
-		.name          = "y offset even field",
-		.minimum       = 0,
-		.maximum       = 128,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
-		.name          = "automute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}
-};
-static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
-
-static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
-{
-	unsigned int i;
-
-	for (i = 0; i < CTRLS; i++)
-		if (video_ctrls[i].id == id)
-			return video_ctrls+i;
-	return NULL;
-}
-
 static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
 {
 	unsigned int i;
@@ -868,7 +757,7 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool
 	return 0;
 }
 
-static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+static int start_preview(struct saa7134_dev *dev)
 {
 	unsigned long base,control,bpl;
 	int err;
@@ -923,7 +812,7 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
 	return 0;
 }
 
-static int stop_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+static int stop_preview(struct saa7134_dev *dev)
 {
 	dev->ovenable = 0;
 	saa7134_set_dmabits(dev);
@@ -1114,133 +1003,56 @@ static struct videobuf_queue_ops video_qops = {
 
 /* ------------------------------------------------------------------ */
 
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
-{
-	const struct v4l2_queryctrl* ctrl;
-
-	ctrl = ctrl_by_id(c->id);
-	if (NULL == ctrl)
-		return -EINVAL;
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		c->value = dev->ctl_bright;
-		break;
-	case V4L2_CID_HUE:
-		c->value = dev->ctl_hue;
-		break;
-	case V4L2_CID_CONTRAST:
-		c->value = dev->ctl_contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		c->value = dev->ctl_saturation;
-		break;
-	case V4L2_CID_AUDIO_MUTE:
-		c->value = dev->ctl_mute;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-		c->value = dev->ctl_volume;
-		break;
-	case V4L2_CID_PRIVATE_INVERT:
-		c->value = dev->ctl_invert;
-		break;
-	case V4L2_CID_HFLIP:
-		c->value = dev->ctl_mirror;
-		break;
-	case V4L2_CID_PRIVATE_Y_EVEN:
-		c->value = dev->ctl_y_even;
-		break;
-	case V4L2_CID_PRIVATE_Y_ODD:
-		c->value = dev->ctl_y_odd;
-		break;
-	case V4L2_CID_PRIVATE_AUTOMUTE:
-		c->value = dev->ctl_automute;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
-
-static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct saa7134_fh *fh = priv;
-
-	return saa7134_g_ctrl_internal(fh->dev, fh, c);
-}
-
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c)
-{
-	const struct v4l2_queryctrl* ctrl;
+	struct saa7134_dev *dev = container_of(ctrl->handler, struct saa7134_dev, ctrl_handler);
 	unsigned long flags;
 	int restart_overlay = 0;
-	int err;
-
-	err = -EINVAL;
 
-	mutex_lock(&dev->lock);
-
-	ctrl = ctrl_by_id(c->id);
-	if (NULL == ctrl)
-		goto error;
-
-	dprintk("set_control name=%s val=%d\n",ctrl->name,c->value);
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_BOOLEAN:
-	case V4L2_CTRL_TYPE_MENU:
-	case V4L2_CTRL_TYPE_INTEGER:
-		if (c->value < ctrl->minimum)
-			c->value = ctrl->minimum;
-		if (c->value > ctrl->maximum)
-			c->value = ctrl->maximum;
-		break;
-	default:
-		/* nothing */;
-	}
-	switch (c->id) {
+	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		dev->ctl_bright = c->value;
-		saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
+		dev->ctl_bright = ctrl->val;
+		saa_writeb(SAA7134_DEC_LUMA_BRIGHT, ctrl->val);
 		break;
 	case V4L2_CID_HUE:
-		dev->ctl_hue = c->value;
-		saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
+		dev->ctl_hue = ctrl->val;
+		saa_writeb(SAA7134_DEC_CHROMA_HUE, ctrl->val);
 		break;
 	case V4L2_CID_CONTRAST:
-		dev->ctl_contrast = c->value;
+		dev->ctl_contrast = ctrl->val;
 		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
 			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
 		break;
 	case V4L2_CID_SATURATION:
-		dev->ctl_saturation = c->value;
+		dev->ctl_saturation = ctrl->val;
 		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
 			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		dev->ctl_mute = c->value;
+		dev->ctl_mute = ctrl->val;
 		saa7134_tvaudio_setmute(dev);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
-		dev->ctl_volume = c->value;
+		dev->ctl_volume = ctrl->val;
 		saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
 		break;
 	case V4L2_CID_PRIVATE_INVERT:
-		dev->ctl_invert = c->value;
+		dev->ctl_invert = ctrl->val;
 		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
 			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
 		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
 			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
 		break;
 	case V4L2_CID_HFLIP:
-		dev->ctl_mirror = c->value;
+		dev->ctl_mirror = ctrl->val;
 		restart_overlay = 1;
 		break;
 	case V4L2_CID_PRIVATE_Y_EVEN:
-		dev->ctl_y_even = c->value;
+		dev->ctl_y_even = ctrl->val;
 		restart_overlay = 1;
 		break;
 	case V4L2_CID_PRIVATE_Y_ODD:
-		dev->ctl_y_odd = c->value;
+		dev->ctl_y_odd = ctrl->val;
 		restart_overlay = 1;
 		break;
 	case V4L2_CID_PRIVATE_AUTOMUTE:
@@ -1250,7 +1062,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, str
 		tda9887_cfg.tuner = TUNER_TDA9887;
 		tda9887_cfg.priv = &dev->tda9887_conf;
 
-		dev->ctl_automute = c->value;
+		dev->ctl_automute = ctrl->val;
 		if (dev->tda9887_conf) {
 			if (dev->ctl_automute)
 				dev->tda9887_conf |= TDA9887_AUTOMUTE;
@@ -1262,27 +1074,15 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, str
 		break;
 	}
 	default:
-		goto error;
+		return -EINVAL;
 	}
-	if (restart_overlay && fh && res_check(fh, RESOURCE_OVERLAY)) {
-		spin_lock_irqsave(&dev->slock,flags);
-		stop_preview(dev,fh);
-		start_preview(dev,fh);
-		spin_unlock_irqrestore(&dev->slock,flags);
+	if (restart_overlay && res_locked(dev, RESOURCE_OVERLAY)) {
+		spin_lock_irqsave(&dev->slock, flags);
+		stop_preview(dev);
+		start_preview(dev);
+		spin_unlock_irqrestore(&dev->slock, flags);
 	}
-	err = 0;
-
-error:
-	mutex_unlock(&dev->lock);
-	return err;
-}
-EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
-
-static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
-{
-	struct saa7134_fh *fh = f;
-
-	return saa7134_s_ctrl_internal(fh->dev, fh, c);
+	return 0;
 }
 
 /* ------------------------------------------------------------------ */
@@ -1434,7 +1234,7 @@ static int video_release(struct file *file)
 	/* turn off overlay */
 	if (res_check(fh, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock,flags);
-		stop_preview(dev,fh);
+		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock,flags);
 		res_free(dev,fh,RESOURCE_OVERLAY);
 	}
@@ -1702,8 +1502,8 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 
 	if (res_check(fh, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock, flags);
-		stop_preview(dev, fh);
-		start_preview(dev, fh);
+		stop_preview(dev);
+		start_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 	}
 
@@ -1711,21 +1511,6 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 	return 0;
 }
 
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c)
-{
-	const struct v4l2_queryctrl *ctrl;
-
-	if ((c->id <  V4L2_CID_BASE ||
-	     c->id >= V4L2_CID_LASTP1) &&
-	    (c->id <  V4L2_CID_PRIVATE_BASE ||
-	     c->id >= V4L2_CID_PRIVATE_LASTP1))
-		return -EINVAL;
-	ctrl = ctrl_by_id(c->id);
-	*c = (NULL != ctrl) ? *ctrl : no_ctrl;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7134_queryctrl);
-
 static int saa7134_enum_input(struct file *file, void *priv,
 					struct v4l2_input *i)
 {
@@ -1881,13 +1666,13 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 	mutex_lock(&dev->lock);
 	if (fh && res_check(fh, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock, flags);
-		stop_preview(dev, fh);
+		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 
 		set_tvnorm(dev, &tvnorms[i]);
 
 		spin_lock_irqsave(&dev->slock, flags);
-		start_preview(dev, fh);
+		start_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 	} else
 		set_tvnorm(dev, &tvnorms[i]);
@@ -2156,14 +1941,14 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on)
 		if (!res_get(dev, fh, RESOURCE_OVERLAY))
 			return -EBUSY;
 		spin_lock_irqsave(&dev->slock, flags);
-		start_preview(dev, fh);
+		start_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 	}
 	if (!on) {
 		if (!res_check(fh, RESOURCE_OVERLAY))
 			return -EINVAL;
 		spin_lock_irqsave(&dev->slock, flags);
-		stop_preview(dev, fh);
+		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 		res_free(dev, fh, RESOURCE_OVERLAY);
 	}
@@ -2322,22 +2107,6 @@ static int radio_s_std(struct file *file, void *fh, v4l2_std_id norm)
 	return 0;
 }
 
-static int radio_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *c)
-{
-	const struct v4l2_queryctrl *ctrl;
-
-	if (c->id <  V4L2_CID_BASE ||
-	    c->id >= V4L2_CID_LASTP1)
-		return -EINVAL;
-	if (c->id == V4L2_CID_AUDIO_MUTE) {
-		ctrl = ctrl_by_id(c->id);
-		*c = *ctrl;
-	} else
-		*c = no_ctrl;
-	return 0;
-}
-
 static const struct v4l2_file_operations video_fops =
 {
 	.owner	  = THIS_MODULE,
@@ -2372,9 +2141,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_enum_input		= saa7134_enum_input,
 	.vidioc_g_input			= saa7134_g_input,
 	.vidioc_s_input			= saa7134_s_input,
-	.vidioc_queryctrl		= saa7134_queryctrl,
-	.vidioc_g_ctrl			= saa7134_g_ctrl,
-	.vidioc_s_ctrl			= saa7134_s_ctrl,
 	.vidioc_streamon		= saa7134_streamon,
 	.vidioc_streamoff		= saa7134_streamoff,
 	.vidioc_g_tuner			= saa7134_g_tuner,
@@ -2408,10 +2174,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_s_tuner		= radio_s_tuner,
 	.vidioc_s_input		= radio_s_input,
 	.vidioc_s_std		= radio_s_std,
-	.vidioc_queryctrl	= radio_queryctrl,
 	.vidioc_g_input		= radio_g_input,
-	.vidioc_g_ctrl		= saa7134_g_ctrl,
-	.vidioc_s_ctrl		= saa7134_s_ctrl,
 	.vidioc_g_frequency	= saa7134_g_frequency,
 	.vidioc_s_frequency	= saa7134_s_frequency,
 };
@@ -2433,8 +2196,55 @@ struct video_device saa7134_radio_template = {
 	.ioctl_ops 		= &radio_ioctl_ops,
 };
 
+static const struct v4l2_ctrl_ops saa7134_ctrl_ops = {
+	.s_ctrl = saa7134_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_invert = {
+	.ops = &saa7134_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_INVERT,
+	.name = "Invert",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_y_odd = {
+	.ops = &saa7134_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_Y_ODD,
+	.name = "Y Offset Odd Field",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 128,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_y_even = {
+	.ops = &saa7134_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_Y_EVEN,
+	.name = "Y Offset Even Field",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 128,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_automute = {
+	.ops = &saa7134_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_AUTOMUTE,
+	.name = "Automute",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
 int saa7134_video_init1(struct saa7134_dev *dev)
 {
+	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
+
 	/* sanitycheck insmod options */
 	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
 		gbuffers = 2;
@@ -2442,17 +2252,38 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 		gbufsize = gbufsize_max;
 	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 
-	/* put some sensible defaults into the data structures ... */
-	dev->ctl_bright     = ctrl_by_id(V4L2_CID_BRIGHTNESS)->default_value;
-	dev->ctl_contrast   = ctrl_by_id(V4L2_CID_CONTRAST)->default_value;
-	dev->ctl_hue        = ctrl_by_id(V4L2_CID_HUE)->default_value;
-	dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
-	dev->ctl_volume     = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
-	dev->ctl_mute       = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
-	dev->ctl_invert     = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
-	dev->ctl_automute   = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
-
-	if (dev->tda9887_conf && dev->ctl_automute)
+	v4l2_ctrl_handler_init(hdl, 11);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 127, 1, 68);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);
+	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_invert, NULL);
+	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_odd, NULL);
+	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_even, NULL);
+	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_automute, NULL);
+	if (hdl->error)
+		return hdl->error;
+	if (card_has_radio(dev)) {
+		hdl = &dev->radio_ctrl_handler;
+		v4l2_ctrl_handler_init(hdl, 2);
+		v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler,
+				v4l2_ctrl_radio_filter);
+		if (hdl->error)
+			return hdl->error;
+	}
+	dev->ctl_mute       = 1;
+
+	if (dev->tda9887_conf && saa7134_ctrl_automute.def)
 		dev->tda9887_conf |= TDA9887_AUTOMUTE;
 	dev->automute       = 0;
 
@@ -2498,6 +2329,9 @@ void saa7134_video_fini(struct saa7134_dev *dev)
 	/* free stuff */
 	saa7134_pgtable_free(dev->pci, &dev->pt_cap);
 	saa7134_pgtable_free(dev->pci, &dev->pt_vbi);
+	v4l2_ctrl_handler_free(&dev->ctrl_handler);
+	if (card_has_radio(dev))
+		v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
 }
 
 int saa7134_videoport_init(struct saa7134_dev *dev)
@@ -2541,6 +2375,7 @@ int saa7134_video_init2(struct saa7134_dev *dev)
 	/* init video hw */
 	set_tvnorm(dev,&tvnorms[0]);
 	video_mux(dev,0);
+	v4l2_ctrl_handler_setup(&dev->ctrl_handler);
 	saa7134_tvaudio_setmute(dev);
 	saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
 	return 0;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 96b7ccf..e0e5c70 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -37,6 +37,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
 #include <media/tuner.h>
 #include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
@@ -410,6 +411,11 @@ struct saa7134_board {
 #define card(dev)             (saa7134_boards[dev->board])
 #define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
 
+#define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_USER_SAA7134_BASE + 0)
+#define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_USER_SAA7134_BASE + 1)
+#define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_USER_SAA7134_BASE + 2)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_USER_SAA7134_BASE + 3)
+
 /* ----------------------------------------------------------- */
 /* device / file handle status                                 */
 
@@ -595,6 +601,7 @@ struct saa7134_dev {
 	/* various v4l controls */
 	struct saa7134_tvnorm      *tvnorm;              /* video */
 	struct saa7134_tvaudio     *tvaudio;
+	struct v4l2_ctrl_handler   ctrl_handler;
 	unsigned int               ctl_input;
 	int                        ctl_bright;
 	int                        ctl_contrast;
@@ -622,6 +629,7 @@ struct saa7134_dev {
 	int                        last_carrier;
 	int                        nosignal;
 	unsigned int               insuspend;
+	struct v4l2_ctrl_handler   radio_ctrl_handler;
 
 	/* I2C keyboard data */
 	struct IR_i2c_init_data    init_data;
@@ -634,10 +642,12 @@ struct saa7134_dev {
 
 	/* SAA7134_MPEG_EMPRESS only */
 	struct video_device        *empress_dev;
+	struct v4l2_subdev	   *empress_sd;
 	struct videobuf_queue      empress_tsq;
 	atomic_t 		   empress_users;
 	struct work_struct         empress_workqueue;
 	int                        empress_started;
+	struct v4l2_ctrl_handler   empress_ctrl_handler;
 
 #if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB)
 	/* SAA7134_MPEG_DVB only */
@@ -757,9 +767,6 @@ extern unsigned int video_debug;
 extern struct video_device saa7134_video_template;
 extern struct video_device saa7134_radio_template;
 
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
 int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id id);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 69bd5bb..0f76a16 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -160,6 +160,10 @@ enum v4l2_colorfx {
  * of controls. Total of 16 controls is reserved for this driver */
 #define V4L2_CID_USER_SI476X_BASE		(V4L2_CID_USER_BASE + 0x1040)
 
+/* The base for the saa7134 driver controls.
+ * We reserve 16 controls for this driver. */
+#define V4L2_CID_USER_SAA7134_BASE		(V4L2_CID_USER_BASE + 0x1050)
+
 /* MPEG-class control IDs */
 
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
-- 
1.7.10.4


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

* [RFC PATCH 08/16] v4l2-ctrls: V4L2_CTRL_CLASS_FM_RX controls are also valid radio controls.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (6 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 07/16] saa7134: convert to the control framework Hans Verkuil
@ 2013-06-02 10:55 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 09/16] saa7134: cleanup radio/video/empress ioctl handling Hans Verkuil
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The radio filter function that filters controls that are valid for a radio
device should also accept V4L2_CTRL_CLASS_FM_RX controls.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index ebb8e48..fccd08b 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1835,6 +1835,8 @@ bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl)
 {
 	if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX)
 		return true;
+	if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_RX)
+		return true;
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 	case V4L2_CID_AUDIO_VOLUME:
-- 
1.7.10.4


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

* [RFC PATCH 09/16] saa7134: cleanup radio/video/empress ioctl handling
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (7 preceding siblings ...)
  2013-06-02 10:55 ` [RFC PATCH 08/16] v4l2-ctrls: V4L2_CTRL_CLASS_FM_RX controls are also valid radio controls Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 10/16] saa7134: fix empress format compliance bugs Hans Verkuil
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The video and empress nodes can share various ioctls.

Drop the input/std ioctls from the radio node (out of spec).

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-empress.c |   79 +++-----------------
 drivers/media/pci/saa7134/saa7134-video.c   |  108 +++++++++------------------
 drivers/media/pci/saa7134/saa7134.h         |   16 +++-
 3 files changed, 61 insertions(+), 142 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index edf4221..0bc1eec 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -157,54 +157,6 @@ ts_mmap(struct file *file, struct vm_area_struct * vma)
 	return videobuf_mmap_mapper(&dev->empress_tsq, vma);
 }
 
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel pointer.
- */
-
-static int empress_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *cap)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	strcpy(cap->driver, "saa7134");
-	strlcpy(cap->card, saa7134_boards[dev->board].name,
-		sizeof(cap->card));
-	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-	cap->capabilities =
-		V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_READWRITE |
-		V4L2_CAP_STREAMING;
-	return 0;
-}
-
-static int empress_enum_input(struct file *file, void *priv,
-					struct v4l2_input *i)
-{
-	if (i->index != 0)
-		return -EINVAL;
-
-	i->type = V4L2_INPUT_TYPE_CAMERA;
-	strcpy(i->name, "CCIR656");
-
-	return 0;
-}
-
-static int empress_g_input(struct file *file, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
-static int empress_s_input(struct file *file, void *priv, unsigned int i)
-{
-	if (i != 0)
-		return -EINVAL;
-
-	return 0;
-}
-
 static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
@@ -321,21 +273,6 @@ static int empress_g_chip_ident(struct file *file, void *fh,
 	return -EINVAL;
 }
 
-static int empress_s_std(struct file *file, void *priv, v4l2_std_id id)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	return saa7134_s_std_internal(dev, NULL, id);
-}
-
-static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-	struct saa7134_dev *dev = file->private_data;
-
-	*id = dev->tvnorm->id;
-	return 0;
-}
-
 static const struct v4l2_file_operations ts_fops =
 {
 	.owner	  = THIS_MODULE,
@@ -348,7 +285,7 @@ static const struct v4l2_file_operations ts_fops =
 };
 
 static const struct v4l2_ioctl_ops ts_ioctl_ops = {
-	.vidioc_querycap		= empress_querycap,
+	.vidioc_querycap		= saa7134_querycap,
 	.vidioc_enum_fmt_vid_cap	= empress_enum_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
@@ -359,12 +296,16 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
 	.vidioc_dqbuf			= empress_dqbuf,
 	.vidioc_streamon		= empress_streamon,
 	.vidioc_streamoff		= empress_streamoff,
-	.vidioc_enum_input		= empress_enum_input,
-	.vidioc_g_input			= empress_g_input,
-	.vidioc_s_input			= empress_s_input,
+	.vidioc_g_frequency		= saa7134_g_frequency,
+	.vidioc_s_frequency		= saa7134_s_frequency,
+	.vidioc_g_tuner			= saa7134_g_tuner,
+	.vidioc_s_tuner			= saa7134_s_tuner,
+	.vidioc_enum_input		= saa7134_enum_input,
+	.vidioc_g_input			= saa7134_g_input,
+	.vidioc_s_input			= saa7134_s_input,
 	.vidioc_g_chip_ident 		= empress_g_chip_ident,
-	.vidioc_s_std			= empress_s_std,
-	.vidioc_g_std			= empress_g_std,
+	.vidioc_s_std			= saa7134_s_std,
+	.vidioc_g_std			= saa7134_g_std,
 };
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 6ca00fa..3471841 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1511,11 +1511,9 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 	return 0;
 }
 
-static int saa7134_enum_input(struct file *file, void *priv,
-					struct v4l2_input *i)
+int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	unsigned int n;
 
 	n = i->index;
@@ -1542,20 +1540,20 @@ static int saa7134_enum_input(struct file *file, void *priv,
 	i->std = SAA7134_NORMS;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_enum_input);
 
-static int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
+int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	*i = dev->ctl_input;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_g_input);
 
-static int saa7134_s_input(struct file *file, void *priv, unsigned int i)
+int saa7134_s_input(struct file *file, void *priv, unsigned int i)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (i >= SAA7134_INPUT_MAX)
 		return -EINVAL;
@@ -1566,12 +1564,12 @@ static int saa7134_s_input(struct file *file, void *priv, unsigned int i)
 	mutex_unlock(&dev->lock);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_s_input);
 
-static int saa7134_querycap(struct file *file, void  *priv,
+int saa7134_querycap(struct file *file, void *priv,
 					struct v4l2_capability *cap)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct video_device *vdev = video_devdata(file);
 	u32 radio_caps, video_caps, vbi_caps;
 
@@ -1591,7 +1589,8 @@ static int saa7134_querycap(struct file *file, void  *priv,
 		radio_caps |= V4L2_CAP_RDS_CAPTURE;
 
 	video_caps = V4L2_CAP_VIDEO_CAPTURE;
-	if (saa7134_no_overlay <= 0)
+	/* For the empress video node priv == dev */
+	if (saa7134_no_overlay <= 0 && priv != dev)
 		video_caps |= V4L2_CAP_VIDEO_OVERLAY;
 
 	vbi_caps = V4L2_CAP_VBI_CAPTURE;
@@ -1617,14 +1616,18 @@ static int saa7134_querycap(struct file *file, void  *priv,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_querycap);
 
-int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id id)
+int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
+	struct saa7134_dev *dev = video_drvdata(file);
+	/* For the empress video node priv == dev */
+	bool is_empress = priv == dev;
 	unsigned long flags;
 	unsigned int i;
 	v4l2_std_id fixup;
 
-	if (!fh && res_locked(dev, RESOURCE_OVERLAY)) {
+	if (is_empress && res_locked(dev, RESOURCE_OVERLAY)) {
 		/* Don't change the std from the mpeg device
 		   if overlay is active. */
 		return -EBUSY;
@@ -1664,7 +1667,7 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 	id = tvnorms[i].id;
 
 	mutex_lock(&dev->lock);
-	if (fh && res_check(fh, RESOURCE_OVERLAY)) {
+	if (!is_empress && res_check(priv, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock, flags);
 		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
@@ -1681,23 +1684,16 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 	mutex_unlock(&dev->lock);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+EXPORT_SYMBOL_GPL(saa7134_s_std);
 
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
+int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
 {
-	struct saa7134_fh *fh = priv;
-
-	return saa7134_s_std_internal(fh->dev, fh, id);
-}
-
-static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	*id = dev->tvnorm->id;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_g_std);
 
 static int saa7134_cropcap(struct file *file, void *priv,
 					struct v4l2_cropcap *cap)
@@ -1772,11 +1768,10 @@ static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *cr
 	return 0;
 }
 
-static int saa7134_g_tuner(struct file *file, void *priv,
+int saa7134_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *t)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	int n;
 
 	if (0 != t->index)
@@ -1803,12 +1798,12 @@ static int saa7134_g_tuner(struct file *file, void *priv,
 		t->signal = 0xffff;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_g_tuner);
 
-static int saa7134_s_tuner(struct file *file, void *priv,
+int saa7134_s_tuner(struct file *file, void *priv,
 					const struct v4l2_tuner *t)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	int rx, mode;
 
 	if (0 != t->index)
@@ -1824,12 +1819,12 @@ static int saa7134_s_tuner(struct file *file, void *priv,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_s_tuner);
 
-static int saa7134_g_frequency(struct file *file, void *priv,
+int saa7134_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (0 != f->tuner)
 		return -EINVAL;
@@ -1838,12 +1833,12 @@ static int saa7134_g_frequency(struct file *file, void *priv,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_g_frequency);
 
-static int saa7134_s_frequency(struct file *file, void *priv,
+int saa7134_s_frequency(struct file *file, void *priv,
 					const struct v4l2_frequency *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (0 != f->tuner)
 		return -EINVAL;
@@ -1855,6 +1850,7 @@ static int saa7134_s_frequency(struct file *file, void *priv,
 	mutex_unlock(&dev->lock);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_s_frequency);
 
 static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
@@ -2079,34 +2075,6 @@ static int radio_s_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int radio_enum_input(struct file *file, void *priv,
-					struct v4l2_input *i)
-{
-	if (i->index != 0)
-		return -EINVAL;
-
-	strcpy(i->name, "Radio");
-	i->type = V4L2_INPUT_TYPE_TUNER;
-
-	return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-	return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id norm)
-{
-	return 0;
-}
-
 static const struct v4l2_file_operations video_fops =
 {
 	.owner	  = THIS_MODULE,
@@ -2170,11 +2138,7 @@ static const struct v4l2_file_operations radio_fops = {
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_querycap	= saa7134_querycap,
 	.vidioc_g_tuner		= radio_g_tuner,
-	.vidioc_enum_input	= radio_enum_input,
 	.vidioc_s_tuner		= radio_s_tuner,
-	.vidioc_s_input		= radio_s_input,
-	.vidioc_s_std		= radio_s_std,
-	.vidioc_g_input		= radio_g_input,
 	.vidioc_g_frequency	= saa7134_g_frequency,
 	.vidioc_s_frequency	= saa7134_s_frequency,
 };
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index e0e5c70..3573aa2 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -767,7 +767,21 @@ extern unsigned int video_debug;
 extern struct video_device saa7134_video_template;
 extern struct video_device saa7134_radio_template;
 
-int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id id);
+int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id);
+int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id);
+int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i);
+int saa7134_g_input(struct file *file, void *priv, unsigned int *i);
+int saa7134_s_input(struct file *file, void *priv, unsigned int i);
+int saa7134_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *cap);
+int saa7134_g_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t);
+int saa7134_s_tuner(struct file *file, void *priv,
+					const struct v4l2_tuner *t);
+int saa7134_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f);
+int saa7134_s_frequency(struct file *file, void *priv,
+					const struct v4l2_frequency *f);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
 void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
-- 
1.7.10.4


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

* [RFC PATCH 10/16] saa7134: fix empress format compliance bugs.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (8 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 09/16] saa7134: cleanup radio/video/empress ioctl handling Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 11/16] saa7134: remove dev from saa7134_fh, use saa7134_fh for empress node Hans Verkuil
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Missing fields and a missing TRY_FMT implementation in saa6752hs.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa6752hs.c       |   58 ++++++++++++++++-----------
 drivers/media/pci/saa7134/saa7134-empress.c |   13 +++++-
 2 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
index 5813ce8..f29812e 100644
--- a/drivers/media/pci/saa7134/saa6752hs.c
+++ b/drivers/media/pci/saa7134/saa6752hs.c
@@ -570,10 +570,36 @@ static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
 	return 0;
 }
 
+static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	int dist_352, dist_480, dist_720;
+
+	f->code = V4L2_MBUS_FMT_FIXED;
+
+	dist_352 = abs(f->width - 352);
+	dist_480 = abs(f->width - 480);
+	dist_720 = abs(f->width - 720);
+	if (dist_720 < dist_480) {
+		f->width = 720;
+		f->height = 576;
+	} else if (dist_480 < dist_352) {
+		f->width = 480;
+		f->height = 576;
+	} else {
+		f->width = 352;
+		if (abs(f->height - 576) < abs(f->height - 288))
+			f->height = 576;
+		else
+			f->height = 288;
+	}
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
 static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
 {
 	struct saa6752hs_state *h = to_state(sd);
-	int dist_352, dist_480, dist_720;
 
 	if (f->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
@@ -590,30 +616,15 @@ static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm
 	  D1     | 720x576 | 720x480
 	*/
 
-	dist_352 = abs(f->width - 352);
-	dist_480 = abs(f->width - 480);
-	dist_720 = abs(f->width - 720);
-	if (dist_720 < dist_480) {
-		f->width = 720;
-		f->height = 576;
+	saa6752hs_try_mbus_fmt(sd, f);
+	if (f->width == 720)
 		h->video_format = SAA6752HS_VF_D1;
-	} else if (dist_480 < dist_352) {
-		f->width = 480;
-		f->height = 576;
+	else if (f->width == 480)
 		h->video_format = SAA6752HS_VF_2_3_D1;
-	} else {
-		f->width = 352;
-		if (abs(f->height - 576) <
-		    abs(f->height - 288)) {
-			f->height = 576;
-			h->video_format = SAA6752HS_VF_1_2_D1;
-		} else {
-			f->height = 288;
-			h->video_format = SAA6752HS_VF_SIF;
-		}
-	}
-	f->field = V4L2_FIELD_INTERLACED;
-	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	else if (f->height == 576)
+		h->video_format = SAA6752HS_VF_1_2_D1;
+	else
+		h->video_format = SAA6752HS_VF_SIF;
 	return 0;
 }
 
@@ -656,6 +667,7 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
 
 static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
 	.s_mbus_fmt = saa6752hs_s_mbus_fmt,
+	.try_mbus_fmt = saa6752hs_try_mbus_fmt,
 	.g_mbus_fmt = saa6752hs_g_mbus_fmt,
 };
 
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 0bc1eec..62e03f2 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -165,7 +165,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
 
 	strlcpy(f->description, "MPEG TS", sizeof(f->description));
 	f->pixelformat = V4L2_PIX_FMT_MPEG;
-
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
 	return 0;
 }
 
@@ -180,6 +180,8 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -196,6 +198,8 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -204,9 +208,16 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
 	struct saa7134_dev *dev = file->private_data;
+	struct v4l2_mbus_framefmt mbus_fmt;
+
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+	saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
+	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
-- 
1.7.10.4


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

* [RFC PATCH 11/16] saa7134: remove dev from saa7134_fh, use saa7134_fh for empress node
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (9 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 10/16] saa7134: fix empress format compliance bugs Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 12/16] saa7134: share resource management between normal and empress nodes Hans Verkuil
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Use the saa7134_fh struct for the empress video node as well, drop the dev
pointer from that struct since we can use drvdata for that.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-empress.c |   44 ++++++----
 drivers/media/pci/saa7134/saa7134-video.c   |  117 +++++++++++----------------
 drivers/media/pci/saa7134/saa7134.h         |    2 +-
 3 files changed, 77 insertions(+), 86 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 62e03f2..3669e89 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -86,6 +86,7 @@ static int ts_open(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
+	struct saa7134_fh *fh;
 	int err;
 
 	dprintk("open dev=%s\n", video_device_node_name(vdev));
@@ -95,12 +96,22 @@ static int ts_open(struct file *file)
 	if (atomic_read(&dev->empress_users))
 		goto done;
 
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	err = -ENOMEM;
+	if (NULL == fh)
+		goto done;
+
+	v4l2_fh_init(&fh->fh, vdev);
+	file->private_data = fh;
+	fh->is_empress = true;
+	v4l2_fh_add(&fh->fh);
+
 	/* Unmute audio */
 	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
 		saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
 
 	atomic_inc(&dev->empress_users);
-	file->private_data = dev;
 	err = 0;
 
 done:
@@ -110,7 +121,8 @@ done:
 
 static int ts_release(struct file *file)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
+	struct saa7134_fh *fh = file->private_data;
 
 	videobuf_stop(&dev->empress_tsq);
 	videobuf_mmap_free(&dev->empress_tsq);
@@ -124,13 +136,15 @@ static int ts_release(struct file *file)
 
 	atomic_dec(&dev->empress_users);
 
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	return 0;
 }
 
 static ssize_t
 ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (!dev->empress_started)
 		ts_init_encoder(dev);
@@ -143,7 +157,7 @@ ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 static unsigned int
 ts_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_poll_stream(file, &dev->empress_tsq, wait);
 }
@@ -152,7 +166,7 @@ ts_poll(struct file *file, struct poll_table_struct *wait)
 static int
 ts_mmap(struct file *file, struct vm_area_struct * vma)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_mmap_mapper(&dev->empress_tsq, vma);
 }
@@ -172,7 +186,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int empress_g_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_mbus_framefmt mbus_fmt;
 
 	saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
@@ -189,7 +203,7 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
 static int empress_s_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_mbus_framefmt mbus_fmt;
 
 	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
@@ -207,7 +221,7 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
 static int empress_try_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_mbus_framefmt mbus_fmt;
 
 	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
@@ -225,7 +239,7 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
 static int empress_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_reqbufs(&dev->empress_tsq, p);
 }
@@ -233,21 +247,21 @@ static int empress_reqbufs(struct file *file, void *priv,
 static int empress_querybuf(struct file *file, void *priv,
 					struct v4l2_buffer *b)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_querybuf(&dev->empress_tsq, b);
 }
 
 static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_qbuf(&dev->empress_tsq, b);
 }
 
 static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_dqbuf(&dev->empress_tsq, b,
 				file->f_flags & O_NONBLOCK);
@@ -256,7 +270,7 @@ static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 static int empress_streamon(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_streamon(&dev->empress_tsq);
 }
@@ -264,7 +278,7 @@ static int empress_streamon(struct file *file, void *priv,
 static int empress_streamoff(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	return videobuf_streamoff(&dev->empress_tsq);
 }
@@ -272,7 +286,7 @@ static int empress_streamoff(struct file *file, void *priv,
 static int empress_g_chip_ident(struct file *file, void *fh,
 	       struct v4l2_dbg_chip_ident *chip)
 {
-	struct saa7134_dev *dev = file->private_data;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 3471841..4965b88 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1090,8 +1090,7 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
 static struct videobuf_queue *saa7134_queue(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct videobuf_queue *q = NULL;
 
 	switch (vdev->vfl_type) {
@@ -1134,7 +1133,6 @@ static int video_open(struct file *file)
 
 	v4l2_fh_init(&fh->fh, vdev);
 	file->private_data = fh;
-	fh->dev      = dev;
 
 	if (vdev->vfl_type == VFL_TYPE_RADIO) {
 		/* switch to radio mode */
@@ -1153,17 +1151,18 @@ static ssize_t
 video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
 	struct video_device *vdev = video_devdata(file);
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh = file->private_data;
 
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_GRABBER:
-		if (res_locked(fh->dev,RESOURCE_VIDEO))
+		if (res_locked(dev, RESOURCE_VIDEO))
 			return -EBUSY;
 		return videobuf_read_one(saa7134_queue(file),
 					 data, count, ppos,
 					 file->f_flags & O_NONBLOCK);
 	case VFL_TYPE_VBI:
-		if (!res_get(fh->dev,fh,RESOURCE_VBI))
+		if (!res_get(dev, fh, RESOURCE_VBI))
 			return -EBUSY;
 		return videobuf_read_stream(saa7134_queue(file),
 					    data, count, ppos, 1,
@@ -1179,15 +1178,15 @@ static unsigned int
 video_poll(struct file *file, struct poll_table_struct *wait)
 {
 	struct video_device *vdev = video_devdata(file);
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
 	struct videobuf_buffer *buf = NULL;
 	unsigned int rc = 0;
 
 	if (vdev->vfl_type == VFL_TYPE_VBI)
 		return videobuf_poll_stream(file, &dev->vbi, wait);
 
-	if (res_check(fh,RESOURCE_VIDEO)) {
+	if (res_check(fh, RESOURCE_VIDEO)) {
 		mutex_lock(&dev->cap.vb_lock);
 		if (!list_empty(&dev->cap.stream))
 			buf = list_entry(dev->cap.stream.next, struct videobuf_buffer, stream);
@@ -1195,7 +1194,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
 		mutex_lock(&dev->cap.vb_lock);
 		if (UNSET == dev->cap.read_off) {
 			/* need to capture a new frame */
-			if (res_locked(fh->dev,RESOURCE_VIDEO))
+			if (res_locked(dev, RESOURCE_VIDEO))
 				goto err;
 			if (0 != dev->cap.ops->buf_prepare(&dev->cap,
 					dev->cap.read_buf, dev->cap.field))
@@ -1224,8 +1223,8 @@ err:
 static int video_release(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct saa7134_fh  *fh  = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
+	struct saa7134_fh *fh = file->private_data;
 	struct saa6588_command cmd;
 	unsigned long flags;
 
@@ -1236,13 +1235,13 @@ static int video_release(struct file *file)
 		spin_lock_irqsave(&dev->slock,flags);
 		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock,flags);
-		res_free(dev,fh,RESOURCE_OVERLAY);
+		res_free(dev, fh, RESOURCE_OVERLAY);
 	}
 
 	/* stop video capture */
 	if (res_check(fh, RESOURCE_VIDEO)) {
 		videobuf_streamoff(&dev->cap);
-		res_free(dev,fh,RESOURCE_VIDEO);
+		res_free(dev, fh, RESOURCE_VIDEO);
 		videobuf_mmap_free(&dev->cap);
 	}
 	if (dev->cap.read_buf) {
@@ -1253,7 +1252,7 @@ static int video_release(struct file *file)
 	/* stop vbi capture */
 	if (res_check(fh, RESOURCE_VBI)) {
 		videobuf_stop(&dev->vbi);
-		res_free(dev,fh,RESOURCE_VBI);
+		res_free(dev, fh, RESOURCE_VBI);
 		videobuf_mmap_free(&dev->vbi);
 	}
 
@@ -1282,8 +1281,7 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma)
 static ssize_t radio_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
-	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa6588_command cmd;
 
 	cmd.block_count = count/3;
@@ -1298,8 +1296,7 @@ static ssize_t radio_read(struct file *file, char __user *data,
 
 static unsigned int radio_poll(struct file *file, poll_table *wait)
 {
-	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa6588_command cmd;
 
 	cmd.instance = file;
@@ -1315,8 +1312,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
 static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
 						struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_tvnorm *norm = dev->tvnorm;
 
 	memset(&f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
@@ -1336,8 +1332,7 @@ static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
 static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	f->fmt.pix.width        = dev->width;
 	f->fmt.pix.height       = dev->height;
@@ -1355,8 +1350,7 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
 static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_clip *clips = f->fmt.win.clips;
 	u32 clipcount = f->fmt.win.clipcount;
 	int err = 0;
@@ -1388,8 +1382,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
 static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
 						struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_format *fmt;
 	enum v4l2_field field;
 	unsigned int maxw, maxh;
@@ -1440,8 +1433,7 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
 static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
 						struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (saa7134_no_overlay > 0) {
 		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
@@ -1456,8 +1448,7 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
 static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
 
 	err = saa7134_try_fmt_vid_cap(file, priv, f);
@@ -1474,8 +1465,7 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
 static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
 	unsigned long flags;
 
@@ -1500,7 +1490,7 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
 		return -EFAULT;
 	}
 
-	if (res_check(fh, RESOURCE_OVERLAY)) {
+	if (res_check(priv, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock, flags);
 		stop_preview(dev);
 		start_preview(dev);
@@ -1571,6 +1561,7 @@ int saa7134_querycap(struct file *file, void *priv,
 {
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct video_device *vdev = video_devdata(file);
+	struct saa7134_fh *fh = priv;
 	u32 radio_caps, video_caps, vbi_caps;
 
 	unsigned int tuner_type = dev->tuner_type;
@@ -1589,8 +1580,7 @@ int saa7134_querycap(struct file *file, void *priv,
 		radio_caps |= V4L2_CAP_RDS_CAPTURE;
 
 	video_caps = V4L2_CAP_VIDEO_CAPTURE;
-	/* For the empress video node priv == dev */
-	if (saa7134_no_overlay <= 0 && priv != dev)
+	if (saa7134_no_overlay <= 0 && !fh->is_empress)
 		video_caps |= V4L2_CAP_VIDEO_OVERLAY;
 
 	vbi_caps = V4L2_CAP_VBI_CAPTURE;
@@ -1621,13 +1611,12 @@ EXPORT_SYMBOL_GPL(saa7134_querycap);
 int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct saa7134_dev *dev = video_drvdata(file);
-	/* For the empress video node priv == dev */
-	bool is_empress = priv == dev;
+	struct saa7134_fh *fh = priv;
 	unsigned long flags;
 	unsigned int i;
 	v4l2_std_id fixup;
 
-	if (is_empress && res_locked(dev, RESOURCE_OVERLAY)) {
+	if (fh->is_empress && res_locked(dev, RESOURCE_OVERLAY)) {
 		/* Don't change the std from the mpeg device
 		   if overlay is active. */
 		return -EBUSY;
@@ -1667,7 +1656,7 @@ int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
 	id = tvnorms[i].id;
 
 	mutex_lock(&dev->lock);
-	if (!is_empress && res_check(priv, RESOURCE_OVERLAY)) {
+	if (!fh->is_empress && res_check(fh, RESOURCE_OVERLAY)) {
 		spin_lock_irqsave(&dev->slock, flags);
 		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
@@ -1698,8 +1687,7 @@ EXPORT_SYMBOL_GPL(saa7134_g_std);
 static int saa7134_cropcap(struct file *file, void *priv,
 					struct v4l2_cropcap *cap)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
@@ -1721,8 +1709,7 @@ static int saa7134_cropcap(struct file *file, void *priv,
 
 static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
 {
-	struct saa7134_fh *fh = f;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 	    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
@@ -1733,8 +1720,7 @@ static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
 static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 {
-	struct saa7134_fh *fh = f;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_rect *b = &dev->crop_bounds;
 	struct v4l2_rect *c = &dev->crop_current;
 
@@ -1746,9 +1732,9 @@ static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *cr
 	if (crop->c.width < 0)
 		return -EINVAL;
 
-	if (res_locked(fh->dev, RESOURCE_OVERLAY))
+	if (res_locked(dev, RESOURCE_OVERLAY))
 		return -EBUSY;
-	if (res_locked(fh->dev, RESOURCE_VIDEO))
+	if (res_locked(dev, RESOURCE_VIDEO))
 		return -EBUSY;
 
 	*c = crop->c;
@@ -1888,8 +1874,7 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
 static int saa7134_g_fbuf(struct file *file, void *f,
 				struct v4l2_framebuffer *fb)
 {
-	struct saa7134_fh *fh = f;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	*fb = dev->ovbuf;
 	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
@@ -1900,8 +1885,7 @@ static int saa7134_g_fbuf(struct file *file, void *f,
 static int saa7134_s_fbuf(struct file *file, void *f,
 					const struct v4l2_framebuffer *fb)
 {
-	struct saa7134_fh *fh = f;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_format *fmt;
 
 	if (!capable(CAP_SYS_ADMIN) &&
@@ -1922,10 +1906,9 @@ static int saa7134_s_fbuf(struct file *file, void *f,
 	return 0;
 }
 
-static int saa7134_overlay(struct file *file, void *f, unsigned int on)
+static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
 {
-	struct saa7134_fh *fh = f;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	unsigned long flags;
 
 	if (on) {
@@ -1934,19 +1917,19 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on)
 			return -EINVAL;
 		}
 
-		if (!res_get(dev, fh, RESOURCE_OVERLAY))
+		if (!res_get(dev, priv, RESOURCE_OVERLAY))
 			return -EBUSY;
 		spin_lock_irqsave(&dev->slock, flags);
 		start_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
 	}
 	if (!on) {
-		if (!res_check(fh, RESOURCE_OVERLAY))
+		if (!res_check(priv, RESOURCE_OVERLAY))
 			return -EINVAL;
 		spin_lock_irqsave(&dev->slock, flags);
 		stop_preview(dev);
 		spin_unlock_irqrestore(&dev->slock, flags);
-		res_free(dev, fh, RESOURCE_OVERLAY);
+		res_free(dev, priv, RESOURCE_OVERLAY);
 	}
 	return 0;
 }
@@ -1977,11 +1960,10 @@ static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 static int saa7134_streamon(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 	int res = saa7134_resource(file);
 
-	if (!res_get(dev, fh, res))
+	if (!res_get(dev, priv, res))
 		return -EBUSY;
 
 	/* The SAA7134 has a 1K FIFO; the datasheet suggests that when
@@ -2001,9 +1983,8 @@ static int saa7134_streamon(struct file *file, void *priv,
 static int saa7134_streamoff(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
+	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
 	int res = saa7134_resource(file);
 
 	pm_qos_remove_request(&dev->qos_request);
@@ -2011,7 +1992,7 @@ static int saa7134_streamoff(struct file *file, void *priv,
 	err = videobuf_streamoff(saa7134_queue(file));
 	if (err < 0)
 		return err;
-	res_free(dev, fh, res);
+	res_free(dev, priv, res);
 	return 0;
 }
 
@@ -2019,8 +2000,7 @@ static int saa7134_streamoff(struct file *file, void *priv,
 static int vidioc_g_register (struct file *file, void *priv,
 			      struct v4l2_dbg_register *reg)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
@@ -2032,8 +2012,7 @@ static int vidioc_g_register (struct file *file, void *priv,
 static int vidioc_s_register (struct file *file, void *priv,
 				const struct v4l2_dbg_register *reg)
 {
-	struct saa7134_fh *fh = priv;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
@@ -2045,8 +2024,7 @@ static int vidioc_s_register (struct file *file, void *priv,
 static int radio_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *t)
 {
-	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -2065,8 +2043,7 @@ static int radio_g_tuner(struct file *file, void *priv,
 static int radio_s_tuner(struct file *file, void *priv,
 					const struct v4l2_tuner *t)
 {
-	struct saa7134_fh *fh = file->private_data;
-	struct saa7134_dev *dev = fh->dev;
+	struct saa7134_dev *dev = video_drvdata(file);
 
 	if (0 != t->index)
 		return -EINVAL;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 3573aa2..d7bef5e 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -476,7 +476,7 @@ struct saa7134_dmaqueue {
 /* video filehandle status */
 struct saa7134_fh {
 	struct v4l2_fh             fh;
-	struct saa7134_dev         *dev;
+	bool			   is_empress;
 	unsigned int               resources;
 };
 
-- 
1.7.10.4


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

* [RFC PATCH 12/16] saa7134: share resource management between normal and empress nodes.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (10 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 11/16] saa7134: remove dev from saa7134_fh, use saa7134_fh for empress node Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 13/16] saa7134: add support for control events Hans Verkuil
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The empress video node can share resource management with the normal
video nodes, thus allowing for code sharing and making the empress node
non-exclusive.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-empress.c |   98 ++++++---------------------
 drivers/media/pci/saa7134/saa7134-video.c   |   43 ++++++------
 drivers/media/pci/saa7134/saa7134.h         |   22 +++++-
 3 files changed, 62 insertions(+), 101 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 3669e89..66a7ddc 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -87,20 +87,11 @@ static int ts_open(struct file *file)
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh;
-	int err;
-
-	dprintk("open dev=%s\n", video_device_node_name(vdev));
-	err = -EBUSY;
-	if (!mutex_trylock(&dev->empress_tsq.vb_lock))
-		return err;
-	if (atomic_read(&dev->empress_users))
-		goto done;
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	err = -ENOMEM;
 	if (NULL == fh)
-		goto done;
+		return -ENOMEM;
 
 	v4l2_fh_init(&fh->fh, vdev);
 	file->private_data = fh;
@@ -111,12 +102,7 @@ static int ts_open(struct file *file)
 	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
 		saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
 
-	atomic_inc(&dev->empress_users);
-	err = 0;
-
-done:
-	mutex_unlock(&dev->empress_tsq.vb_lock);
-	return err;
+	return 0;
 }
 
 static int ts_release(struct file *file)
@@ -124,17 +110,17 @@ static int ts_release(struct file *file)
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh = file->private_data;
 
-	videobuf_stop(&dev->empress_tsq);
-	videobuf_mmap_free(&dev->empress_tsq);
+	if (res_check(fh, RESOURCE_EMPRESS)) {
+		videobuf_stop(&dev->empress_tsq);
+		videobuf_mmap_free(&dev->empress_tsq);
 
-	/* stop the encoder */
-	ts_reset_encoder(dev);
+		/* stop the encoder */
+		ts_reset_encoder(dev);
 
-	/* Mute audio */
-	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
-		saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
-
-	atomic_dec(&dev->empress_users);
+		/* Mute audio */
+		saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
+				saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
+	}
 
 	v4l2_fh_del(&fh->fh);
 	v4l2_fh_exit(&fh->fh);
@@ -146,6 +132,8 @@ ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
 	struct saa7134_dev *dev = video_drvdata(file);
 
+	if (res_locked(dev, RESOURCE_EMPRESS))
+		return -EBUSY;
 	if (!dev->empress_started)
 		ts_init_encoder(dev);
 
@@ -236,53 +224,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int empress_reqbufs(struct file *file, void *priv,
-					struct v4l2_requestbuffers *p)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_reqbufs(&dev->empress_tsq, p);
-}
-
-static int empress_querybuf(struct file *file, void *priv,
-					struct v4l2_buffer *b)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_querybuf(&dev->empress_tsq, b);
-}
-
-static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_qbuf(&dev->empress_tsq, b);
-}
-
-static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_dqbuf(&dev->empress_tsq, b,
-				file->f_flags & O_NONBLOCK);
-}
-
-static int empress_streamon(struct file *file, void *priv,
-					enum v4l2_buf_type type)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_streamon(&dev->empress_tsq);
-}
-
-static int empress_streamoff(struct file *file, void *priv,
-					enum v4l2_buf_type type)
-{
-	struct saa7134_dev *dev = video_drvdata(file);
-
-	return videobuf_streamoff(&dev->empress_tsq);
-}
-
 static int empress_g_chip_ident(struct file *file, void *fh,
 	       struct v4l2_dbg_chip_ident *chip)
 {
@@ -315,12 +256,12 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
 	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap		= empress_g_fmt_vid_cap,
-	.vidioc_reqbufs			= empress_reqbufs,
-	.vidioc_querybuf		= empress_querybuf,
-	.vidioc_qbuf			= empress_qbuf,
-	.vidioc_dqbuf			= empress_dqbuf,
-	.vidioc_streamon		= empress_streamon,
-	.vidioc_streamoff		= empress_streamoff,
+	.vidioc_reqbufs			= saa7134_reqbufs,
+	.vidioc_querybuf		= saa7134_querybuf,
+	.vidioc_qbuf			= saa7134_qbuf,
+	.vidioc_dqbuf			= saa7134_dqbuf,
+	.vidioc_streamon		= saa7134_streamon,
+	.vidioc_streamoff		= saa7134_streamoff,
 	.vidioc_g_frequency		= saa7134_g_frequency,
 	.vidioc_s_frequency		= saa7134_s_frequency,
 	.vidioc_g_tuner			= saa7134_g_tuner,
@@ -393,6 +334,7 @@ static int empress_init(struct saa7134_dev *dev)
 	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
 		 "%s empress (%s)", dev->name,
 		 saa7134_boards[dev->board].name);
+	set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
 	v4l2_ctrl_handler_init(hdl, 21);
 	v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
 	if (dev->empress_sd)
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 4965b88..a35e137 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -403,16 +403,6 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int
 	return 1;
 }
 
-static int res_check(struct saa7134_fh *fh, unsigned int bit)
-{
-	return (fh->resources & bit);
-}
-
-static int res_locked(struct saa7134_dev *dev, unsigned int bit)
-{
-	return (dev->resources & bit);
-}
-
 static
 void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
 {
@@ -1091,11 +1081,12 @@ static struct videobuf_queue *saa7134_queue(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
+	struct saa7134_fh *fh = file->private_data;
 	struct videobuf_queue *q = NULL;
 
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_GRABBER:
-		q = &dev->cap;
+		q = fh->is_empress ? &dev->empress_tsq : &dev->cap;
 		break;
 	case VFL_TYPE_VBI:
 		q = &dev->vbi;
@@ -1109,9 +1100,10 @@ static struct videobuf_queue *saa7134_queue(struct file *file)
 static int saa7134_resource(struct file *file)
 {
 	struct video_device *vdev = video_devdata(file);
+	struct saa7134_fh *fh = file->private_data;
 
 	if (vdev->vfl_type == VFL_TYPE_GRABBER)
-		return RESOURCE_VIDEO;
+		return fh->is_empress ? RESOURCE_EMPRESS : RESOURCE_VIDEO;
 
 	if (vdev->vfl_type == VFL_TYPE_VBI)
 		return RESOURCE_VBI;
@@ -1934,30 +1926,34 @@ static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
 	return 0;
 }
 
-static int saa7134_reqbufs(struct file *file, void *priv,
+int saa7134_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
 {
 	return videobuf_reqbufs(saa7134_queue(file), p);
 }
+EXPORT_SYMBOL_GPL(saa7134_reqbufs);
 
-static int saa7134_querybuf(struct file *file, void *priv,
+int saa7134_querybuf(struct file *file, void *priv,
 					struct v4l2_buffer *b)
 {
 	return videobuf_querybuf(saa7134_queue(file), b);
 }
+EXPORT_SYMBOL_GPL(saa7134_querybuf);
 
-static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	return videobuf_qbuf(saa7134_queue(file), b);
 }
+EXPORT_SYMBOL_GPL(saa7134_qbuf);
 
-static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	return videobuf_dqbuf(saa7134_queue(file), b,
 				file->f_flags & O_NONBLOCK);
 }
+EXPORT_SYMBOL_GPL(saa7134_dqbuf);
 
-static int saa7134_streamon(struct file *file, void *priv,
+int saa7134_streamon(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
 	struct saa7134_dev *dev = video_drvdata(file);
@@ -1973,21 +1969,23 @@ static int saa7134_streamon(struct file *file, void *priv,
 	 * Unfortunately, I lack register-level documentation to check the
 	 * Linux FIFO setup and confirm the perfect value.
 	 */
-	pm_qos_add_request(&dev->qos_request,
-			   PM_QOS_CPU_DMA_LATENCY,
-			   20);
+	if (res != RESOURCE_EMPRESS)
+		pm_qos_add_request(&dev->qos_request,
+			   PM_QOS_CPU_DMA_LATENCY, 20);
 
 	return videobuf_streamon(saa7134_queue(file));
 }
+EXPORT_SYMBOL_GPL(saa7134_streamon);
 
-static int saa7134_streamoff(struct file *file, void *priv,
+int saa7134_streamoff(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
 	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
 	int res = saa7134_resource(file);
 
-	pm_qos_remove_request(&dev->qos_request);
+	if (res != RESOURCE_EMPRESS)
+		pm_qos_remove_request(&dev->qos_request);
 
 	err = videobuf_streamoff(saa7134_queue(file));
 	if (err < 0)
@@ -1995,6 +1993,7 @@ static int saa7134_streamoff(struct file *file, void *priv,
 	res_free(dev, priv, res);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_streamoff);
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register (struct file *file, void *priv,
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index d7bef5e..2474e84 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -422,6 +422,7 @@ struct saa7134_board {
 #define RESOURCE_OVERLAY       1
 #define RESOURCE_VIDEO         2
 #define RESOURCE_VBI           4
+#define RESOURCE_EMPRESS       8
 
 #define INTERLACE_AUTO         0
 #define INTERLACE_ON           1
@@ -644,7 +645,6 @@ struct saa7134_dev {
 	struct video_device        *empress_dev;
 	struct v4l2_subdev	   *empress_sd;
 	struct videobuf_queue      empress_tsq;
-	atomic_t 		   empress_users;
 	struct work_struct         empress_workqueue;
 	int                        empress_started;
 	struct v4l2_ctrl_handler   empress_ctrl_handler;
@@ -705,6 +705,16 @@ struct saa7134_dev {
 	_rc;								\
 })
 
+static inline int res_check(struct saa7134_fh *fh, unsigned int bit)
+{
+	return fh->resources & bit;
+}
+
+static inline int res_locked(struct saa7134_dev *dev, unsigned int bit)
+{
+	return dev->resources & bit;
+}
+
 /* ----------------------------------------------------------- */
 /* saa7134-core.c                                              */
 
@@ -782,6 +792,16 @@ int saa7134_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f);
 int saa7134_s_frequency(struct file *file, void *priv,
 					const struct v4l2_frequency *f);
+int saa7134_reqbufs(struct file *file, void *priv,
+					struct v4l2_requestbuffers *p);
+int saa7134_querybuf(struct file *file, void *priv,
+					struct v4l2_buffer *b);
+int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+int saa7134_streamon(struct file *file, void *priv,
+					enum v4l2_buf_type type);
+int saa7134_streamoff(struct file *file, void *priv,
+					enum v4l2_buf_type type);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
 void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
-- 
1.7.10.4


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

* [RFC PATCH 13/16] saa7134: add support for control events.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (11 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 12/16] saa7134: share resource management between normal and empress nodes Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 14/16] saa7134: use V4L2_IN_ST_NO_SIGNAL instead of NO_SYNC Hans Verkuil
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa7134-empress.c |   19 ++++++++++++----
 drivers/media/pci/saa7134/saa7134-video.c   |   32 +++++++++++++++++++--------
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 66a7ddc..3d24408 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -23,13 +23,14 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
 #include <media/saa6752hs.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-chip-ident.h>
 
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
 /* ------------------------------------------------------------------ */
 
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -145,9 +146,16 @@ ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 static unsigned int
 ts_poll(struct file *file, struct poll_table_struct *wait)
 {
+	unsigned long req_events = poll_requested_events(wait);
 	struct saa7134_dev *dev = video_drvdata(file);
+	struct saa7134_fh *fh = file->private_data;
+	unsigned int rc = 0;
 
-	return videobuf_poll_stream(file, &dev->empress_tsq, wait);
+	if (v4l2_event_pending(&fh->fh))
+		rc = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
+	return rc | videobuf_poll_stream(file, &dev->empress_tsq, wait);
 }
 
 
@@ -272,6 +280,9 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
 	.vidioc_g_chip_ident 		= empress_g_chip_ident,
 	.vidioc_s_std			= saa7134_s_std,
 	.vidioc_g_std			= saa7134_g_std,
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index a35e137..fa6cc17 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -27,11 +27,13 @@
 #include <linux/slab.h>
 #include <linux/sort.h>
 
-#include "saa7134-reg.h"
-#include "saa7134.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
 #include <media/saa6588.h>
 
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
 /* ------------------------------------------------------------------ */
 
 unsigned int video_debug;
@@ -1169,14 +1171,20 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 static unsigned int
 video_poll(struct file *file, struct poll_table_struct *wait)
 {
+	unsigned long req_events = poll_requested_events(wait);
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh = file->private_data;
 	struct videobuf_buffer *buf = NULL;
 	unsigned int rc = 0;
 
+	if (v4l2_event_pending(&fh->fh))
+		rc = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
+
 	if (vdev->vfl_type == VFL_TYPE_VBI)
-		return videobuf_poll_stream(file, &dev->vbi, wait);
+		return rc | videobuf_poll_stream(file, &dev->vbi, wait);
 
 	if (res_check(fh, RESOURCE_VIDEO)) {
 		mutex_lock(&dev->cap.vb_lock);
@@ -1201,15 +1209,14 @@ video_poll(struct file *file, struct poll_table_struct *wait)
 		goto err;
 
 	poll_wait(file, &buf->done, wait);
-	if (buf->state == VIDEOBUF_DONE ||
-	    buf->state == VIDEOBUF_ERROR)
-		rc = POLLIN|POLLRDNORM;
+	if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR)
+		rc |= POLLIN | POLLRDNORM;
 	mutex_unlock(&dev->cap.vb_lock);
 	return rc;
 
 err:
 	mutex_unlock(&dev->cap.vb_lock);
-	return POLLERR;
+	return rc | POLLERR;
 }
 
 static int video_release(struct file *file)
@@ -1290,13 +1297,14 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
 {
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa6588_command cmd;
+	unsigned int rc = v4l2_ctrl_poll(file, wait);
 
 	cmd.instance = file;
 	cmd.event_list = wait;
-	cmd.result = -ENODEV;
+	cmd.result = 0;
 	saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
 
-	return cmd.result;
+	return rc | cmd.result;
 }
 
 /* ------------------------------------------------------------------ */
@@ -2100,6 +2108,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_g_register              = vidioc_g_register,
 	.vidioc_s_register              = vidioc_s_register,
 #endif
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
 static const struct v4l2_file_operations radio_fops = {
@@ -2117,6 +2128,9 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_s_tuner		= radio_s_tuner,
 	.vidioc_g_frequency	= saa7134_g_frequency,
 	.vidioc_s_frequency	= saa7134_s_frequency,
+	.vidioc_log_status	= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event	= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 /* ----------------------------------------------------------- */
-- 
1.7.10.4


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

* [RFC PATCH 14/16] saa7134: use V4L2_IN_ST_NO_SIGNAL instead of NO_SYNC
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (12 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 13/16] saa7134: add support for control events Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 15/16] saa6752hs: drop compat control code Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 16/16] saa6752hs: move to media/i2c Hans Verkuil
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

NO_SYNC was meant for DVB and shouldn't be used anymore.

In this case NO_SIGNAL is a good alternative.

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

diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index fa6cc17..44b7ed2 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1523,7 +1523,7 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)
 		if (0 != (v1 & 0x40))
 			i->status |= V4L2_IN_ST_NO_H_LOCK;
 		if (0 != (v2 & 0x40))
-			i->status |= V4L2_IN_ST_NO_SYNC;
+			i->status |= V4L2_IN_ST_NO_SIGNAL;
 		if (0 != (v2 & 0x0e))
 			i->status |= V4L2_IN_ST_MACROVISION;
 	}
-- 
1.7.10.4


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

* [RFC PATCH 15/16] saa6752hs: drop compat control code.
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (13 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 14/16] saa7134: use V4L2_IN_ST_NO_SIGNAL instead of NO_SYNC Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  2013-06-02 10:56 ` [RFC PATCH 16/16] saa6752hs: move to media/i2c Hans Verkuil
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The saa7134 driver is now converted to the control framework, so drop the
control compat code in saa6752hs.c.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/saa7134/saa6752hs.c |   20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
index f29812e..b14f5f6 100644
--- a/drivers/media/pci/saa7134/saa6752hs.c
+++ b/drivers/media/pci/saa7134/saa6752hs.c
@@ -33,12 +33,13 @@
 #include <linux/i2c.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
 
 #define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
 #define MPEG_VIDEO_MAX_BITRATE_MAX     27000
@@ -126,7 +127,7 @@ static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
 
 /* ---------------------------------------------------------------------- */
 
-static u8 PAT[] = {
+static const u8 PAT[] = {
 	0xc2, /* i2c register */
 	0x00, /* table number for encoder */
 
@@ -152,7 +153,7 @@ static u8 PAT[] = {
 	0x00, 0x00, 0x00, 0x00 /* CRC32 */
 };
 
-static u8 PMT[] = {
+static const u8 PMT[] = {
 	0xc2, /* i2c register */
 	0x01, /* table number for encoder */
 
@@ -181,7 +182,7 @@ static u8 PMT[] = {
 	0x00, 0x00, 0x00, 0x00 /* CRC32 */
 };
 
-static u8 PMT_AC3[] = {
+static const u8 PMT_AC3[] = {
 	0xc2, /* i2c register */
 	0x01, /* table number for encoder(1) */
 	0x47, /* sync */
@@ -214,7 +215,7 @@ static u8 PMT_AC3[] = {
 	0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
 };
 
-static struct saa6752hs_mpeg_params param_defaults =
+static const struct saa6752hs_mpeg_params param_defaults =
 {
 	.ts_pid_pmt      = 16,
 	.ts_pid_video    = 260,
@@ -655,13 +656,6 @@ static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = {
 static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
 	.g_chip_ident = saa6752hs_g_chip_ident,
 	.init = saa6752hs_init,
-	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
-	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
-	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
-	.g_ctrl = v4l2_subdev_g_ctrl,
-	.s_ctrl = v4l2_subdev_s_ctrl,
-	.queryctrl = v4l2_subdev_queryctrl,
-	.querymenu = v4l2_subdev_querymenu,
 	.s_std = saa6752hs_s_std,
 };
 
-- 
1.7.10.4


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

* [RFC PATCH 16/16] saa6752hs: move to media/i2c
  2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
                   ` (14 preceding siblings ...)
  2013-06-02 10:56 ` [RFC PATCH 15/16] saa6752hs: drop compat control code Hans Verkuil
@ 2013-06-02 10:56 ` Hans Verkuil
  15 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2013-06-02 10:56 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

This driver is independent from saa7134, so there is no reason why this
shouldn't be in media/i2c like all other i2c media drivers.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/Kconfig             |   14 +-
 drivers/media/i2c/Makefile            |    1 +
 drivers/media/i2c/saa6752hs.c         |  805 +++++++++++++++++++++++++++++++++
 drivers/media/pci/saa7134/Kconfig     |    1 +
 drivers/media/pci/saa7134/Makefile    |    2 +-
 drivers/media/pci/saa7134/saa6752hs.c |  805 ---------------------------------
 6 files changed, 821 insertions(+), 807 deletions(-)
 create mode 100644 drivers/media/i2c/saa6752hs.c
 delete mode 100644 drivers/media/pci/saa7134/saa6752hs.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index f981d50..fa641c3 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -605,7 +605,19 @@ config VIDEO_UPD64083
 	  To compile this driver as a module, choose M here: the
 	  module will be called upd64083.
 
-comment "Miscelaneous helper chips"
+comment "Audio/Video compression chips"
+
+config VIDEO_SAA6752HS
+	tristate "Philips SAA6752HS MPEG-2 Audio/Video Encoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA6752HS MPEG-2 video and MPEG-audio/AC-3
+	  audio encoder with multiplexer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa6752hs.
+
+comment "Miscellaneous helper chips"
 
 config VIDEO_THS7303
 	tristate "THS7303/53 Video Amplifier"
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 720f42d..11b7664 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
new file mode 100644
index 0000000..b14f5f6
--- /dev/null
+++ b/drivers/media/i2c/saa6752hs.c
@@ -0,0 +1,805 @@
+ /*
+    saa6752hs - i2c-driver for the saa6752hs by Philips
+
+    Copyright (C) 2004 Andrew de Quincey
+
+    AC-3 support:
+
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License vs published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
+#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
+#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
+
+MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+enum saa6752hs_videoformat {
+	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
+	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
+	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
+	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
+	SAA6752HS_VF_UNKNOWN,
+};
+
+struct saa6752hs_mpeg_params {
+	/* transport streams */
+	__u16				ts_pid_pmt;
+	__u16				ts_pid_audio;
+	__u16				ts_pid_video;
+	__u16				ts_pid_pcr;
+
+	/* audio */
+	enum v4l2_mpeg_audio_encoding    au_encoding;
+	enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
+	enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
+
+	/* video */
+	enum v4l2_mpeg_video_aspect	vi_aspect;
+	enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+	__u32 				vi_bitrate;
+	__u32 				vi_bitrate_peak;
+};
+
+static const struct v4l2_format v4l2_format_table[] =
+{
+	[SAA6752HS_VF_D1] =
+		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
+	[SAA6752HS_VF_2_3_D1] =
+		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
+	[SAA6752HS_VF_1_2_D1] =
+		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
+	[SAA6752HS_VF_SIF] =
+		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
+	[SAA6752HS_VF_UNKNOWN] =
+		{ .fmt = { .pix = { .width = 0, .height = 0}}},
+};
+
+struct saa6752hs_state {
+	struct v4l2_subdev            sd;
+	struct v4l2_ctrl_handler      hdl;
+	struct { /* video bitrate mode control cluster */
+		struct v4l2_ctrl *video_bitrate_mode;
+		struct v4l2_ctrl *video_bitrate;
+		struct v4l2_ctrl *video_bitrate_peak;
+	};
+	int 			      chip;
+	u32 			      revision;
+	int 			      has_ac3;
+	struct saa6752hs_mpeg_params  params;
+	enum saa6752hs_videoformat    video_format;
+	v4l2_std_id                   standard;
+};
+
+enum saa6752hs_command {
+	SAA6752HS_COMMAND_RESET = 0,
+	SAA6752HS_COMMAND_STOP = 1,
+	SAA6752HS_COMMAND_START = 2,
+	SAA6752HS_COMMAND_PAUSE = 3,
+	SAA6752HS_COMMAND_RECONFIGURE = 4,
+	SAA6752HS_COMMAND_SLEEP = 5,
+	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
+
+	SAA6752HS_COMMAND_MAX
+};
+
+static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa6752hs_state, sd);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const u8 PAT[] = {
+	0xc2, /* i2c register */
+	0x00, /* table number for encoder */
+
+	0x47, /* sync */
+	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x00, /* tid(0) */
+	0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
+
+	0x00, 0x01, /* transport_stream_id(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xe0, 0x00, /* PMT PID */
+
+	0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static const u8 PMT[] = {
+	0xc2, /* i2c register */
+	0x01, /* table number for encoder */
+
+	0x47, /* sync */
+	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x02, /* tid(2) */
+	0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0xe0, 0x00, /* PCR_PID */
+
+	0xf0, 0x00, /* program_info_length(0) */
+
+	0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+	0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
+
+	0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static const u8 PMT_AC3[] = {
+	0xc2, /* i2c register */
+	0x01, /* table number for encoder(1) */
+	0x47, /* sync */
+
+	0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
+	0x10, /* PMT PID (0x0010) */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x02, /* TID (2) */
+	0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0xe1, 0x04, /* PCR_PID (0x0104) */
+
+	0xf0, 0x00, /* program_info_length(0) */
+
+	0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+	0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
+	0x6a, /* AC3 */
+	0x01, /* Descriptor_length(1) */
+	0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
+
+	0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
+};
+
+static const struct saa6752hs_mpeg_params param_defaults =
+{
+	.ts_pid_pmt      = 16,
+	.ts_pid_video    = 260,
+	.ts_pid_audio    = 256,
+	.ts_pid_pcr      = 259,
+
+	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.vi_bitrate      = 4000,
+	.vi_bitrate_peak = 6000,
+	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+	.au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6752hs_chip_command(struct i2c_client *client,
+				  enum saa6752hs_command command)
+{
+	unsigned char buf[3];
+	unsigned long timeout;
+	int status = 0;
+
+	/* execute the command */
+	switch(command) {
+	case SAA6752HS_COMMAND_RESET:
+		buf[0] = 0x00;
+		break;
+
+	case SAA6752HS_COMMAND_STOP:
+		buf[0] = 0x03;
+		break;
+
+	case SAA6752HS_COMMAND_START:
+		buf[0] = 0x02;
+		break;
+
+	case SAA6752HS_COMMAND_PAUSE:
+		buf[0] = 0x04;
+		break;
+
+	case SAA6752HS_COMMAND_RECONFIGURE:
+		buf[0] = 0x05;
+		break;
+
+	case SAA6752HS_COMMAND_SLEEP:
+		buf[0] = 0x06;
+		break;
+
+	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
+		buf[0] = 0x07;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* set it and wait for it to be so */
+	i2c_master_send(client, buf, 1);
+	timeout = jiffies + HZ * 3;
+	for (;;) {
+		/* get the current status */
+		buf[0] = 0x10;
+		i2c_master_send(client, buf, 1);
+		i2c_master_recv(client, buf, 1);
+
+		if (!(buf[0] & 0x20))
+			break;
+		if (time_after(jiffies,timeout)) {
+			status = -ETIMEDOUT;
+			break;
+		}
+
+		msleep(10);
+	}
+
+	/* delay a bit to let encoder settle */
+	msleep(50);
+
+	return status;
+}
+
+
+static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
+{
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	i2c_master_send(client, buf, 2);
+}
+
+static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
+{
+	u8 buf[3];
+
+	buf[0] = reg;
+	buf[1] = val >> 8;
+	buf[2] = val & 0xff;
+	i2c_master_send(client, buf, 3);
+}
+
+static int saa6752hs_set_bitrate(struct i2c_client *client,
+				 struct saa6752hs_state *h)
+{
+	struct saa6752hs_mpeg_params *params = &h->params;
+	int tot_bitrate;
+	int is_384k;
+
+	/* set the bitrate mode */
+	set_reg8(client, 0x71,
+		params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+
+	/* set the video bitrate */
+	if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+		/* set the target bitrate */
+		set_reg16(client, 0x80, params->vi_bitrate);
+
+		/* set the max bitrate */
+		set_reg16(client, 0x81, params->vi_bitrate_peak);
+		tot_bitrate = params->vi_bitrate_peak;
+	} else {
+		/* set the target bitrate (no max bitrate for CBR) */
+		set_reg16(client, 0x81, params->vi_bitrate);
+		tot_bitrate = params->vi_bitrate;
+	}
+
+	/* set the audio encoding */
+	set_reg8(client, 0x93,
+			params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
+
+	/* set the audio bitrate */
+	if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
+		is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
+	else
+		is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
+	set_reg8(client, 0x94, is_384k);
+	tot_bitrate += is_384k ? 384 : 256;
+
+	/* Note: the total max bitrate is determined by adding the video and audio
+	   bitrates together and also adding an extra 768kbit/s to stay on the
+	   safe side. If more control should be required, then an extra MPEG control
+	   should be added. */
+	tot_bitrate += 768;
+	if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
+		tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
+
+	/* set the total bitrate */
+	set_reg16(client, 0xb1, tot_bitrate);
+	return 0;
+}
+
+static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct saa6752hs_state *h =
+		container_of(ctrl->handler, struct saa6752hs_state, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		/* peak bitrate shall be >= normal bitrate */
+		if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+		    h->video_bitrate_peak->val < h->video_bitrate->val)
+			h->video_bitrate_peak->val = h->video_bitrate->val;
+		break;
+	}
+	return 0;
+}
+
+static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct saa6752hs_state *h =
+		container_of(ctrl->handler, struct saa6752hs_state, hdl);
+	struct saa6752hs_mpeg_params *params = &h->params;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PMT:
+		params->ts_pid_pmt = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+		params->ts_pid_audio = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+		params->ts_pid_video = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PCR:
+		params->ts_pid_pcr = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		params->au_encoding = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		params->au_l2_bitrate = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		params->au_ac3_bitrate = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		params->vi_aspect = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		params->vi_bitrate_mode = ctrl->val;
+		params->vi_bitrate = h->video_bitrate->val / 1000;
+		params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000;
+		v4l2_ctrl_activate(h->video_bitrate_peak,
+				ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
+{
+	unsigned char buf[9], buf2[4];
+	struct saa6752hs_state *h = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	unsigned size;
+	u32 crc;
+	unsigned char localPAT[256];
+	unsigned char localPMT[256];
+
+	/* Set video format - must be done first as it resets other settings */
+	set_reg8(client, 0x41, h->video_format);
+
+	/* Set number of lines in input signal */
+	set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
+
+	/* set bitrate */
+	saa6752hs_set_bitrate(client, h);
+
+	/* Set GOP structure {3, 13} */
+	set_reg16(client, 0x72, 0x030d);
+
+	/* Set minimum Q-scale {4} */
+	set_reg8(client, 0x82, 0x04);
+
+	/* Set maximum Q-scale {12} */
+	set_reg8(client, 0x83, 0x0c);
+
+	/* Set Output Protocol */
+	set_reg8(client, 0xd0, 0x81);
+
+	/* Set video output stream format {TS} */
+	set_reg8(client, 0xb0, 0x05);
+
+	/* Set leading null byte for TS */
+	set_reg16(client, 0xf6, leading_null_bytes);
+
+	/* compute PAT */
+	memcpy(localPAT, PAT, sizeof(PAT));
+	localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+	localPAT[18] = h->params.ts_pid_pmt & 0xff;
+	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+	localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+	/* compute PMT */
+	if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+		size = sizeof(PMT_AC3);
+		memcpy(localPMT, PMT_AC3, size);
+	} else {
+		size = sizeof(PMT);
+		memcpy(localPMT, PMT, size);
+	}
+	localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+	localPMT[4] = h->params.ts_pid_pmt & 0xff;
+	localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
+	localPMT[16] = h->params.ts_pid_pcr & 0xFF;
+	localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
+	localPMT[21] = h->params.ts_pid_video & 0xFF;
+	localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
+	localPMT[26] = h->params.ts_pid_audio & 0xFF;
+	crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
+	localPMT[size - 4] = (crc >> 24) & 0xFF;
+	localPMT[size - 3] = (crc >> 16) & 0xFF;
+	localPMT[size - 2] = (crc >> 8) & 0xFF;
+	localPMT[size - 1] = crc & 0xFF;
+
+	/* Set Audio PID */
+	set_reg16(client, 0xc1, h->params.ts_pid_audio);
+
+	/* Set Video PID */
+	set_reg16(client, 0xc0, h->params.ts_pid_video);
+
+	/* Set PCR PID */
+	set_reg16(client, 0xc4, h->params.ts_pid_pcr);
+
+	/* Send SI tables */
+	i2c_master_send(client, localPAT, sizeof(PAT));
+	i2c_master_send(client, localPMT, size);
+
+	/* mute then unmute audio. This removes buzzing artefacts */
+	set_reg8(client, 0xa4, 1);
+	set_reg8(client, 0xa4, 0);
+
+	/* start it going */
+	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
+
+	/* readout current state */
+	buf[0] = 0xE1;
+	buf[1] = 0xA7;
+	buf[2] = 0xFE;
+	buf[3] = 0x82;
+	buf[4] = 0xB0;
+	i2c_master_send(client, buf, 5);
+	i2c_master_recv(client, buf2, 4);
+
+	/* change aspect ratio */
+	buf[0] = 0xE0;
+	buf[1] = 0xA7;
+	buf[2] = 0xFE;
+	buf[3] = 0x82;
+	buf[4] = 0xB0;
+	buf[5] = buf2[0];
+	switch (h->params.vi_aspect) {
+	case V4L2_MPEG_VIDEO_ASPECT_16x9:
+		buf[6] = buf2[1] | 0x40;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_4x3:
+	default:
+		buf[6] = buf2[1] & 0xBF;
+		break;
+	}
+	buf[7] = buf2[2];
+	buf[8] = buf2[3];
+	i2c_master_send(client, buf, 9);
+
+	return 0;
+}
+
+static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	if (h->video_format == SAA6752HS_VF_UNKNOWN)
+		h->video_format = SAA6752HS_VF_D1;
+	f->width = v4l2_format_table[h->video_format].fmt.pix.width;
+	f->height = v4l2_format_table[h->video_format].fmt.pix.height;
+	f->code = V4L2_MBUS_FMT_FIXED;
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	int dist_352, dist_480, dist_720;
+
+	f->code = V4L2_MBUS_FMT_FIXED;
+
+	dist_352 = abs(f->width - 352);
+	dist_480 = abs(f->width - 480);
+	dist_720 = abs(f->width - 720);
+	if (dist_720 < dist_480) {
+		f->width = 720;
+		f->height = 576;
+	} else if (dist_480 < dist_352) {
+		f->width = 480;
+		f->height = 576;
+	} else {
+		f->width = 352;
+		if (abs(f->height - 576) < abs(f->height - 288))
+			f->height = 576;
+		else
+			f->height = 288;
+	}
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	if (f->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+
+	/*
+	  FIXME: translate and round width/height into EMPRESS
+	  subsample type:
+
+	  type   |   PAL   |  NTSC
+	  ---------------------------
+	  SIF    | 352x288 | 352x240
+	  1/2 D1 | 352x576 | 352x480
+	  2/3 D1 | 480x576 | 480x480
+	  D1     | 720x576 | 720x480
+	*/
+
+	saa6752hs_try_mbus_fmt(sd, f);
+	if (f->width == 720)
+		h->video_format = SAA6752HS_VF_D1;
+	else if (f->width == 480)
+		h->video_format = SAA6752HS_VF_2_3_D1;
+	else if (f->height == 576)
+		h->video_format = SAA6752HS_VF_1_2_D1;
+	else
+		h->video_format = SAA6752HS_VF_SIF;
+	return 0;
+}
+
+static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	h->standard = std;
+	return 0;
+}
+
+static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa6752hs_state *h = to_state(sd);
+
+	return v4l2_chip_ident_i2c_client(client,
+			chip, h->chip, h->revision);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = {
+	.try_ctrl = saa6752hs_try_ctrl,
+	.s_ctrl = saa6752hs_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
+	.g_chip_ident = saa6752hs_g_chip_ident,
+	.init = saa6752hs_init,
+	.s_std = saa6752hs_s_std,
+};
+
+static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
+	.s_mbus_fmt = saa6752hs_s_mbus_fmt,
+	.try_mbus_fmt = saa6752hs_try_mbus_fmt,
+	.g_mbus_fmt = saa6752hs_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_ops saa6752hs_ops = {
+	.core = &saa6752hs_core_ops,
+	.video = &saa6752hs_video_ops,
+};
+
+static int saa6752hs_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+	u8 addr = 0x13;
+	u8 data[12];
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+	if (h == NULL)
+		return -ENOMEM;
+	sd = &h->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
+
+	i2c_master_send(client, &addr, 1);
+	i2c_master_recv(client, data, sizeof(data));
+	h->chip = V4L2_IDENT_SAA6752HS;
+	h->revision = (data[8] << 8) | data[9];
+	h->has_ac3 = 0;
+	if (h->revision == 0x0206) {
+		h->chip = V4L2_IDENT_SAA6752HS_AC3;
+		h->has_ac3 = 1;
+		v4l_info(client, "supports AC-3\n");
+	}
+	h->params = param_defaults;
+
+	hdl = &h->hdl;
+	v4l2_ctrl_handler_init(hdl, 14);
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_AUDIO_ENCODING,
+		h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+			V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+		0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+		V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+		~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) |
+		  (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)),
+		V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+
+	if (h->has_ac3)
+		v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+			V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
+			V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+			~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) |
+			  (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)),
+			V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+		V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+		~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000),
+		V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_ENCODING,
+		V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+		~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2),
+		V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_ASPECT,
+		V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01,
+		V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+	h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+		1000000, 27000000, 1000, 8000000);
+
+	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_TYPE,
+		V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+		~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS),
+		V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
+
+	h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+	h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000);
+	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16);
+	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260);
+	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256);
+	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(h);
+		return err;
+	}
+	v4l2_ctrl_cluster(3, &h->video_bitrate_mode);
+	v4l2_ctrl_handler_setup(hdl);
+	h->standard = 0; /* Assume 625 input lines */
+	return 0;
+}
+
+static int saa6752hs_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&to_state(sd)->hdl);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id saa6752hs_id[] = {
+	{ "saa6752hs", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+static struct i2c_driver saa6752hs_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa6752hs",
+	},
+	.probe		= saa6752hs_probe,
+	.remove		= saa6752hs_remove,
+	.id_table	= saa6752hs_id,
+};
+
+module_i2c_driver(saa6752hs_driver);
diff --git a/drivers/media/pci/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig
index 15b90d6..7883393 100644
--- a/drivers/media/pci/saa7134/Kconfig
+++ b/drivers/media/pci/saa7134/Kconfig
@@ -6,6 +6,7 @@ config VIDEO_SAA7134
 	select VIDEO_TVEEPROM
 	select CRC32
 	select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_SAA6752HS if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  This is a video4linux driver for Philips SAA713x based
 	  TV cards.
diff --git a/drivers/media/pci/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile
index 3537548..58de9b0 100644
--- a/drivers/media/pci/saa7134/Makefile
+++ b/drivers/media/pci/saa7134/Makefile
@@ -4,7 +4,7 @@ saa7134-y +=	saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
 saa7134-y +=	saa7134-video.o
 saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
 
-obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
+obj-$(CONFIG_VIDEO_SAA7134) +=  saa7134.o saa7134-empress.o
 
 obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
 
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
deleted file mode 100644
index b14f5f6..0000000
--- a/drivers/media/pci/saa7134/saa6752hs.c
+++ /dev/null
@@ -1,805 +0,0 @@
- /*
-    saa6752hs - i2c-driver for the saa6752hs by Philips
-
-    Copyright (C) 2004 Andrew de Quincey
-
-    AC-3 support:
-
-    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License vs published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA.
-  */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
-
-#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
-#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
-#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
-#define MPEG_PID_MAX ((1 << 14) - 1)
-
-
-MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-enum saa6752hs_videoformat {
-	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
-	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
-	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
-	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
-	SAA6752HS_VF_UNKNOWN,
-};
-
-struct saa6752hs_mpeg_params {
-	/* transport streams */
-	__u16				ts_pid_pmt;
-	__u16				ts_pid_audio;
-	__u16				ts_pid_video;
-	__u16				ts_pid_pcr;
-
-	/* audio */
-	enum v4l2_mpeg_audio_encoding    au_encoding;
-	enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
-	enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
-
-	/* video */
-	enum v4l2_mpeg_video_aspect	vi_aspect;
-	enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
-	__u32 				vi_bitrate;
-	__u32 				vi_bitrate_peak;
-};
-
-static const struct v4l2_format v4l2_format_table[] =
-{
-	[SAA6752HS_VF_D1] =
-		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
-	[SAA6752HS_VF_2_3_D1] =
-		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
-	[SAA6752HS_VF_1_2_D1] =
-		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
-	[SAA6752HS_VF_SIF] =
-		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
-	[SAA6752HS_VF_UNKNOWN] =
-		{ .fmt = { .pix = { .width = 0, .height = 0}}},
-};
-
-struct saa6752hs_state {
-	struct v4l2_subdev            sd;
-	struct v4l2_ctrl_handler      hdl;
-	struct { /* video bitrate mode control cluster */
-		struct v4l2_ctrl *video_bitrate_mode;
-		struct v4l2_ctrl *video_bitrate;
-		struct v4l2_ctrl *video_bitrate_peak;
-	};
-	int 			      chip;
-	u32 			      revision;
-	int 			      has_ac3;
-	struct saa6752hs_mpeg_params  params;
-	enum saa6752hs_videoformat    video_format;
-	v4l2_std_id                   standard;
-};
-
-enum saa6752hs_command {
-	SAA6752HS_COMMAND_RESET = 0,
-	SAA6752HS_COMMAND_STOP = 1,
-	SAA6752HS_COMMAND_START = 2,
-	SAA6752HS_COMMAND_PAUSE = 3,
-	SAA6752HS_COMMAND_RECONFIGURE = 4,
-	SAA6752HS_COMMAND_SLEEP = 5,
-	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
-
-	SAA6752HS_COMMAND_MAX
-};
-
-static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct saa6752hs_state, sd);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static const u8 PAT[] = {
-	0xc2, /* i2c register */
-	0x00, /* table number for encoder */
-
-	0x47, /* sync */
-	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
-	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-	0x00, /* PSI pointer to start of table */
-
-	0x00, /* tid(0) */
-	0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
-
-	0x00, 0x01, /* transport_stream_id(1) */
-
-	0xc1, /* version_number(0), current_next_indicator(1) */
-
-	0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-	0x00, 0x01, /* program_number(1) */
-
-	0xe0, 0x00, /* PMT PID */
-
-	0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static const u8 PMT[] = {
-	0xc2, /* i2c register */
-	0x01, /* table number for encoder */
-
-	0x47, /* sync */
-	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
-	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-	0x00, /* PSI pointer to start of table */
-
-	0x02, /* tid(2) */
-	0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
-
-	0x00, 0x01, /* program_number(1) */
-
-	0xc1, /* version_number(0), current_next_indicator(1) */
-
-	0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-	0xe0, 0x00, /* PCR_PID */
-
-	0xf0, 0x00, /* program_info_length(0) */
-
-	0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
-	0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
-
-	0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static const u8 PMT_AC3[] = {
-	0xc2, /* i2c register */
-	0x01, /* table number for encoder(1) */
-	0x47, /* sync */
-
-	0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
-	0x10, /* PMT PID (0x0010) */
-	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-	0x00, /* PSI pointer to start of table */
-
-	0x02, /* TID (2) */
-	0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
-
-	0x00, 0x01, /* program_number(1) */
-
-	0xc1, /* version_number(0), current_next_indicator(1) */
-
-	0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-	0xe1, 0x04, /* PCR_PID (0x0104) */
-
-	0xf0, 0x00, /* program_info_length(0) */
-
-	0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
-	0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
-	0x6a, /* AC3 */
-	0x01, /* Descriptor_length(1) */
-	0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
-
-	0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
-};
-
-static const struct saa6752hs_mpeg_params param_defaults =
-{
-	.ts_pid_pmt      = 16,
-	.ts_pid_video    = 260,
-	.ts_pid_audio    = 256,
-	.ts_pid_pcr      = 259,
-
-	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
-	.vi_bitrate      = 4000,
-	.vi_bitrate_peak = 6000,
-	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-
-	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
-	.au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int saa6752hs_chip_command(struct i2c_client *client,
-				  enum saa6752hs_command command)
-{
-	unsigned char buf[3];
-	unsigned long timeout;
-	int status = 0;
-
-	/* execute the command */
-	switch(command) {
-	case SAA6752HS_COMMAND_RESET:
-		buf[0] = 0x00;
-		break;
-
-	case SAA6752HS_COMMAND_STOP:
-		buf[0] = 0x03;
-		break;
-
-	case SAA6752HS_COMMAND_START:
-		buf[0] = 0x02;
-		break;
-
-	case SAA6752HS_COMMAND_PAUSE:
-		buf[0] = 0x04;
-		break;
-
-	case SAA6752HS_COMMAND_RECONFIGURE:
-		buf[0] = 0x05;
-		break;
-
-	case SAA6752HS_COMMAND_SLEEP:
-		buf[0] = 0x06;
-		break;
-
-	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
-		buf[0] = 0x07;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* set it and wait for it to be so */
-	i2c_master_send(client, buf, 1);
-	timeout = jiffies + HZ * 3;
-	for (;;) {
-		/* get the current status */
-		buf[0] = 0x10;
-		i2c_master_send(client, buf, 1);
-		i2c_master_recv(client, buf, 1);
-
-		if (!(buf[0] & 0x20))
-			break;
-		if (time_after(jiffies,timeout)) {
-			status = -ETIMEDOUT;
-			break;
-		}
-
-		msleep(10);
-	}
-
-	/* delay a bit to let encoder settle */
-	msleep(50);
-
-	return status;
-}
-
-
-static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
-{
-	u8 buf[2];
-
-	buf[0] = reg;
-	buf[1] = val;
-	i2c_master_send(client, buf, 2);
-}
-
-static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
-{
-	u8 buf[3];
-
-	buf[0] = reg;
-	buf[1] = val >> 8;
-	buf[2] = val & 0xff;
-	i2c_master_send(client, buf, 3);
-}
-
-static int saa6752hs_set_bitrate(struct i2c_client *client,
-				 struct saa6752hs_state *h)
-{
-	struct saa6752hs_mpeg_params *params = &h->params;
-	int tot_bitrate;
-	int is_384k;
-
-	/* set the bitrate mode */
-	set_reg8(client, 0x71,
-		params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-
-	/* set the video bitrate */
-	if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
-		/* set the target bitrate */
-		set_reg16(client, 0x80, params->vi_bitrate);
-
-		/* set the max bitrate */
-		set_reg16(client, 0x81, params->vi_bitrate_peak);
-		tot_bitrate = params->vi_bitrate_peak;
-	} else {
-		/* set the target bitrate (no max bitrate for CBR) */
-		set_reg16(client, 0x81, params->vi_bitrate);
-		tot_bitrate = params->vi_bitrate;
-	}
-
-	/* set the audio encoding */
-	set_reg8(client, 0x93,
-			params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
-
-	/* set the audio bitrate */
-	if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
-		is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
-	else
-		is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
-	set_reg8(client, 0x94, is_384k);
-	tot_bitrate += is_384k ? 384 : 256;
-
-	/* Note: the total max bitrate is determined by adding the video and audio
-	   bitrates together and also adding an extra 768kbit/s to stay on the
-	   safe side. If more control should be required, then an extra MPEG control
-	   should be added. */
-	tot_bitrate += 768;
-	if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
-		tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
-
-	/* set the total bitrate */
-	set_reg16(client, 0xb1, tot_bitrate);
-	return 0;
-}
-
-static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct saa6752hs_state *h =
-		container_of(ctrl->handler, struct saa6752hs_state, hdl);
-
-	switch (ctrl->id) {
-	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-		/* peak bitrate shall be >= normal bitrate */
-		if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
-		    h->video_bitrate_peak->val < h->video_bitrate->val)
-			h->video_bitrate_peak->val = h->video_bitrate->val;
-		break;
-	}
-	return 0;
-}
-
-static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct saa6752hs_state *h =
-		container_of(ctrl->handler, struct saa6752hs_state, hdl);
-	struct saa6752hs_mpeg_params *params = &h->params;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MPEG_STREAM_TYPE:
-		break;
-	case V4L2_CID_MPEG_STREAM_PID_PMT:
-		params->ts_pid_pmt = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-		params->ts_pid_audio = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-		params->ts_pid_video = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_STREAM_PID_PCR:
-		params->ts_pid_pcr = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_AUDIO_ENCODING:
-		params->au_encoding = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-		params->au_l2_bitrate = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-		params->au_ac3_bitrate = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-		break;
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		break;
-	case V4L2_CID_MPEG_VIDEO_ASPECT:
-		params->vi_aspect = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-		params->vi_bitrate_mode = ctrl->val;
-		params->vi_bitrate = h->video_bitrate->val / 1000;
-		params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000;
-		v4l2_ctrl_activate(h->video_bitrate_peak,
-				ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
-{
-	unsigned char buf[9], buf2[4];
-	struct saa6752hs_state *h = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	unsigned size;
-	u32 crc;
-	unsigned char localPAT[256];
-	unsigned char localPMT[256];
-
-	/* Set video format - must be done first as it resets other settings */
-	set_reg8(client, 0x41, h->video_format);
-
-	/* Set number of lines in input signal */
-	set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
-
-	/* set bitrate */
-	saa6752hs_set_bitrate(client, h);
-
-	/* Set GOP structure {3, 13} */
-	set_reg16(client, 0x72, 0x030d);
-
-	/* Set minimum Q-scale {4} */
-	set_reg8(client, 0x82, 0x04);
-
-	/* Set maximum Q-scale {12} */
-	set_reg8(client, 0x83, 0x0c);
-
-	/* Set Output Protocol */
-	set_reg8(client, 0xd0, 0x81);
-
-	/* Set video output stream format {TS} */
-	set_reg8(client, 0xb0, 0x05);
-
-	/* Set leading null byte for TS */
-	set_reg16(client, 0xf6, leading_null_bytes);
-
-	/* compute PAT */
-	memcpy(localPAT, PAT, sizeof(PAT));
-	localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
-	localPAT[18] = h->params.ts_pid_pmt & 0xff;
-	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
-	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
-	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
-	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
-	localPAT[sizeof(PAT) - 1] = crc & 0xFF;
-
-	/* compute PMT */
-	if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
-		size = sizeof(PMT_AC3);
-		memcpy(localPMT, PMT_AC3, size);
-	} else {
-		size = sizeof(PMT);
-		memcpy(localPMT, PMT, size);
-	}
-	localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
-	localPMT[4] = h->params.ts_pid_pmt & 0xff;
-	localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
-	localPMT[16] = h->params.ts_pid_pcr & 0xFF;
-	localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
-	localPMT[21] = h->params.ts_pid_video & 0xFF;
-	localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
-	localPMT[26] = h->params.ts_pid_audio & 0xFF;
-	crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
-	localPMT[size - 4] = (crc >> 24) & 0xFF;
-	localPMT[size - 3] = (crc >> 16) & 0xFF;
-	localPMT[size - 2] = (crc >> 8) & 0xFF;
-	localPMT[size - 1] = crc & 0xFF;
-
-	/* Set Audio PID */
-	set_reg16(client, 0xc1, h->params.ts_pid_audio);
-
-	/* Set Video PID */
-	set_reg16(client, 0xc0, h->params.ts_pid_video);
-
-	/* Set PCR PID */
-	set_reg16(client, 0xc4, h->params.ts_pid_pcr);
-
-	/* Send SI tables */
-	i2c_master_send(client, localPAT, sizeof(PAT));
-	i2c_master_send(client, localPMT, size);
-
-	/* mute then unmute audio. This removes buzzing artefacts */
-	set_reg8(client, 0xa4, 1);
-	set_reg8(client, 0xa4, 0);
-
-	/* start it going */
-	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
-
-	/* readout current state */
-	buf[0] = 0xE1;
-	buf[1] = 0xA7;
-	buf[2] = 0xFE;
-	buf[3] = 0x82;
-	buf[4] = 0xB0;
-	i2c_master_send(client, buf, 5);
-	i2c_master_recv(client, buf2, 4);
-
-	/* change aspect ratio */
-	buf[0] = 0xE0;
-	buf[1] = 0xA7;
-	buf[2] = 0xFE;
-	buf[3] = 0x82;
-	buf[4] = 0xB0;
-	buf[5] = buf2[0];
-	switch (h->params.vi_aspect) {
-	case V4L2_MPEG_VIDEO_ASPECT_16x9:
-		buf[6] = buf2[1] | 0x40;
-		break;
-	case V4L2_MPEG_VIDEO_ASPECT_4x3:
-	default:
-		buf[6] = buf2[1] & 0xBF;
-		break;
-	}
-	buf[7] = buf2[2];
-	buf[8] = buf2[3];
-	i2c_master_send(client, buf, 9);
-
-	return 0;
-}
-
-static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
-	struct saa6752hs_state *h = to_state(sd);
-
-	if (h->video_format == SAA6752HS_VF_UNKNOWN)
-		h->video_format = SAA6752HS_VF_D1;
-	f->width = v4l2_format_table[h->video_format].fmt.pix.width;
-	f->height = v4l2_format_table[h->video_format].fmt.pix.height;
-	f->code = V4L2_MBUS_FMT_FIXED;
-	f->field = V4L2_FIELD_INTERLACED;
-	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	return 0;
-}
-
-static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
-	int dist_352, dist_480, dist_720;
-
-	f->code = V4L2_MBUS_FMT_FIXED;
-
-	dist_352 = abs(f->width - 352);
-	dist_480 = abs(f->width - 480);
-	dist_720 = abs(f->width - 720);
-	if (dist_720 < dist_480) {
-		f->width = 720;
-		f->height = 576;
-	} else if (dist_480 < dist_352) {
-		f->width = 480;
-		f->height = 576;
-	} else {
-		f->width = 352;
-		if (abs(f->height - 576) < abs(f->height - 288))
-			f->height = 576;
-		else
-			f->height = 288;
-	}
-	f->field = V4L2_FIELD_INTERLACED;
-	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	return 0;
-}
-
-static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
-	struct saa6752hs_state *h = to_state(sd);
-
-	if (f->code != V4L2_MBUS_FMT_FIXED)
-		return -EINVAL;
-
-	/*
-	  FIXME: translate and round width/height into EMPRESS
-	  subsample type:
-
-	  type   |   PAL   |  NTSC
-	  ---------------------------
-	  SIF    | 352x288 | 352x240
-	  1/2 D1 | 352x576 | 352x480
-	  2/3 D1 | 480x576 | 480x480
-	  D1     | 720x576 | 720x480
-	*/
-
-	saa6752hs_try_mbus_fmt(sd, f);
-	if (f->width == 720)
-		h->video_format = SAA6752HS_VF_D1;
-	else if (f->width == 480)
-		h->video_format = SAA6752HS_VF_2_3_D1;
-	else if (f->height == 576)
-		h->video_format = SAA6752HS_VF_1_2_D1;
-	else
-		h->video_format = SAA6752HS_VF_SIF;
-	return 0;
-}
-
-static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
-{
-	struct saa6752hs_state *h = to_state(sd);
-
-	h->standard = std;
-	return 0;
-}
-
-static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct saa6752hs_state *h = to_state(sd);
-
-	return v4l2_chip_ident_i2c_client(client,
-			chip, h->chip, h->revision);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = {
-	.try_ctrl = saa6752hs_try_ctrl,
-	.s_ctrl = saa6752hs_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
-	.g_chip_ident = saa6752hs_g_chip_ident,
-	.init = saa6752hs_init,
-	.s_std = saa6752hs_s_std,
-};
-
-static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
-	.s_mbus_fmt = saa6752hs_s_mbus_fmt,
-	.try_mbus_fmt = saa6752hs_try_mbus_fmt,
-	.g_mbus_fmt = saa6752hs_g_mbus_fmt,
-};
-
-static const struct v4l2_subdev_ops saa6752hs_ops = {
-	.core = &saa6752hs_core_ops,
-	.video = &saa6752hs_video_ops,
-};
-
-static int saa6752hs_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
-	struct v4l2_subdev *sd;
-	struct v4l2_ctrl_handler *hdl;
-	u8 addr = 0x13;
-	u8 data[12];
-
-	v4l_info(client, "chip found @ 0x%x (%s)\n",
-			client->addr << 1, client->adapter->name);
-	if (h == NULL)
-		return -ENOMEM;
-	sd = &h->sd;
-	v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
-
-	i2c_master_send(client, &addr, 1);
-	i2c_master_recv(client, data, sizeof(data));
-	h->chip = V4L2_IDENT_SAA6752HS;
-	h->revision = (data[8] << 8) | data[9];
-	h->has_ac3 = 0;
-	if (h->revision == 0x0206) {
-		h->chip = V4L2_IDENT_SAA6752HS_AC3;
-		h->has_ac3 = 1;
-		v4l_info(client, "supports AC-3\n");
-	}
-	h->params = param_defaults;
-
-	hdl = &h->hdl;
-	v4l2_ctrl_handler_init(hdl, 14);
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_AUDIO_ENCODING,
-		h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
-			V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-		0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
-
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_AUDIO_L2_BITRATE,
-		V4L2_MPEG_AUDIO_L2_BITRATE_384K,
-		~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) |
-		  (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)),
-		V4L2_MPEG_AUDIO_L2_BITRATE_256K);
-
-	if (h->has_ac3)
-		v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-			V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
-			V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
-			~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) |
-			  (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)),
-			V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
-
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
-		V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
-		~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000),
-		V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
-
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_ENCODING,
-		V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
-		~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2),
-		V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_ASPECT,
-		V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01,
-		V4L2_MPEG_VIDEO_ASPECT_4x3);
-
-	h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-		1000000, 27000000, 1000, 8000000);
-
-	v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_STREAM_TYPE,
-		V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
-		~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS),
-		V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
-
-	h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
-		V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-	h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000);
-	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16);
-	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260);
-	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256);
-	v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
-		V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259);
-	sd->ctrl_handler = hdl;
-	if (hdl->error) {
-		int err = hdl->error;
-
-		v4l2_ctrl_handler_free(hdl);
-		kfree(h);
-		return err;
-	}
-	v4l2_ctrl_cluster(3, &h->video_bitrate_mode);
-	v4l2_ctrl_handler_setup(hdl);
-	h->standard = 0; /* Assume 625 input lines */
-	return 0;
-}
-
-static int saa6752hs_remove(struct i2c_client *client)
-{
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-	v4l2_device_unregister_subdev(sd);
-	v4l2_ctrl_handler_free(&to_state(sd)->hdl);
-	kfree(to_state(sd));
-	return 0;
-}
-
-static const struct i2c_device_id saa6752hs_id[] = {
-	{ "saa6752hs", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
-
-static struct i2c_driver saa6752hs_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "saa6752hs",
-	},
-	.probe		= saa6752hs_probe,
-	.remove		= saa6752hs_remove,
-	.id_table	= saa6752hs_id,
-};
-
-module_i2c_driver(saa6752hs_driver);
-- 
1.7.10.4


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

end of thread, other threads:[~2013-06-02 10:56 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-02 10:55 [RFC PATCH 00/16] saa7134: cleanup Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 01/16] saa7134: remove radio/type field from saa7134_fh Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 02/16] saa7134: move the overlay fields from saa7134_fh to saa7134_dev Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 03/16] saa7134: move fmt/width/height " Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 04/16] saa7134: move qos_request " Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 05/16] saa7134: move the queue data " Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 06/16] saa7134: fix format-related compliance issues Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 07/16] saa7134: convert to the control framework Hans Verkuil
2013-06-02 10:55 ` [RFC PATCH 08/16] v4l2-ctrls: V4L2_CTRL_CLASS_FM_RX controls are also valid radio controls Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 09/16] saa7134: cleanup radio/video/empress ioctl handling Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 10/16] saa7134: fix empress format compliance bugs Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 11/16] saa7134: remove dev from saa7134_fh, use saa7134_fh for empress node Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 12/16] saa7134: share resource management between normal and empress nodes Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 13/16] saa7134: add support for control events Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 14/16] saa7134: use V4L2_IN_ST_NO_SIGNAL instead of NO_SYNC Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 15/16] saa6752hs: drop compat control code Hans Verkuil
2013-06-02 10:56 ` [RFC PATCH 16/16] saa6752hs: move to media/i2c Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).