All of lore.kernel.org
 help / color / mirror / Atom feed
* [REVIEWv2 PATCH 00/19] bttv v4l2-compliance fixes
@ 2013-02-10 12:49 Hans Verkuil
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:49 UTC (permalink / raw)
  To: linux-media

This is the second version of my v4l2-compliance patches for bttv.
It's identical to the first, except for the last patch which is new, and
it includes the tda7432 control framework conversion which I skipped for
some reason in v1.

This patch series has been tested with the following bttv cards:

Simple bttv cards:

39, 77, 41, 33

msp34xx based cards:

10 (with msp3410d)
1 (with msp3410c)

tvaudio based card:

40 (with tda7432, tea6420 and tda9850)

The last one is now finally working. I doubt audio has worked at all in the
last few years for that card.

If there are no comments, then I'll post the final pull request on Friday.

Regards,

	Hans


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

* [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues.
  2013-02-10 12:49 [REVIEWv2 PATCH 00/19] bttv v4l2-compliance fixes Hans Verkuil
@ 2013-02-10 12:49 ` Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 02/19] bttv: add VIDIOC_DBG_G_CHIP_IDENT Hans Verkuil
                     ` (17 more replies)
  0 siblings, 18 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The querycap ioctl didn't support V4L2_CAP_DEVICE_CAPS and the radio device
implemented audio and video inputs and s_std, which are not part of the radio
API.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |  101 +++++++++------------------------
 1 file changed, 27 insertions(+), 74 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index ccd18e4..cc7f58f 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2630,6 +2630,7 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
 static int bttv_querycap(struct file *file, void  *priv,
 				struct v4l2_capability *cap)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
@@ -2642,11 +2643,15 @@ static int bttv_querycap(struct file *file, void  *priv,
 		 "PCI:%s", pci_name(btv->c.pci));
 	cap->capabilities =
 		V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_VBI_CAPTURE |
 		V4L2_CAP_READWRITE |
-		V4L2_CAP_STREAMING;
+		V4L2_CAP_STREAMING |
+		V4L2_CAP_DEVICE_CAPS;
 	if (no_overlay <= 0)
 		cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+	if (btv->vbi_dev)
+		cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
+	if (btv->radio_dev)
+		cap->capabilities |= V4L2_CAP_RADIO;
 
 	/*
 	 * No need to lock here: those vars are initialized during board
@@ -2656,6 +2661,25 @@ static int bttv_querycap(struct file *file, void  *priv,
 		cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
 	if (btv->tuner_type != TUNER_ABSENT)
 		cap->capabilities |= V4L2_CAP_TUNER;
+	if (vdev->vfl_type == VFL_TYPE_GRABBER)
+		cap->device_caps = cap->capabilities &
+			(V4L2_CAP_VIDEO_CAPTURE |
+			 V4L2_CAP_READWRITE |
+			 V4L2_CAP_STREAMING |
+			 V4L2_CAP_VIDEO_OVERLAY |
+			 V4L2_CAP_TUNER);
+	else if (vdev->vfl_type == VFL_TYPE_VBI)
+		cap->device_caps = cap->capabilities &
+			(V4L2_CAP_VBI_CAPTURE |
+			 V4L2_CAP_READWRITE |
+			 V4L2_CAP_STREAMING |
+			 V4L2_CAP_TUNER);
+	else {
+		cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
+		if (btv->has_saa6588)
+			cap->device_caps |= V4L2_CAP_READWRITE |
+						V4L2_CAP_RDS_CAPTURE;
+	}
 	return 0;
 }
 
@@ -3430,20 +3454,6 @@ static int radio_release(struct file *file)
 	return 0;
 }
 
-static int radio_querycap(struct file *file, void *priv,
-					struct v4l2_capability *cap)
-{
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-
-	strcpy(cap->driver, "bttv");
-	strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
-	sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
-	cap->capabilities = V4L2_CAP_TUNER;
-
-	return 0;
-}
-
 static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
 	struct bttv_fh *fh = priv;
@@ -3464,29 +3474,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	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_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-
-	return 0;
-}
-
 static int radio_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *t)
 {
@@ -3500,28 +3487,6 @@ static int radio_s_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int radio_s_audio(struct file *file, void *priv,
-					const struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-	if (unlikely(i))
-		return -EINVAL;
-
-	return 0;
-}
-
-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)
 {
@@ -3540,12 +3505,6 @@ static int radio_queryctrl(struct file *file, void *priv,
 	return 0;
 }
 
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
 static ssize_t radio_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3586,16 +3545,10 @@ static const struct v4l2_file_operations radio_fops =
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-	.vidioc_querycap        = radio_querycap,
+	.vidioc_querycap        = bttv_querycap,
 	.vidioc_g_tuner         = radio_g_tuner,
-	.vidioc_enum_input      = radio_enum_input,
-	.vidioc_g_audio         = radio_g_audio,
 	.vidioc_s_tuner         = radio_s_tuner,
-	.vidioc_s_audio         = radio_s_audio,
-	.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          = bttv_g_ctrl,
 	.vidioc_s_ctrl          = bttv_s_ctrl,
 	.vidioc_g_frequency     = bttv_g_frequency,
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 02/19] bttv: add VIDIOC_DBG_G_CHIP_IDENT
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
@ 2013-02-10 12:49   ` Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 03/19] bttv: fix ENUM_INPUT and S_INPUT Hans Verkuil
                     ` (16 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

VIDIOC_DBG_G_CHIP_IDENT is a prerequisite for the G/S_REGISTER ioctls.
In addition, add support to call G/S_REGISTER for supporting i2c devices.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   40 +++++++++++++++++++++++++++++----
 drivers/media/pci/bt8xx/bttv.h        |    3 +++
 include/media/v4l2-chip-ident.h       |    8 +++++++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index cc7f58f..b36d675 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -49,6 +49,7 @@
 #include "bttvp.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
 
@@ -2059,6 +2060,28 @@ static int bttv_log_status(struct file *file, void *f)
 	return 0;
 }
 
+static int bttv_g_chip_ident(struct file *file, void *f, struct v4l2_dbg_chip_ident *chip)
+{
+	struct bttv_fh *fh  = f;
+	struct bttv *btv = fh->btv;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+		if (v4l2_chip_match_host(&chip->match)) {
+			chip->ident = btv->id;
+			if (chip->ident == PCI_DEVICE_ID_FUSION879)
+				chip->ident = V4L2_IDENT_BT879;
+		}
+		return 0;
+	}
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+	/* TODO: is this correct? */
+	return bttv_call_all_err(btv, core, g_chip_ident, chip);
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int bttv_g_register(struct file *file, void *f,
 					struct v4l2_dbg_register *reg)
@@ -2069,8 +2092,12 @@ static int bttv_g_register(struct file *file, void *f,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!v4l2_chip_match_host(&reg->match))
-		return -EINVAL;
+	if (!v4l2_chip_match_host(&reg->match)) {
+		/* TODO: subdev errors should not be ignored, this should become a
+		   subdev helper function. */
+		bttv_call_all(btv, core, g_register, reg);
+		return 0;
+	}
 
 	/* bt848 has a 12-bit register space */
 	reg->reg &= 0xfff;
@@ -2089,8 +2116,12 @@ static int bttv_s_register(struct file *file, void *f,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!v4l2_chip_match_host(&reg->match))
-		return -EINVAL;
+	if (!v4l2_chip_match_host(&reg->match)) {
+		/* TODO: subdev errors should not be ignored, this should become a
+		   subdev helper function. */
+		bttv_call_all(btv, core, s_register, reg);
+		return 0;
+	}
 
 	/* bt848 has a 12-bit register space */
 	reg->reg &= 0xfff;
@@ -3394,6 +3425,7 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_s_frequency             = bttv_s_frequency,
 	.vidioc_log_status		= bttv_log_status,
 	.vidioc_querystd		= bttv_querystd,
+	.vidioc_g_chip_ident		= bttv_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register		= bttv_g_register,
 	.vidioc_s_register		= bttv_s_register,
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
index 79a1124..6139ce2 100644
--- a/drivers/media/pci/bt8xx/bttv.h
+++ b/drivers/media/pci/bt8xx/bttv.h
@@ -359,6 +359,9 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
 #define bttv_call_all(btv, o, f, args...) \
 	v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
 
+#define bttv_call_all_err(btv, o, f, args...) \
+	v4l2_device_call_until_err(&btv->c.v4l2_dev, 0, o, f, ##args)
+
 extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
 extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
 			 unsigned char b2, int both);
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 4ee125b..b5996f9 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -96,12 +96,20 @@ enum {
 	/* module au0828 */
 	V4L2_IDENT_AU0828 = 828,
 
+	/* module bttv: ident 848 + 849 */
+	V4L2_IDENT_BT848 = 848,
+	V4L2_IDENT_BT849 = 849,
+
 	/* module bt856: just ident 856 */
 	V4L2_IDENT_BT856 = 856,
 
 	/* module bt866: just ident 866 */
 	V4L2_IDENT_BT866 = 866,
 
+	/* module bttv: ident 878 + 879 */
+	V4L2_IDENT_BT878 = 878,
+	V4L2_IDENT_BT879 = 879,
+
 	/* module ks0127: reserved range 1120-1129 */
 	V4L2_IDENT_KS0122S = 1122,
 	V4L2_IDENT_KS0127  = 1127,
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 03/19] bttv: fix ENUM_INPUT and S_INPUT
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 02/19] bttv: add VIDIOC_DBG_G_CHIP_IDENT Hans Verkuil
@ 2013-02-10 12:49   ` Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input Hans Verkuil
                     ` (15 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

- Fix ENUM_INPUT audioset.
- Fix incorrect input check in s_input.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index b36d675..6e61dbd 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1923,7 +1923,7 @@ static int bttv_enum_input(struct file *file, void *priv,
 	}
 
 	i->type     = V4L2_INPUT_TYPE_CAMERA;
-	i->audioset = 1;
+	i->audioset = 0;
 
 	if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
 		sprintf(i->name, "Television");
@@ -1964,21 +1964,16 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-
 	int err;
 
 	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
+	if (err)
+		return err;
 
-	if (i > bttv_tvcards[btv->c.type].video_inputs) {
-		err = -EINVAL;
-		goto err;
-	}
+	if (i >= bttv_tvcards[btv->c.type].video_inputs)
+		return -EINVAL;
 
 	set_input(btv, i, btv->tvnorm);
-
-err:
 	return 0;
 }
 
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 02/19] bttv: add VIDIOC_DBG_G_CHIP_IDENT Hans Verkuil
  2013-02-10 12:49   ` [REVIEWv2 PATCH 03/19] bttv: fix ENUM_INPUT and S_INPUT Hans Verkuil
@ 2013-02-10 12:49   ` Hans Verkuil
  2013-02-10 20:22     ` Frank Schäfer
  2013-02-10 12:50   ` [REVIEWv2 PATCH 05/19] bttv: disable g/s_tuner and g/s_freq when no tuner present, fix return codes Hans Verkuil
                     ` (14 subsequent siblings)
  17 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:49 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/bt8xx/bttv-driver.c |   19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 6e61dbd..a02c031 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3138,23 +3138,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 	return 0;
 }
 
-static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	strcpy(a->name, "audio");
-	return 0;
-}
-
-static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	return 0;
-}
-
 static ssize_t bttv_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3390,8 +3373,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
 	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
 	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
-	.vidioc_g_audio                 = bttv_g_audio,
-	.vidioc_s_audio                 = bttv_s_audio,
 	.vidioc_cropcap                 = bttv_cropcap,
 	.vidioc_reqbufs                 = bttv_reqbufs,
 	.vidioc_querybuf                = bttv_querybuf,
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 05/19] bttv: disable g/s_tuner and g/s_freq when no tuner present, fix return codes.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (2 preceding siblings ...)
  2013-02-10 12:49   ` [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 06/19] bttv: set initial tv/radio frequencies Hans Verkuil
                     ` (13 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

If no tuner is present, then disable the tuner and frequency ioctls.
We can remove a number of checks from those ioctls testing for the presence
of a tuner.

Also remove some tuner type checks (now done by the core) and fix an
error return when the prio check fails.

Finally some 'unlikely' statements are removed since those only make sense
in tightly often executed loops, otherwise they just clutter up the code.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   44 ++++++++++++---------------------
 1 file changed, 16 insertions(+), 28 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index a02c031..228b7c1 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1984,25 +1984,17 @@ static int bttv_s_tuner(struct file *file, void *priv,
 	struct bttv *btv = fh->btv;
 	int err;
 
-	if (unlikely(0 != t->index))
+	if (t->index)
 		return -EINVAL;
 
-	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
-		err = -EINVAL;
-		goto err;
-	}
-
 	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
+	if (err)
+		return err;
 
 	bttv_call_all(btv, tuner, s_tuner, t);
 
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 1);
-
-err:
-
 	return 0;
 }
 
@@ -2012,9 +2004,10 @@ static int bttv_g_frequency(struct file *file, void *priv,
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 
-	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	f->frequency = btv->freq;
+	if (f->tuner)
+		return -EINVAL;
 
+	f->frequency = btv->freq;
 	return 0;
 }
 
@@ -2025,24 +2018,17 @@ static int bttv_s_frequency(struct file *file, void *priv,
 	struct bttv *btv = fh->btv;
 	int err;
 
-	if (unlikely(f->tuner != 0))
+	if (f->tuner)
 		return -EINVAL;
 
 	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
+	if (err)
+		return err;
 
-	if (unlikely(f->type != (btv->radio_user
-		? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
-		err = -EINVAL;
-		goto err;
-	}
 	btv->freq = f->frequency;
 	bttv_call_all(btv, tuner, s_frequency, f);
 	if (btv->has_matchbox && btv->radio_user)
 		tea5757_set_freq(btv, btv->freq);
-err:
-
 	return 0;
 }
 
@@ -2983,8 +2969,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (btv->tuner_type == TUNER_ABSENT)
-		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 
@@ -3467,8 +3451,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (btv->tuner_type == TUNER_ABSENT)
-		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 	strcpy(t->name, "Radio");
@@ -4112,7 +4094,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 
 
 /* ----------------------------------------------------------------------- */
-/* initialitation                                                          */
+/* initialization                                                          */
 
 static struct video_device *vdev_init(struct bttv *btv,
 				      const struct video_device *template,
@@ -4131,6 +4113,12 @@ static struct video_device *vdev_init(struct bttv *btv,
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
 		 type_name, bttv_tvcards[btv->c.type].name);
+	if (btv->tuner_type == TUNER_ABSENT) {
+		v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+	}
 	return vfd;
 }
 
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 06/19] bttv: set initial tv/radio frequencies
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (3 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 05/19] bttv: disable g/s_tuner and g/s_freq when no tuner present, fix return codes Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 07/19] bttv: G_PARM: set readbuffers Hans Verkuil
                     ` (12 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Set an initial frequencies when the driver is loaded. That way G_FREQUENCY will
give a frequency that corresponds with reality.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   34 +++++++++++++++++++++++++++------
 drivers/media/pci/bt8xx/bttvp.h       |    3 ++-
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 228b7c1..07c0919 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2007,10 +2007,27 @@ static int bttv_g_frequency(struct file *file, void *priv,
 	if (f->tuner)
 		return -EINVAL;
 
-	f->frequency = btv->freq;
+	f->frequency = f->type == V4L2_TUNER_RADIO ?
+				btv->radio_freq : btv->tv_freq;
+
 	return 0;
 }
 
+static void bttv_set_frequency(struct bttv *btv, struct v4l2_frequency *f)
+{
+	bttv_call_all(btv, tuner, s_frequency, f);
+	/* s_frequency may clamp the frequency, so get the actual
+	   frequency before assigning radio/tv_freq. */
+	bttv_call_all(btv, tuner, g_frequency, f);
+	if (f->type == V4L2_TUNER_RADIO) {
+		btv->radio_freq = f->frequency;
+		if (btv->has_matchbox)
+			tea5757_set_freq(btv, btv->radio_freq);
+	} else {
+		btv->tv_freq = f->frequency;
+	}
+}
+
 static int bttv_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
@@ -2024,11 +2041,7 @@ static int bttv_s_frequency(struct file *file, void *priv,
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	if (err)
 		return err;
-
-	btv->freq = f->frequency;
-	bttv_call_all(btv, tuner, s_frequency, f);
-	if (btv->has_matchbox && btv->radio_user)
-		tea5757_set_freq(btv, btv->freq);
+	bttv_set_frequency(btv, f);
 	return 0;
 }
 
@@ -4216,6 +4229,11 @@ static void pci_set_command(struct pci_dev *dev)
 
 static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 {
+	struct v4l2_frequency init_freq = {
+		.tuner = 0,
+		.type = V4L2_TUNER_ANALOG_TV,
+		.frequency = 980,
+	};
 	int result;
 	unsigned char lat;
 	struct bttv *btv;
@@ -4356,6 +4374,10 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	/* some card-specific stuff (needs working i2c) */
 	bttv_init_card2(btv);
 	bttv_init_tuner(btv);
+	if (btv->tuner_type != TUNER_ABSENT) {
+		bttv_set_frequency(btv, &init_freq);
+		btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
+	}
 	init_irqreg(btv);
 
 	/* register video4linux + input */
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 9ec0adb..528e03e 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -418,7 +418,7 @@ struct bttv {
 	unsigned int input;
 	unsigned int audio;
 	unsigned int mute;
-	unsigned long freq;
+	unsigned long tv_freq;
 	unsigned int tvnorm;
 	int hue, contrast, bright, saturation;
 	struct v4l2_framebuffer fbuf;
@@ -442,6 +442,7 @@ struct bttv {
 	int has_radio;
 	int radio_user;
 	int radio_uses_msp_demodulator;
+	unsigned long radio_freq;
 
 	/* miro/pinnacle + Aimslab VHX
 	   philips matchbox (tea5757 radio tuner) support */
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 07/19] bttv: G_PARM: set readbuffers.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (4 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 06/19] bttv: set initial tv/radio frequencies Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 08/19] bttv: fill in colorspace Hans Verkuil
                     ` (11 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 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/bt8xx/bttv-driver.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 07c0919..3ba423e 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2970,6 +2970,9 @@ static int bttv_g_parm(struct file *file, void *f,
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	parm->parm.capture.readbuffers = gbuffers;
 	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
 				    &parm->parm.capture.timeperframe);
 
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 08/19] bttv: fill in colorspace.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (5 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 07/19] bttv: G_PARM: set readbuffers Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 09/19] bttv: fill in fb->flags for VIDIOC_G_FBUF Hans Verkuil
                     ` (10 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 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/bt8xx/bttv-driver.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 3ba423e..70878e6 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2506,6 +2506,7 @@ static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
 				fh->width, fh->height);
 	f->fmt.pix.field        = fh->cap.field;
 	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
 }
@@ -2577,6 +2578,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 	/* update data for the application */
 	f->fmt.pix.field = field;
 	pix_format_set_size(&f->fmt.pix, fmt, width, height);
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
 }
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 09/19] bttv: fill in fb->flags for VIDIOC_G_FBUF
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (6 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 08/19] bttv: fill in colorspace Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 10/19] bttv: fix field handling inside TRY_FMT Hans Verkuil
                     ` (9 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 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/bt8xx/bttv-driver.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 70878e6..81886e1 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2769,6 +2769,7 @@ static int bttv_g_fbuf(struct file *file, void *f,
 
 	*fb = btv->fbuf;
 	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
 	if (fh->ovfmt)
 		fb->fmt.pixelformat  = fh->ovfmt->fourcc;
 	return 0;
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 10/19] bttv: fix field handling inside TRY_FMT.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (7 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 09/19] bttv: fill in fb->flags for VIDIOC_G_FBUF Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 11/19] tda7432: convert to the control framework Hans Verkuil
                     ` (8 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

- don't return -EINVAL for invalid field types, handle those as if it
  was FIELD_ANY.
- the handling of FIELD_SEQ_BT/TB was wrong as well: if such field formats
  aren't supported, then fall back to FIELD_ANY instead of returning an error.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 81886e1..21b38ee 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2530,6 +2530,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 	struct bttv *btv = fh->btv;
 	enum v4l2_field field;
 	__s32 width, height;
+	__s32 height2;
 	int rc;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -2538,30 +2539,25 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 
 	field = f->fmt.pix.field;
 
-	if (V4L2_FIELD_ANY == field) {
-		__s32 height2;
-
-		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-		field = (f->fmt.pix.height > height2)
-			? V4L2_FIELD_INTERLACED
-			: V4L2_FIELD_BOTTOM;
-	}
-
-	if (V4L2_FIELD_SEQ_BT == field)
-		field = V4L2_FIELD_SEQ_TB;
-
 	switch (field) {
 	case V4L2_FIELD_TOP:
 	case V4L2_FIELD_BOTTOM:
 	case V4L2_FIELD_ALTERNATE:
 	case V4L2_FIELD_INTERLACED:
 		break;
+	case V4L2_FIELD_SEQ_BT:
 	case V4L2_FIELD_SEQ_TB:
-		if (fmt->flags & FORMAT_FLAGS_PLANAR)
-			return -EINVAL;
+		if (!(fmt->flags & FORMAT_FLAGS_PLANAR)) {
+			field = V4L2_FIELD_SEQ_TB;
+			break;
+		}
+		/* fall through */
+	default: /* FIELD_ANY case */
+		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (f->fmt.pix.height > height2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
 		break;
-	default:
-		return -EINVAL;
 	}
 
 	width = f->fmt.pix.width;
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 11/19] tda7432: convert to the control framework
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (8 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 10/19] bttv: fix field handling inside TRY_FMT Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 12/19] bttv: " Hans Verkuil
                     ` (7 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 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/i2c/tda7432.c |  276 +++++++++++++++++--------------------------
 1 file changed, 110 insertions(+), 166 deletions(-)

diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c
index f7707e6..28b5121 100644
--- a/drivers/media/i2c/tda7432.c
+++ b/drivers/media/i2c/tda7432.c
@@ -35,6 +35,7 @@
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
 #include <media/i2c-addr.h>
 
 #ifndef VIDEO_AUDIO_BALANCE
@@ -60,13 +61,17 @@ MODULE_PARM_DESC(maxvol, "Set maximium volume to +20dB(0) else +0dB(1). Default
 
 struct tda7432 {
 	struct v4l2_subdev sd;
-	int addr;
-	int input;
-	int volume;
-	int muted;
-	int bass, treble;
-	int lf, lr, rf, rr;
-	int loud;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* bass/treble cluster */
+		struct v4l2_ctrl *bass;
+		struct v4l2_ctrl *treble;
+	};
+	struct {
+		/* mute/balance cluster */
+		struct v4l2_ctrl *mute;
+		struct v4l2_ctrl *balance;
+	};
 };
 
 static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
@@ -74,6 +79,11 @@ static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
 	return container_of(sd, struct tda7432, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tda7432, hdl)->sd;
+}
+
 /* The TDA7432 is made by STS-Thompson
  * http://www.st.com
  * http://us.st.com/stonline/books/pdf/docs/4056.pdf
@@ -227,24 +237,22 @@ static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val)
 static int tda7432_set(struct v4l2_subdev *sd)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct tda7432 *t = to_state(sd);
 	unsigned char buf[16];
 
-	v4l2_dbg(1, debug, sd,
-		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
-		t->input, t->volume, t->bass, t->treble, t->lf, t->lr,
-		t->rf, t->rr, t->loud);
 	buf[0]  = TDA7432_IN;
-	buf[1]  = t->input;
-	buf[2]  = t->volume;
-	buf[3]  = t->bass;
-	buf[4]	= t->treble;
-	buf[5]  = t->lf;
-	buf[6]  = t->lr;
-	buf[7]  = t->rf;
-	buf[8]  = t->rr;
-	buf[9]  = t->loud;
-	if (10 != i2c_master_send(client, buf, 10)) {
+	buf[1]  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
+		  TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
+		  TDA7432_BASS_NORM;   /* Normal bass range     */
+	buf[2]  = 0x3b;
+	if (loudness)			 /* Turn loudness on?     */
+		buf[2] |= TDA7432_LD_ON;
+	buf[3]  = TDA7432_TREBLE_0DB | (TDA7432_BASS_0DB << 4);
+	buf[4]  = TDA7432_ATTEN_0DB;
+	buf[5]  = TDA7432_ATTEN_0DB;
+	buf[6]  = TDA7432_ATTEN_0DB;
+	buf[7]  = TDA7432_ATTEN_0DB;
+	buf[8]  = loudness;
+	if (9 != i2c_master_send(client, buf, 9)) {
 		v4l2_err(sd, "I/O error, trying tda7432_set\n");
 		return -1;
 	}
@@ -252,174 +260,86 @@ static int tda7432_set(struct v4l2_subdev *sd)
 	return 0;
 }
 
-static void do_tda7432_init(struct v4l2_subdev *sd)
-{
-	struct tda7432 *t = to_state(sd);
-
-	v4l2_dbg(2, debug, sd, "In tda7432_init\n");
-
-	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
-		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
-		    TDA7432_BASS_NORM;   /* Normal bass range     */
-	t->volume =  0x3b ;				 /* -27dB Volume            */
-	if (loudness)			 /* Turn loudness on?     */
-		t->volume |= TDA7432_LD_ON;
-	t->muted    = 1;
-	t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
-	t->bass		= TDA7432_BASS_0DB; 	 /* 0dB Bass              */
-	t->lf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->lr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->rf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->rr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->loud   = loudness;		 /* insmod parameter      */
-
-	tda7432_set(sd);
-}
-
-static int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tda7432_log_status(struct v4l2_subdev *sd)
 {
-	struct tda7432 *t = to_state(sd);
+	struct tda7432 *state = to_state(sd);
 
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value=t->muted;
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (!maxvol){  /* max +20db */
-			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 630;
-		} else {       /* max 0db   */
-			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 829;
-		}
-		return 0;
-	case V4L2_CID_AUDIO_BALANCE:
-	{
-		if ( (t->lf) < (t->rf) )
-			/* right is attenuated, balance shifted left */
-			ctrl->value = (32768 - 1057*(t->rf));
-		else
-			/* left is attenuated, balance shifted right */
-			ctrl->value = (32768 + 1057*(t->lf));
-		return 0;
-	}
-	case V4L2_CID_AUDIO_BASS:
-	{
-		/* Bass/treble 4 bits each */
-		int bass=t->bass;
-		if(bass >= 0x8)
-			bass = ~(bass - 0x8) & 0xf;
-		ctrl->value = (bass << 12)+(bass << 8)+(bass << 4)+(bass);
-		return 0;
-	}
-	case V4L2_CID_AUDIO_TREBLE:
-	{
-		int treble=t->treble;
-		if(treble >= 0x8)
-			treble = ~(treble - 0x8) & 0xf;
-		ctrl->value = (treble << 12)+(treble << 8)+(treble << 4)+(treble);
-		return 0;
-	}
-	}
-	return -EINVAL;
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
 }
 
-static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct tda7432 *t = to_state(sd);
+	u8 bass, treble, volume;
+	u8 lf, lr, rf, rr;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		t->muted=ctrl->value;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-		if(!maxvol){ /* max +20db */
-			t->volume = 0x6f - ((ctrl->value)/630);
-		} else {    /* max 0db   */
-			t->volume = 0x6f - ((ctrl->value)/829);
-		}
-		if (loudness)		/* Turn on the loudness bit */
-			t->volume |= TDA7432_LD_ON;
-
-		tda7432_write(sd, TDA7432_VL, t->volume);
-		return 0;
-	case V4L2_CID_AUDIO_BALANCE:
-		if (ctrl->value < 32768) {
+		if (t->balance->val < 0) {
 			/* shifted to left, attenuate right */
-			t->rr = (32768 - ctrl->value)/1057;
-			t->rf = t->rr;
-			t->lr = TDA7432_ATTEN_0DB;
-			t->lf = TDA7432_ATTEN_0DB;
-		} else if(ctrl->value > 32769) {
+			rr = rf = -t->balance->val;
+			lr = lf = TDA7432_ATTEN_0DB;
+		} else if (t->balance->val > 0) {
 			/* shifted to right, attenuate left */
-			t->lf = (ctrl->value - 32768)/1057;
-			t->lr = t->lf;
-			t->rr = TDA7432_ATTEN_0DB;
-			t->rf = TDA7432_ATTEN_0DB;
+			rr = rf = TDA7432_ATTEN_0DB;
+			lr = lf = t->balance->val;
 		} else {
 			/* centered */
-			t->rr = TDA7432_ATTEN_0DB;
-			t->rf = TDA7432_ATTEN_0DB;
-			t->lf = TDA7432_ATTEN_0DB;
-			t->lr = TDA7432_ATTEN_0DB;
+			rr = rf = TDA7432_ATTEN_0DB;
+			lr = lf = TDA7432_ATTEN_0DB;
 		}
-		break;
-	case V4L2_CID_AUDIO_BASS:
-		t->bass = ctrl->value >> 12;
-		if(t->bass>= 0x8)
-				t->bass = (~t->bass & 0xf) + 0x8 ;
-
-		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		if (t->mute->val) {
+			lf |= TDA7432_MUTE;
+			lr |= TDA7432_MUTE;
+			lf |= TDA7432_MUTE;
+			rr |= TDA7432_MUTE;
+		}
+		/* Mute & update balance*/
+		tda7432_write(sd, TDA7432_LF, lf);
+		tda7432_write(sd, TDA7432_LR, lr);
+		tda7432_write(sd, TDA7432_RF, rf);
+		tda7432_write(sd, TDA7432_RR, rr);
 		return 0;
-	case V4L2_CID_AUDIO_TREBLE:
-		t->treble= ctrl->value >> 12;
-		if(t->treble>= 0x8)
-				t->treble = (~t->treble & 0xf) + 0x8 ;
+	case V4L2_CID_AUDIO_VOLUME:
+		volume = 0x6f - ctrl->val;
+		if (loudness)		/* Turn on the loudness bit */
+			volume |= TDA7432_LD_ON;
 
-		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		tda7432_write(sd, TDA7432_VL, volume);
 		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	/* Used for both mute and balance changes */
-	if (t->muted)
-	{
-		/* Mute & update balance*/
-		tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE);
-	} else {
-		tda7432_write(sd, TDA7432_LF, t->lf);
-		tda7432_write(sd, TDA7432_LR, t->lr);
-		tda7432_write(sd, TDA7432_RF, t->rf);
-		tda7432_write(sd, TDA7432_RR, t->rr);
-	}
-	return 0;
-}
-
-static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
-	case V4L2_CID_AUDIO_MUTE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
+		bass = t->bass->val;
+		treble = t->treble->val;
+		if (bass >= 0x8)
+			bass = 14 - (bass - 8);
+		if (treble >= 0x8)
+			treble = 14 - (treble - 8);
+
+		tda7432_write(sd, TDA7432_TN, 0x10 | (bass << 4) | treble);
+		return 0;
 	}
 	return -EINVAL;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static const struct v4l2_subdev_core_ops tda7432_core_ops = {
-	.queryctrl = tda7432_queryctrl,
-	.g_ctrl = tda7432_g_ctrl,
+static const struct v4l2_ctrl_ops tda7432_ctrl_ops = {
 	.s_ctrl = tda7432_s_ctrl,
 };
 
+static const struct v4l2_subdev_core_ops tda7432_core_ops = {
+	.log_status = tda7432_log_status,
+	.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,
+};
+
 static const struct v4l2_subdev_ops tda7432_ops = {
 	.core = &tda7432_core_ops,
 };
@@ -444,6 +364,28 @@ static int tda7432_probe(struct i2c_client *client,
 		return -ENOMEM;
 	sd = &t->sd;
 	v4l2_i2c_subdev_init(sd, client, &tda7432_ops);
+	v4l2_ctrl_handler_init(&t->hdl, 5);
+	v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_VOLUME, 0, maxvol ? 0x68 : 0x4f, 1, maxvol ? 0x5d : 0x47);
+	t->mute = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	t->balance = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_BALANCE, -31, 31, 1, 0);
+	t->bass = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_BASS, 0, 14, 1, 7);
+	t->treble = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_TREBLE, 0, 14, 1, 7);
+	sd->ctrl_handler = &t->hdl;
+	if (t->hdl.error) {
+		int err = t->hdl.error;
+
+		v4l2_ctrl_handler_free(&t->hdl);
+		kfree(t);
+		return err;
+	}
+	v4l2_ctrl_cluster(2, &t->bass);
+	v4l2_ctrl_cluster(2, &t->mute);
+	v4l2_ctrl_handler_setup(&t->hdl);
 	if (loudness < 0 || loudness > 15) {
 		v4l2_warn(sd, "loudness parameter must be between 0 and 15\n");
 		if (loudness < 0)
@@ -452,17 +394,19 @@ static int tda7432_probe(struct i2c_client *client,
 			loudness = 15;
 	}
 
-	do_tda7432_init(sd);
+	tda7432_set(sd);
 	return 0;
 }
 
 static int tda7432_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tda7432 *t = to_state(sd);
 
-	do_tda7432_init(sd);
+	tda7432_set(sd);
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
+	v4l2_ctrl_handler_free(&t->hdl);
+	kfree(t);
 	return 0;
 }
 
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 12/19] bttv: convert to the control framework.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (9 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 11/19] tda7432: convert to the control framework Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 13/19] bttv: add support for control events Hans Verkuil
                     ` (6 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Note that the private chroma agc control has been replaced with the standard
CHROMA_AGC control.

Also fixes a mute/automute problem where closing the file handle would force
mute on. That's not what you want since that would make the mute state out of
sync with the mute control. Instead check against the user count.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-cards.c  |    5 +-
 drivers/media/pci/bt8xx/bttv-driver.c |  682 +++++++++++++--------------------
 drivers/media/pci/bt8xx/bttvp.h       |   16 +-
 include/uapi/linux/v4l2-controls.h    |    5 +
 4 files changed, 271 insertions(+), 437 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index c4c5917..682ed89 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -3554,8 +3554,9 @@ void bttv_init_card2(struct bttv *btv)
 			I2C_CLIENT_END
 		};
 
-		if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-				&btv->c.i2c_adap, "tda7432", 0, addrs))
+		btv->sd_tda7432 = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tda7432", 0, addrs);
+		if (btv->sd_tda7432)
 			return;
 	}
 
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 21b38ee..09f58f3 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -94,7 +94,7 @@ static unsigned int combfilter;
 static unsigned int lumafilter;
 static unsigned int automute    = 1;
 static unsigned int chroma_agc;
-static unsigned int adc_crush   = 1;
+static unsigned int agc_crush   = 1;
 static unsigned int whitecrush_upper = 0xCF;
 static unsigned int whitecrush_lower = 0x7F;
 static unsigned int vcr_hack;
@@ -126,7 +126,7 @@ module_param(combfilter,        int, 0444);
 module_param(lumafilter,        int, 0444);
 module_param(automute,          int, 0444);
 module_param(chroma_agc,        int, 0444);
-module_param(adc_crush,         int, 0444);
+module_param(agc_crush,         int, 0444);
 module_param(whitecrush_upper,  int, 0444);
 module_param(whitecrush_lower,  int, 0444);
 module_param(vcr_hack,          int, 0444);
@@ -139,27 +139,27 @@ module_param_array(video_nr,    int, NULL, 0444);
 module_param_array(radio_nr,    int, NULL, 0444);
 module_param_array(vbi_nr,      int, NULL, 0444);
 
-MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
-MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
-MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
-MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
-MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
-MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
+MODULE_PARM_DESC(radio, "The TV card supports radio, default is 0 (no)");
+MODULE_PARM_DESC(bigendian, "byte order of the framebuffer, default is native endian");
+MODULE_PARM_DESC(bttv_verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(bttv_gpio, "log gpio changes, default is 0 (no)");
+MODULE_PARM_DESC(bttv_debug, "debug messages, default is 0 (no)");
+MODULE_PARM_DESC(irq_debug, "irq handler debug messages, default is 0 (no)");
 MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
-MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
-MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+MODULE_PARM_DESC(gbuffers, "number of capture buffers. range 2-32, default 8");
+MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default "
 		 "is 1 (yes) for compatibility with older applications");
-MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
-MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
-MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
-MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
-MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
-MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
-MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
-MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
-MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
-MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(automute, "mute audio on bad/missing video signal, default is 1 (yes)");
+MODULE_PARM_DESC(chroma_agc, "enables the AGC of chroma signal, default is 0 (no)");
+MODULE_PARM_DESC(agc_crush, "enables the luminance AGC crush, default is 1 (yes)");
+MODULE_PARM_DESC(whitecrush_upper, "sets the white crush upper value, default is 207");
+MODULE_PARM_DESC(whitecrush_lower, "sets the white crush lower value, default is 127");
+MODULE_PARM_DESC(vcr_hack, "enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
+MODULE_PARM_DESC(irq_iswitch, "switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio, "ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range, "use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring, "set the luma coring level, default is 0 (no)");
 MODULE_PARM_DESC(video_nr, "video device numbers");
 MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
 MODULE_PARM_DESC(radio_nr, "radio device numbers");
@@ -169,6 +169,17 @@ MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(BTTV_VERSION);
 
+#define V4L2_CID_PRIVATE_COMBFILTER		(V4L2_CID_USER_BTTV_BASE + 0)
+#define V4L2_CID_PRIVATE_AUTOMUTE		(V4L2_CID_USER_BTTV_BASE + 1)
+#define V4L2_CID_PRIVATE_LUMAFILTER		(V4L2_CID_USER_BTTV_BASE + 2)
+#define V4L2_CID_PRIVATE_AGC_CRUSH		(V4L2_CID_USER_BTTV_BASE + 3)
+#define V4L2_CID_PRIVATE_VCR_HACK		(V4L2_CID_USER_BTTV_BASE + 4)
+#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER	(V4L2_CID_USER_BTTV_BASE + 5)
+#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER	(V4L2_CID_USER_BTTV_BASE + 6)
+#define V4L2_CID_PRIVATE_UV_RATIO		(V4L2_CID_USER_BTTV_BASE + 7)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE	(V4L2_CID_USER_BTTV_BASE + 8)
+#define V4L2_CID_PRIVATE_CORING			(V4L2_CID_USER_BTTV_BASE + 9)
+
 /* ----------------------------------------------------------------------- */
 /* sysfs                                                                   */
 
@@ -623,198 +634,6 @@ static const struct bttv_format formats[] = {
 static const unsigned int FORMATS = ARRAY_SIZE(formats);
 
 /* ----------------------------------------------------------------------- */
-
-#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
-#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
-#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
-
-static const struct v4l2_queryctrl no_ctl = {
-	.name  = "42",
-	.flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl bttv_ctls[] = {
-	/* --- video --- */
-	{
-		.id            = V4L2_CID_BRIGHTNESS,
-		.name          = "Brightness",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 256,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_CONTRAST,
-		.name          = "Contrast",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 128,
-		.default_value = 27648,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_SATURATION,
-		.name          = "Saturation",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 128,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_COLOR_KILLER,
-		.name          = "Color killer",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}, {
-		.id            = V4L2_CID_HUE,
-		.name          = "Hue",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 256,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-	/* --- 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       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 65535,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BALANCE,
-		.name          = "Balance",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BASS,
-		.name          = "Bass",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_TREBLE,
-		.name          = "Treble",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-	/* --- private --- */
-	{
-		.id            = V4L2_CID_PRIVATE_CHROMA_AGC,
-		.name          = "chroma agc",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_COMBFILTER,
-		.name          = "combfilter",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
-		.name          = "automute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_LUMAFILTER,
-		.name          = "luma decimation filter",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_AGC_CRUSH,
-		.name          = "agc crush",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_VCR_HACK,
-		.name          = "vcr hack",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
-		.name          = "whitecrush upper",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 0xCF,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
-		.name          = "whitecrush lower",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 0x7F,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_UV_RATIO,
-		.name          = "uv ratio",
-		.minimum       = 0,
-		.maximum       = 100,
-		.step          = 1,
-		.default_value = 50,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
-		.name          = "full luma range",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_CORING,
-		.name          = "coring",
-		.minimum       = 0,
-		.maximum       = 3,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-
-
-
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(int id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
-		if (bttv_ctls[i].id == id)
-			return bttv_ctls+i;
-
-	return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
 /*
@@ -1173,7 +992,7 @@ static int
 audio_mux(struct bttv *btv, int input, int mute)
 {
 	int gpio_val, signal;
-	struct v4l2_control ctrl;
+	struct v4l2_ctrl *ctrl;
 
 	gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
 		   bttv_tvcards[btv->c.type].gpiomask);
@@ -1183,7 +1002,8 @@ audio_mux(struct bttv *btv, int input, int mute)
 	btv->audio = input;
 
 	/* automute */
-	mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+	mute = mute || (btv->opt_automute && (!signal || !btv->users)
+				&& !btv->radio_user);
 
 	if (mute)
 		gpio_val = bttv_tvcards[btv->c.type].gpiomute;
@@ -1205,12 +1025,13 @@ audio_mux(struct bttv *btv, int input, int mute)
 	if (in_interrupt())
 		return 0;
 
-	ctrl.id = V4L2_CID_AUDIO_MUTE;
-	ctrl.value = btv->mute;
-	bttv_call_all(btv, core, s_ctrl, &ctrl);
 	if (btv->sd_msp34xx) {
 		u32 in;
 
+		ctrl = v4l2_ctrl_find(btv->sd_msp34xx->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, btv->mute);
+
 		/* Note: the inputs tuner/radio/extern/intern are translated
 		   to msp routings. This assumes common behavior for all msp3400
 		   based TV cards. When this assumption fails, then the
@@ -1255,9 +1076,19 @@ audio_mux(struct bttv *btv, int input, int mute)
 			       in, MSP_OUTPUT_DEFAULT, 0);
 	}
 	if (btv->sd_tvaudio) {
+		ctrl = v4l2_ctrl_find(btv->sd_tvaudio->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, btv->mute);
 		v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
 				input, 0, 0);
 	}
+	if (btv->sd_tda7432) {
+		ctrl = v4l2_ctrl_find(btv->sd_tda7432->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, btv->mute);
+	}
 	return 0;
 }
 
@@ -1395,8 +1226,6 @@ static void init_irqreg(struct bttv *btv)
 
 static void init_bt848(struct bttv *btv)
 {
-	int val;
-
 	if (bttv_tvcards[btv->c.type].no_video) {
 		/* very basic init only */
 		init_irqreg(btv);
@@ -1416,30 +1245,10 @@ static void init_bt848(struct bttv *btv)
 		BT848_GPIO_DMA_CTL_GPINTI,
 		BT848_GPIO_DMA_CTL);
 
-	val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-	btwrite(val, BT848_E_SCLOOP);
-	btwrite(val, BT848_O_SCLOOP);
-
 	btwrite(0x20, BT848_E_VSCALE_HI);
 	btwrite(0x20, BT848_O_VSCALE_HI);
-	btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
-		BT848_ADC);
 
-	btwrite(whitecrush_upper, BT848_WC_UP);
-	btwrite(whitecrush_lower, BT848_WC_DOWN);
-
-	if (btv->opt_lumafilter) {
-		btwrite(0, BT848_E_CONTROL);
-		btwrite(0, BT848_O_CONTROL);
-	} else {
-		btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
-		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
-	}
-
-	bt848_bright(btv,   btv->bright);
-	bt848_hue(btv,      btv->hue);
-	bt848_contrast(btv, btv->contrast);
-	bt848_sat(btv,      btv->saturation);
+	v4l2_ctrl_handler_setup(&btv->ctrl_handler);
 
 	/* interrupt */
 	init_irqreg(btv);
@@ -1461,103 +1270,26 @@ static void bttv_reinit_bt848(struct bttv *btv)
 	set_input(btv, btv->input, btv->tvnorm);
 }
 
-static int bttv_g_ctrl(struct file *file, void *priv,
-					struct v4l2_control *c)
+static int bttv_s_ctrl(struct v4l2_ctrl *c)
 {
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		c->value = btv->bright;
-		break;
-	case V4L2_CID_HUE:
-		c->value = btv->hue;
-		break;
-	case V4L2_CID_CONTRAST:
-		c->value = btv->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		c->value = btv->saturation;
-		break;
-	case V4L2_CID_COLOR_KILLER:
-		c->value = btv->opt_color_killer;
-		break;
-
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_all(btv, core, g_ctrl, c);
-		break;
-
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		c->value = btv->opt_chroma_agc;
-		break;
-	case V4L2_CID_PRIVATE_COMBFILTER:
-		c->value = btv->opt_combfilter;
-		break;
-	case V4L2_CID_PRIVATE_LUMAFILTER:
-		c->value = btv->opt_lumafilter;
-		break;
-	case V4L2_CID_PRIVATE_AUTOMUTE:
-		c->value = btv->opt_automute;
-		break;
-	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		c->value = btv->opt_adc_crush;
-		break;
-	case V4L2_CID_PRIVATE_VCR_HACK:
-		c->value = btv->opt_vcr_hack;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		c->value = btv->opt_whitecrush_upper;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		c->value = btv->opt_whitecrush_lower;
-		break;
-	case V4L2_CID_PRIVATE_UV_RATIO:
-		c->value = btv->opt_uv_ratio;
-		break;
-	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		c->value = btv->opt_full_luma_range;
-		break;
-	case V4L2_CID_PRIVATE_CORING:
-		c->value = btv->opt_coring;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int bttv_s_ctrl(struct file *file, void *f,
-					struct v4l2_control *c)
-{
-	int err;
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (0 != err)
-		return err;
+	struct bttv *btv = container_of(c->handler, struct bttv, ctrl_handler);
+	int val;
 
 	switch (c->id) {
 	case V4L2_CID_BRIGHTNESS:
-		bt848_bright(btv, c->value);
+		bt848_bright(btv, c->val);
 		break;
 	case V4L2_CID_HUE:
-		bt848_hue(btv, c->value);
+		bt848_hue(btv, c->val);
 		break;
 	case V4L2_CID_CONTRAST:
-		bt848_contrast(btv, c->value);
+		bt848_contrast(btv, c->val);
 		break;
 	case V4L2_CID_SATURATION:
-		bt848_sat(btv, c->value);
+		bt848_sat(btv, c->val);
 		break;
 	case V4L2_CID_COLOR_KILLER:
-		btv->opt_color_killer = c->value;
-		if (btv->opt_color_killer) {
+		if (c->val) {
 			btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
 			btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
 		} else {
@@ -1566,36 +1298,22 @@ static int bttv_s_ctrl(struct file *file, void *f,
 		}
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		audio_mute(btv, c->value);
-		/* fall through */
-	case V4L2_CID_AUDIO_VOLUME:
-		if (btv->volume_gpio)
-			btv->volume_gpio(btv, c->value);
-
-		bttv_call_all(btv, core, s_ctrl, c);
+		audio_mute(btv, c->val);
 		break;
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_all(btv, core, s_ctrl, c);
+	case V4L2_CID_AUDIO_VOLUME:
+		btv->volume_gpio(btv, c->val);
 		break;
 
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		btv->opt_chroma_agc = c->value;
-		if (btv->opt_chroma_agc) {
-			btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
-			btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
-		} else {
-			btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
-			btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
-		}
+	case V4L2_CID_CHROMA_AGC:
+		val = c->val ? BT848_SCLOOP_CAGC : 0;
+		btwrite(val, BT848_E_SCLOOP);
+		btwrite(val, BT848_O_SCLOOP);
 		break;
 	case V4L2_CID_PRIVATE_COMBFILTER:
-		btv->opt_combfilter = c->value;
+		btv->opt_combfilter = c->val;
 		break;
 	case V4L2_CID_PRIVATE_LUMAFILTER:
-		btv->opt_lumafilter = c->value;
-		if (btv->opt_lumafilter) {
+		if (c->val) {
 			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
 			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
 		} else {
@@ -1604,36 +1322,31 @@ static int bttv_s_ctrl(struct file *file, void *f,
 		}
 		break;
 	case V4L2_CID_PRIVATE_AUTOMUTE:
-		btv->opt_automute = c->value;
+		btv->opt_automute = c->val;
 		break;
 	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		btv->opt_adc_crush = c->value;
 		btwrite(BT848_ADC_RESERVED |
-				(btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+				(c->val ? BT848_ADC_CRUSH : 0),
 				BT848_ADC);
 		break;
 	case V4L2_CID_PRIVATE_VCR_HACK:
-		btv->opt_vcr_hack = c->value;
+		btv->opt_vcr_hack = c->val;
 		break;
 	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		btv->opt_whitecrush_upper = c->value;
-		btwrite(c->value, BT848_WC_UP);
+		btwrite(c->val, BT848_WC_UP);
 		break;
 	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		btv->opt_whitecrush_lower = c->value;
-		btwrite(c->value, BT848_WC_DOWN);
+		btwrite(c->val, BT848_WC_DOWN);
 		break;
 	case V4L2_CID_PRIVATE_UV_RATIO:
-		btv->opt_uv_ratio = c->value;
+		btv->opt_uv_ratio = c->val;
 		bt848_sat(btv, btv->saturation);
 		break;
 	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		btv->opt_full_luma_range = c->value;
-		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+		btaor((c->val << 7), ~BT848_OFORM_RANGE, BT848_OFORM);
 		break;
 	case V4L2_CID_PRIVATE_CORING:
-		btv->opt_coring = c->value;
-		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+		btaor((c->val << 5), ~BT848_OFORM_CORE32, BT848_OFORM);
 		break;
 	default:
 		return -EINVAL;
@@ -1643,6 +1356,121 @@ static int bttv_s_ctrl(struct file *file, void *f,
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops bttv_ctrl_ops = {
+	.s_ctrl = bttv_s_ctrl,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_combfilter = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_COMBFILTER,
+	.name = "Comb Filter",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_automute = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_AUTOMUTE,
+	.name = "Auto Mute",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_lumafilter = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_LUMAFILTER,
+	.name = "Luma Decimation Filter",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_agc_crush = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_AGC_CRUSH,
+	.name = "AGC Crush",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_vcr_hack = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_VCR_HACK,
+	.name = "VCR Hack",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_lower = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
+	.name = "Whitecrush Lower",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 255,
+	.step = 1,
+	.def = 0x7f,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_upper = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
+	.name = "Whitecrush Upper",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 255,
+	.step = 1,
+	.def = 0xcf,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_uv_ratio = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_UV_RATIO,
+	.name = "UV Ratio",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 100,
+	.step = 1,
+	.def = 50,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_full_luma = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+	.name = "Full Luma Range",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_coring = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_CORING,
+	.name = "Coring",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 3,
+	.step = 1,
+};
+
+
+/* ----------------------------------------------------------------------- */
+
 void bttv_gpio_tracking(struct bttv *btv, char *comment)
 {
 	unsigned int outbits, data;
@@ -2047,9 +1875,11 @@ static int bttv_s_frequency(struct file *file, void *priv,
 
 static int bttv_log_status(struct file *file, void *f)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct bttv_fh *fh  = f;
 	struct bttv *btv = fh->btv;
 
+	v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name);
 	bttv_call_all(btv, core, log_status);
 	return 0;
 }
@@ -2939,30 +2769,6 @@ static int bttv_streamoff(struct file *file, void *priv,
 	return 0;
 }
 
-static int bttv_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *c)
-{
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-	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;
-
-	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
-		*c = no_ctl;
-	else {
-		ctrl = ctrl_by_id(c->id);
-
-		*c = (NULL != ctrl) ? *ctrl : no_ctl;
-	}
-
-	return 0;
-}
-
 static int bttv_g_parm(struct file *file, void *f,
 				struct v4l2_streamparm *parm)
 {
@@ -3246,6 +3052,7 @@ static int bttv_open(struct file *file)
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
 	if (unlikely(!fh))
 		return -ENOMEM;
+	btv->users++;
 	file->private_data = fh;
 
 	*fh = btv->init;
@@ -3270,7 +3077,6 @@ static int bttv_open(struct file *file)
 	set_tvnorm(btv,btv->tvnorm);
 	set_input(btv, btv->input, btv->tvnorm);
 
-	btv->users++;
 
 	/* The V4L2 spec requires one global set of cropping parameters
 	   which only change on request. These are stored in btv->crop[1].
@@ -3332,7 +3138,7 @@ static int bttv_release(struct file *file)
 	bttv_field_count(btv);
 
 	if (!btv->users)
-		audio_mute(btv, 1);
+		audio_mute(btv, btv->mute);
 
 	return 0;
 }
@@ -3381,9 +3187,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_enum_input              = bttv_enum_input,
 	.vidioc_g_input                 = bttv_g_input,
 	.vidioc_s_input                 = bttv_s_input,
-	.vidioc_queryctrl               = bttv_queryctrl,
-	.vidioc_g_ctrl                  = bttv_g_ctrl,
-	.vidioc_s_ctrl                  = bttv_s_ctrl,
 	.vidioc_streamon                = bttv_streamon,
 	.vidioc_streamoff               = bttv_streamoff,
 	.vidioc_g_tuner                 = bttv_g_tuner,
@@ -3492,24 +3295,6 @@ static int radio_s_tuner(struct file *file, void *priv,
 	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_ctl;
-
-	return 0;
-}
-
 static ssize_t radio_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3551,11 +3336,9 @@ static const struct v4l2_file_operations radio_fops =
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_querycap        = bttv_querycap,
+	.vidioc_log_status	= bttv_log_status,
 	.vidioc_g_tuner         = radio_g_tuner,
 	.vidioc_s_tuner         = radio_s_tuner,
-	.vidioc_queryctrl       = radio_queryctrl,
-	.vidioc_g_ctrl          = bttv_g_ctrl,
-	.vidioc_s_ctrl          = bttv_s_ctrl,
 	.vidioc_g_frequency     = bttv_g_frequency,
 	.vidioc_s_frequency     = bttv_s_frequency,
 };
@@ -4201,6 +3984,7 @@ static int bttv_register_video(struct bttv *btv)
 	btv->radio_dev = vdev_init(btv, &radio_template, "radio");
 	if (NULL == btv->radio_dev)
 		goto err;
+	btv->radio_dev->ctrl_handler = &btv->radio_ctrl_handler;
 	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
 				  radio_nr[btv->c.nr]) < 0)
 		goto err;
@@ -4239,6 +4023,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	int result;
 	unsigned char lat;
 	struct bttv *btv;
+	struct v4l2_ctrl_handler *hdl;
 
 	if (bttv_num == BTTV_MAX)
 		return -ENOMEM;
@@ -4298,6 +4083,10 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 		pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
 		goto fail0;
 	}
+	hdl = &btv->ctrl_handler;
+	v4l2_ctrl_handler_init(hdl, 20);
+	btv->c.v4l2_dev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(&btv->radio_ctrl_handler, 6);
 
 	btv->revision = dev->revision;
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
@@ -4334,16 +4123,19 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 
 	/* init options from insmod args */
 	btv->opt_combfilter = combfilter;
-	btv->opt_lumafilter = lumafilter;
+	bttv_ctrl_combfilter.def = combfilter;
+	bttv_ctrl_lumafilter.def = lumafilter;
 	btv->opt_automute   = automute;
-	btv->opt_chroma_agc = chroma_agc;
-	btv->opt_adc_crush  = adc_crush;
+	bttv_ctrl_automute.def = automute;
+	bttv_ctrl_agc_crush.def = agc_crush;
 	btv->opt_vcr_hack   = vcr_hack;
-	btv->opt_whitecrush_upper  = whitecrush_upper;
-	btv->opt_whitecrush_lower  = whitecrush_lower;
+	bttv_ctrl_vcr_hack.def = vcr_hack;
+	bttv_ctrl_whitecrush_upper.def = whitecrush_upper;
+	bttv_ctrl_whitecrush_lower.def = whitecrush_lower;
 	btv->opt_uv_ratio   = uv_ratio;
-	btv->opt_full_luma_range   = full_luma_range;
-	btv->opt_coring     = coring;
+	bttv_ctrl_uv_ratio.def = uv_ratio;
+	bttv_ctrl_full_luma.def = full_luma_range;
+	bttv_ctrl_coring.def = coring;
 
 	/* fill struct bttv with some useful defaults */
 	btv->init.btv         = btv;
@@ -4354,6 +4146,34 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	btv->init.height      = 240;
 	btv->input = 0;
 
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 0xff80, 0x80, 0x6c00);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xff80, 0x80, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_HUE, 0, 0xff00, 0x100, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_CHROMA_AGC, 0, 1, 1, !!chroma_agc);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	if (btv->volume_gpio)
+		v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 0xff00, 0x100, 0xff00);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_combfilter, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_automute, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_lumafilter, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_agc_crush, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_vcr_hack, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_lower, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_upper, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_uv_ratio, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_full_luma, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_coring, NULL);
+
 	/* initialize hardware */
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"pre-init");
@@ -4381,20 +4201,26 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 		btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
 	}
 	init_irqreg(btv);
+	v4l2_ctrl_handler_setup(hdl);
 
+	if (hdl->error) {
+		result = hdl->error;
+		goto fail2;
+	}
 	/* register video4linux + input */
 	if (!bttv_tvcards[btv->c.type].no_video) {
-		bttv_register_video(btv);
-		bt848_bright(btv,32768);
-		bt848_contrast(btv, 27648);
-		bt848_hue(btv,32768);
-		bt848_sat(btv,32768);
-		audio_mute(btv, 1);
+		v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
+				v4l2_ctrl_radio_filter);
+		if (btv->radio_ctrl_handler.error) {
+			result = btv->radio_ctrl_handler.error;
+			goto fail2;
+		}
 		set_input(btv, 0, btv->tvnorm);
 		bttv_crop_reset(&btv->crop[0], btv->tvnorm);
 		btv->crop[1] = btv->crop[0]; /* current = default */
 		disclaim_vbi_lines(btv);
 		disclaim_video_lines(btv);
+		bttv_register_video(btv);
 	}
 
 	/* add subdevices and autoload dvb-bt8xx if needed */
@@ -4416,6 +4242,8 @@ fail2:
 	free_irq(btv->c.pci->irq,btv);
 
 fail1:
+	v4l2_ctrl_handler_free(&btv->ctrl_handler);
+	v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
 	v4l2_device_unregister(&btv->c.v4l2_dev);
 
 fail0:
@@ -4457,9 +4285,11 @@ static void bttv_remove(struct pci_dev *pci_dev)
 	bttv_unregister_video(btv);
 
 	/* free allocated memory */
+	v4l2_ctrl_handler_free(&btv->ctrl_handler);
+	v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
 	btcx_riscmem_free(btv->c.pci,&btv->main);
 
-	/* free ressources */
+	/* free resources */
 	free_irq(btv->c.pci->irq,btv);
 	iounmap(btv->bt848_mmio);
 	release_mem_region(pci_resource_start(btv->c.pci,0),
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 528e03e..c3882ef 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -33,9 +33,10 @@
 #include <linux/input.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
+#include <linux/device.h>
 #include <asm/io.h>
 #include <media/v4l2-common.h>
-#include <linux/device.h>
+#include <media/v4l2-ctrls.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/tveeprom.h>
 #include <media/rc-core.h>
@@ -393,12 +394,17 @@ struct bttv {
 	wait_queue_head_t          i2c_queue;
 	struct v4l2_subdev 	  *sd_msp34xx;
 	struct v4l2_subdev 	  *sd_tvaudio;
+	struct v4l2_subdev	  *sd_tda7432;
 
 	/* video4linux (1) */
 	struct video_device *video_dev;
 	struct video_device *radio_dev;
 	struct video_device *vbi_dev;
 
+	/* controls */
+	struct v4l2_ctrl_handler   ctrl_handler;
+	struct v4l2_ctrl_handler   radio_ctrl_handler;
+
 	/* infrared remote */
 	int has_remote;
 	struct bttv_ir *remote;
@@ -426,17 +432,9 @@ struct bttv {
 
 	/* various options */
 	int opt_combfilter;
-	int opt_lumafilter;
 	int opt_automute;
-	int opt_chroma_agc;
-	int opt_color_killer;
-	int opt_adc_crush;
 	int opt_vcr_hack;
-	int opt_whitecrush_upper;
-	int opt_whitecrush_lower;
 	int opt_uv_ratio;
-	int opt_full_luma_range;
-	int opt_coring;
 
 	/* radio data/state */
 	int has_radio;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index dcd6374..1d00ca9 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -146,6 +146,11 @@ enum v4l2_colorfx {
  * of controls. We reserve 16 controls for this driver. */
 #define V4L2_CID_USER_MEYE_BASE			(V4L2_CID_USER_BASE + 0x1000)
 
+/* The base for the bttv driver controls.
+ * We reserve 32 controls for this driver. */
+#define V4L2_CID_USER_BTTV_BASE			(V4L2_CID_USER_BASE + 0x1010)
+
+
 /* MPEG-class control IDs */
 
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 13/19] bttv: add support for control events.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (10 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 12/19] bttv: " Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 14/19] bttv: fix priority handling Hans Verkuil
                     ` (5 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 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/bt8xx/bttv-driver.c |   48 ++++++++++++++++++++++++---------
 drivers/media/pci/bt8xx/bttvp.h       |    4 +++
 2 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 09f58f3..96aa2c9 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -49,6 +49,7 @@
 #include "bttvp.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
@@ -2982,34 +2983,43 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 	struct bttv_fh *fh = file->private_data;
 	struct bttv_buffer *buf;
 	enum v4l2_field field;
-	unsigned int rc = POLLERR;
+	unsigned int rc = 0;
+	unsigned long req_events = poll_requested_events(wait);
+
+	if (v4l2_event_pending(&fh->fh))
+		rc = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
+
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return rc;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
-			return POLLERR;
-		return videobuf_poll_stream(file, &fh->vbi, wait);
+			return rc | POLLERR;
+		return rc | videobuf_poll_stream(file, &fh->vbi, wait);
 	}
 
 	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
 		/* streaming capture */
 		if (list_empty(&fh->cap.stream))
-			goto err;
+			return rc | POLLERR;
 		buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
 	} else {
 		/* read() capture */
 		if (NULL == fh->cap.read_buf) {
 			/* need to capture a new frame */
 			if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
-				goto err;
+				return rc | POLLERR;
 			fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
 			if (NULL == fh->cap.read_buf)
-				goto err;
+				return rc | POLLERR;
 			fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
 			field = videobuf_next_field(&fh->cap);
 			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
 				kfree (fh->cap.read_buf);
 				fh->cap.read_buf = NULL;
-				goto err;
+				return rc | POLLERR;
 			}
 			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
 			fh->cap.read_off = 0;
@@ -3020,10 +3030,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == VIDEOBUF_DONE ||
 	    buf->vb.state == VIDEOBUF_ERROR)
-		rc =  POLLIN|POLLRDNORM;
-	else
-		rc = 0;
-err:
+		rc = rc | POLLIN|POLLRDNORM;
 	return rc;
 }
 
@@ -3056,6 +3063,7 @@ static int bttv_open(struct file *file)
 	file->private_data = fh;
 
 	*fh = btv->init;
+	v4l2_fh_init(&fh->fh, vdev);
 
 	fh->type = type;
 	fh->ov.setup_ok = 0;
@@ -3095,6 +3103,7 @@ static int bttv_open(struct file *file)
 	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
 	bttv_field_count(btv);
+	v4l2_fh_add(&fh->fh);
 	return 0;
 }
 
@@ -3132,7 +3141,6 @@ static int bttv_release(struct file *file)
 	videobuf_mmap_free(&fh->vbi);
 	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
-	kfree(fh);
 
 	btv->users--;
 	bttv_field_count(btv);
@@ -3140,6 +3148,9 @@ static int bttv_release(struct file *file)
 	if (!btv->users)
 		audio_mute(btv, btv->mute);
 
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	kfree(fh);
 	return 0;
 }
 
@@ -3203,6 +3214,8 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_s_frequency             = bttv_s_frequency,
 	.vidioc_log_status		= bttv_log_status,
 	.vidioc_querystd		= bttv_querystd,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 	.vidioc_g_chip_ident		= bttv_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register		= bttv_g_register,
@@ -3315,10 +3328,17 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
 {
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
+	unsigned long req_events = poll_requested_events(wait);
 	struct saa6588_command cmd;
+	unsigned int res = 0;
+
+	if (v4l2_event_pending(&fh->fh))
+		res = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
 	cmd.instance = file;
 	cmd.event_list = wait;
-	cmd.result = -ENODEV;
+	cmd.result = res;
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
 
 	return cmd.result;
@@ -3341,6 +3361,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_s_tuner         = radio_s_tuner,
 	.vidioc_g_frequency     = bttv_g_frequency,
 	.vidioc_s_frequency     = bttv_s_frequency,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device radio_template = {
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index c3882ef..288cfd8 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/tveeprom.h>
 #include <media/rc-core.h>
@@ -215,6 +216,9 @@ struct bttv_crop {
 };
 
 struct bttv_fh {
+	/* This must be the first field in this struct */
+	struct v4l2_fh		 fh;
+
 	struct bttv              *btv;
 	int resources;
 #ifdef VIDIOC_G_PRIORITY
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 14/19] bttv: fix priority handling.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (11 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 13/19] bttv: add support for control events Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 15/19] bttv: use centralized std and implement g_std Hans Verkuil
                     ` (4 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Replace the - incorrect - manual priority handling with the core priority
implementation.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   61 ++++-----------------------------
 drivers/media/pci/bt8xx/bttvp.h       |    6 ----
 2 files changed, 6 insertions(+), 61 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 96aa2c9..559c1d9 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1706,11 +1706,7 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 	unsigned int i;
-	int err;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (err)
-		goto err;
+	int err = 0;
 
 	for (i = 0; i < BTTV_TVNORMS; i++)
 		if (*id & bttv_tvnorms[i].v4l2_id)
@@ -1793,11 +1789,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-	int err;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (err)
-		return err;
 
 	if (i >= bttv_tvcards[btv->c.type].video_inputs)
 		return -EINVAL;
@@ -1811,15 +1802,10 @@ static int bttv_s_tuner(struct file *file, void *priv,
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-	int err;
 
 	if (t->index)
 		return -EINVAL;
 
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (err)
-		return err;
-
 	bttv_call_all(btv, tuner, s_tuner, t);
 
 	if (btv->audio_mode_gpio)
@@ -1862,14 +1848,10 @@ static int bttv_s_frequency(struct file *file, void *priv,
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-	int err;
 
 	if (f->tuner)
 		return -EINVAL;
 
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (err)
-		return err;
 	bttv_set_frequency(btv, f);
 	return 0;
 }
@@ -2808,28 +2790,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-
-	*p = v4l2_prio_max(&btv->prio);
-
-	return 0;
-}
-
-static int bttv_s_priority(struct file *file, void *f,
-					enum v4l2_priority prio)
-{
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-	int	rc;
-
-	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-
-	return rc;
-}
-
 static int bttv_cropcap(struct file *file, void *priv,
 				struct v4l2_cropcap *cap)
 {
@@ -2882,11 +2842,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 	/* Make sure tvnorm, vbi_end and the current cropping
 	   parameters remain consistent until we're done. Note
 	   read() may change vbi_end in check_alloc_btres_lock(). */
-	retval = v4l2_prio_check(&btv->prio, fh->prio);
-	if (0 != retval) {
-		return retval;
-	}
-
 	retval = -EBUSY;
 
 	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
@@ -3068,8 +3023,6 @@ static int bttv_open(struct file *file)
 	fh->type = type;
 	fh->ov.setup_ok = 0;
 
-	v4l2_prio_open(&btv->prio, &fh->prio);
-
 	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
 			    &btv->c.pci->dev, &btv->s_lock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -3139,7 +3092,6 @@ static int bttv_release(struct file *file)
 
 	videobuf_mmap_free(&fh->cap);
 	videobuf_mmap_free(&fh->vbi);
-	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
 
 	btv->users--;
@@ -3207,8 +3159,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_g_fbuf                  = bttv_g_fbuf,
 	.vidioc_s_fbuf                  = bttv_s_fbuf,
 	.vidioc_overlay                 = bttv_overlay,
-	.vidioc_g_priority              = bttv_g_priority,
-	.vidioc_s_priority              = bttv_s_priority,
 	.vidioc_g_parm                  = bttv_g_parm,
 	.vidioc_g_frequency             = bttv_g_frequency,
 	.vidioc_s_frequency             = bttv_s_frequency,
@@ -3249,13 +3199,13 @@ static int radio_open(struct file *file)
 		return -ENOMEM;
 	file->private_data = fh;
 	*fh = btv->init;
-
-	v4l2_prio_open(&btv->prio, &fh->prio);
+	v4l2_fh_init(&fh->fh, vdev);
 
 	btv->radio_user++;
 
 	bttv_call_all(btv, tuner, s_radio);
 	audio_input(btv,TVAUDIO_INPUT_RADIO);
+	v4l2_fh_add(&fh->fh);
 
 	return 0;
 }
@@ -3266,8 +3216,9 @@ static int radio_release(struct file *file)
 	struct bttv *btv = fh->btv;
 	struct saa6588_command cmd;
 
-	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 
 	btv->radio_user--;
@@ -3929,6 +3880,7 @@ static struct video_device *vdev_init(struct bttv *btv,
 	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = bttv_debug;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	video_set_drvdata(vfd, btv);
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
@@ -4067,7 +4019,6 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	INIT_LIST_HEAD(&btv->c.subs);
 	INIT_LIST_HEAD(&btv->capture);
 	INIT_LIST_HEAD(&btv->vcapture);
-	v4l2_prio_init(&btv->prio);
 
 	init_timer(&btv->timeout);
 	btv->timeout.function = bttv_irq_timeout;
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 288cfd8..12cc4eb 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -221,9 +221,6 @@ struct bttv_fh {
 
 	struct bttv              *btv;
 	int resources;
-#ifdef VIDIOC_G_PRIORITY
-	enum v4l2_priority       prio;
-#endif
 	enum v4l2_buf_type       type;
 
 	/* video capture */
@@ -420,9 +417,6 @@ struct bttv {
 	spinlock_t s_lock;
 	struct mutex lock;
 	int resources;
-#ifdef VIDIOC_G_PRIORITY
-	struct v4l2_prio_state prio;
-#endif
 
 	/* video state */
 	unsigned int input;
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 15/19] bttv: use centralized std and implement g_std.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (12 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 14/19] bttv: fix priority handling Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 16/19] bttv: there may be multiple tvaudio/tda7432 devices Hans Verkuil
                     ` (3 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The 'current_norm' field cannot be used if multiple device nodes (video and
vbi in this case) set the same std.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   13 ++++++++++++-
 drivers/media/pci/bt8xx/bttvp.h       |    1 +
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 559c1d9..98b8fd2 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1716,6 +1716,7 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
 		goto err;
 	}
 
+	btv->std = *id;
 	set_tvnorm(btv, i);
 
 err:
@@ -1723,6 +1724,15 @@ err:
 	return err;
 }
 
+static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+
+	*id = btv->std;
+	return 0;
+}
+
 static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
 {
 	struct bttv_fh *fh = f;
@@ -3147,6 +3157,7 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_qbuf                    = bttv_qbuf,
 	.vidioc_dqbuf                   = bttv_dqbuf,
 	.vidioc_s_std                   = bttv_s_std,
+	.vidioc_g_std                   = bttv_g_std,
 	.vidioc_enum_input              = bttv_enum_input,
 	.vidioc_g_input                 = bttv_g_input,
 	.vidioc_s_input                 = bttv_s_input,
@@ -3177,7 +3188,6 @@ static struct video_device bttv_video_template = {
 	.fops         = &bttv_fops,
 	.ioctl_ops    = &bttv_ioctl_ops,
 	.tvnorms      = BTTV_NORMS,
-	.current_norm = V4L2_STD_PAL,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -4173,6 +4183,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 		bttv_set_frequency(btv, &init_freq);
 		btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
 	}
+	btv->std = V4L2_STD_PAL;
 	init_irqreg(btv);
 	v4l2_ctrl_handler_setup(hdl);
 
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 12cc4eb..86d67bb 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -424,6 +424,7 @@ struct bttv {
 	unsigned int mute;
 	unsigned long tv_freq;
 	unsigned int tvnorm;
+	v4l2_std_id std;
 	int hue, contrast, bright, saturation;
 	struct v4l2_framebuffer fbuf;
 	unsigned int field_count;
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 16/19] bttv: there may be multiple tvaudio/tda7432 devices.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (13 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 15/19] bttv: use centralized std and implement g_std Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 17/19] bttv: fix g_tuner capabilities override Hans Verkuil
                     ` (2 subsequent siblings)
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Probe for additional tvaudio devices, and allow tvaudio+tda7432 to
co-exist. My STB TV PCI FM bttv card has a tda7432, a tda9850 and a
tea6420 and with this patch it finally works again (probably for the
first time in many years).

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-cards.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index 682ed89..fa0faaa 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -3547,6 +3547,16 @@ void bttv_init_card2(struct bttv *btv)
 	if (btv->sd_msp34xx)
 		return;
 
+	/* Now see if we can find one of the tvaudio devices. */
+	btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+		&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+	if (btv->sd_tvaudio) {
+		/* There may be two tvaudio chips on the card, so try to
+		   find another. */
+		v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+	}
+
 	/* it might also be a tda7432. */
 	if (!bttv_tvcards[btv->c.type].no_tda7432) {
 		static const unsigned short addrs[] = {
@@ -3559,10 +3569,6 @@ void bttv_init_card2(struct bttv *btv)
 		if (btv->sd_tda7432)
 			return;
 	}
-
-	/* Now see if we can find one of the tvaudio devices. */
-	btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-		&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
 	if (btv->sd_tvaudio)
 		return;
 
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 17/19] bttv: fix g_tuner capabilities override.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (14 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 16/19] bttv: there may be multiple tvaudio/tda7432 devices Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 18/19] bttv: fix try_fmt_vid_overlay and setup initial overlay size Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 19/19] bttv: do not switch to the radio tuner unless it is accessed Hans Verkuil
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

The capability field of v4l2_tuner should be ORed by the various subdevs
and by the main driver. In this case the stereo capability was dropped.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/tvaudio.c           |    2 +-
 drivers/media/pci/bt8xx/bttv-driver.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
index e3b33b7..4c91b35 100644
--- a/drivers/media/i2c/tvaudio.c
+++ b/drivers/media/i2c/tvaudio.c
@@ -1803,7 +1803,7 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 
 	vt->audmode = chip->audmode;
 	vt->rxsubchans = desc->getrxsubchans(chip);
-	vt->capability = V4L2_TUNER_CAP_STEREO |
+	vt->capability |= V4L2_TUNER_CAP_STEREO |
 		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
 
 	return 0;
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 98b8fd2..0492fff 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2787,9 +2787,9 @@ static int bttv_g_tuner(struct file *file, void *priv,
 		return -EINVAL;
 
 	t->rxsubchans = V4L2_TUNER_SUB_MONO;
+	t->capability = V4L2_TUNER_CAP_NORM;
 	bttv_call_all(btv, tuner, g_tuner, t);
 	strcpy(t->name, "Television");
-	t->capability = V4L2_TUNER_CAP_NORM;
 	t->type       = V4L2_TUNER_ANALOG_TV;
 	if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
 		t->signal = 0xffff;
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 18/19] bttv: fix try_fmt_vid_overlay and setup initial overlay size.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (15 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 17/19] bttv: fix g_tuner capabilities override Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  2013-02-10 12:50   ` [REVIEWv2 PATCH 19/19] bttv: do not switch to the radio tuner unless it is accessed Hans Verkuil
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

try_fmt_vid_overlay should map incorrect sizes and fields to valid values.

It also expects that an initial overlay size is defined so g_fmt_vid_overlay
returns valid information.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   44 +++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 0492fff..6518a61 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2111,22 +2111,33 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
    may also adjust the current cropping parameters to get closer
    to the desired window size. */
 static int
-verify_window_lock		(struct bttv_fh *               fh,
-			 struct v4l2_window *           win,
-			 int                            adjust_size,
-			 int                            adjust_crop)
+verify_window_lock(struct bttv_fh *fh, struct v4l2_window *win,
+			 int adjust_size, int adjust_crop)
 {
 	enum v4l2_field field;
 	unsigned int width_mask;
 	int rc;
 
-	if (win->w.width  < 48 || win->w.height < 32)
-		return -EINVAL;
+	if (win->w.width < 48)
+		win->w.width = 48;
+	if (win->w.height < 32)
+		win->w.height = 32;
 	if (win->clipcount > 2048)
-		return -EINVAL;
+		win->clipcount = 2048;
 
+	win->chromakey = 0;
+	win->global_alpha = 0;
 	field = win->field;
 
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		field = V4L2_FIELD_ANY;
+		break;
+	}
 	if (V4L2_FIELD_ANY == field) {
 		__s32 height2;
 
@@ -2135,18 +2146,11 @@ verify_window_lock		(struct bttv_fh *               fh,
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_TOP;
 	}
-	switch (field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_INTERLACED:
-		break;
-	default:
-		return -EINVAL;
-	}
+	win->field = field;
 
-	/* 4-byte alignment. */
 	if (NULL == fh->ovfmt)
 		return -EINVAL;
+	/* 4-byte alignment. */
 	width_mask = ~0;
 	switch (fh->ovfmt->depth) {
 	case 8:
@@ -2171,8 +2175,6 @@ verify_window_lock		(struct bttv_fh *               fh,
 			       adjust_size, adjust_crop);
 	if (0 != rc)
 		return rc;
-
-	win->field = field;
 	return 0;
 }
 
@@ -2407,9 +2409,10 @@ static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
 {
 	struct bttv_fh *fh = priv;
 
-	return verify_window_lock(fh, &f->fmt.win,
+	verify_window_lock(fh, &f->fmt.win,
 			/* adjust_size */ 1,
 			/* adjust_crop */ 0);
+	return 0;
 }
 
 static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
@@ -4127,6 +4130,9 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 	btv->init.width       = 320;
 	btv->init.height      = 240;
+	btv->init.ov.w.width  = 320;
+	btv->init.ov.w.height = 240;
+	btv->init.ov.field    = V4L2_FIELD_INTERLACED;
 	btv->input = 0;
 
 	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
-- 
1.7.10.4


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

* [REVIEWv2 PATCH 19/19] bttv: do not switch to the radio tuner unless it is accessed.
  2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
                     ` (16 preceding siblings ...)
  2013-02-10 12:50   ` [REVIEWv2 PATCH 18/19] bttv: fix try_fmt_vid_overlay and setup initial overlay size Hans Verkuil
@ 2013-02-10 12:50   ` Hans Verkuil
  17 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2013-02-10 12:50 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

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

Just opening the radio tuner should not cause a switch to the radio tuner.
Only after calling g/s_tuner or g/s_frequency should this happen.

This prevents audio being unmuted as soon as the driver is loaded because
some process opens /dev/radioX just to see what sort of node it is, which
switches on the radio tuner and unmutes audio.

This code can be improved further by actually keeping track of who owns the
tuner and returning -EBUSY if switching tuner modes will cause problems.

But for now just fix the annoying case where on boot the radio turns on
automatically.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/bt8xx/bttv-driver.c |   23 ++++++++++++++++++++---
 drivers/media/pci/bt8xx/bttvp.h       |    1 +
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 6518a61..8610b6a 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1004,7 +1004,7 @@ audio_mux(struct bttv *btv, int input, int mute)
 
 	/* automute */
 	mute = mute || (btv->opt_automute && (!signal || !btv->users)
-				&& !btv->radio_user);
+				&& !btv->has_radio_tuner);
 
 	if (mute)
 		gpio_val = bttv_tvcards[btv->c.type].gpiomute;
@@ -1701,6 +1701,16 @@ static struct videobuf_queue_ops bttv_video_qops = {
 	.buf_release  = buffer_release,
 };
 
+static void radio_enable(struct bttv *btv)
+{
+	/* Switch to the radio tuner */
+	if (!btv->has_radio_tuner) {
+		btv->has_radio_tuner = 1;
+		bttv_call_all(btv, tuner, s_radio);
+		audio_input(btv, TVAUDIO_INPUT_RADIO);
+	}
+}
+
 static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
 	struct bttv_fh *fh  = priv;
@@ -1832,6 +1842,8 @@ static int bttv_g_frequency(struct file *file, void *priv,
 	if (f->tuner)
 		return -EINVAL;
 
+	if (f->type == V4L2_TUNER_RADIO)
+		radio_enable(btv);
 	f->frequency = f->type == V4L2_TUNER_RADIO ?
 				btv->radio_freq : btv->tv_freq;
 
@@ -1845,6 +1857,7 @@ static void bttv_set_frequency(struct bttv *btv, struct v4l2_frequency *f)
 	   frequency before assigning radio/tv_freq. */
 	bttv_call_all(btv, tuner, g_frequency, f);
 	if (f->type == V4L2_TUNER_RADIO) {
+		radio_enable(btv);
 		btv->radio_freq = f->frequency;
 		if (btv->has_matchbox)
 			tea5757_set_freq(btv, btv->radio_freq);
@@ -3216,8 +3229,6 @@ static int radio_open(struct file *file)
 
 	btv->radio_user++;
 
-	bttv_call_all(btv, tuner, s_radio);
-	audio_input(btv,TVAUDIO_INPUT_RADIO);
 	v4l2_fh_add(&fh->fh);
 
 	return 0;
@@ -3238,6 +3249,8 @@ static int radio_release(struct file *file)
 
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
+	if (btv->radio_user == 0)
+		btv->has_radio_tuner = 0;
 	return 0;
 }
 
@@ -3250,6 +3263,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 		return -EINVAL;
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
+	radio_enable(btv);
 
 	bttv_call_all(btv, tuner, g_tuner, t);
 
@@ -3268,6 +3282,7 @@ static int radio_s_tuner(struct file *file, void *priv,
 	if (0 != t->index)
 		return -EINVAL;
 
+	radio_enable(btv);
 	bttv_call_all(btv, tuner, s_tuner, t);
 	return 0;
 }
@@ -3282,6 +3297,7 @@ static ssize_t radio_read(struct file *file, char __user *data,
 	cmd.buffer = data;
 	cmd.instance = file;
 	cmd.result = -ENODEV;
+	radio_enable(btv);
 
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
 
@@ -3300,6 +3316,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
 		res = POLLPRI;
 	else if (req_events & POLLPRI)
 		poll_wait(file, &fh->fh.wait, wait);
+	radio_enable(btv);
 	cmd.instance = file;
 	cmd.event_list = wait;
 	cmd.result = res;
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 86d67bb..eb13be7 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -437,6 +437,7 @@ struct bttv {
 
 	/* radio data/state */
 	int has_radio;
+	int has_radio_tuner;
 	int radio_user;
 	int radio_uses_msp_demodulator;
 	unsigned long radio_freq;
-- 
1.7.10.4


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

* Re: [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input.
  2013-02-10 12:49   ` [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input Hans Verkuil
@ 2013-02-10 20:22     ` Frank Schäfer
  2013-02-11 14:22       ` Hans Verkuil
  0 siblings, 1 reply; 23+ messages in thread
From: Frank Schäfer @ 2013-02-10 20:22 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Linux Media Mailing List


Hmm... G/S_AUDIO is also used to query/set the capabilities and the mode
of an input, which IMHO makes sense even if the input is the only one
the device has ?
Don't you think that it's also somehow inconsistent, because for the
video inputs (G/S_INPUT) the spec says:
"This ioctl will fail only when there are no video inputs, returning
EINVAL." ?


Regards,
Frank



Am 10.02.2013 13:49, schrieb Hans Verkuil:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/pci/bt8xx/bttv-driver.c |   19 -------------------
>  1 file changed, 19 deletions(-)
>
> diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
> index 6e61dbd..a02c031 100644
> --- a/drivers/media/pci/bt8xx/bttv-driver.c
> +++ b/drivers/media/pci/bt8xx/bttv-driver.c
> @@ -3138,23 +3138,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
>  	return 0;
>  }
>  
> -static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
> -{
> -	if (unlikely(a->index))
> -		return -EINVAL;
> -
> -	strcpy(a->name, "audio");
> -	return 0;
> -}
> -
> -static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
> -{
> -	if (unlikely(a->index))
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
>  static ssize_t bttv_read(struct file *file, char __user *data,
>  			 size_t count, loff_t *ppos)
>  {
> @@ -3390,8 +3373,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
>  	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
>  	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
>  	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
> -	.vidioc_g_audio                 = bttv_g_audio,
> -	.vidioc_s_audio                 = bttv_s_audio,
>  	.vidioc_cropcap                 = bttv_cropcap,
>  	.vidioc_reqbufs                 = bttv_reqbufs,
>  	.vidioc_querybuf                = bttv_querybuf,


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

* Re: [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input.
  2013-02-10 20:22     ` Frank Schäfer
@ 2013-02-11 14:22       ` Hans Verkuil
  2013-02-11 16:53         ` Frank Schäfer
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2013-02-11 14:22 UTC (permalink / raw)
  To: Frank Schäfer; +Cc: Hans Verkuil, Linux Media Mailing List

On Sun February 10 2013 21:22:41 Frank Schäfer wrote:
> 
> Hmm... G/S_AUDIO is also used to query/set the capabilities and the mode
> of an input, which IMHO makes sense even if the input is the only one
> the device has ?

You are right, but there are problems with the implementation in this driver.
First of all, there is no ENUMAUDIO ioctl implemented, so applications were
never able to enumerate the audio inputs.

Now, it is possible to add this (and I have done this in this tree:
http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/bttv2).
However, the card definitions are unreliable with respect to the number of
audio inputs. So you may end up with a driver reporting incorrect information.

I tried it in the bttv2 branch and frankly it became rather messy.

Given the fact that there was never an ENUMAUDIO ioctl in the first place
I decided that it was better not to have these ioctls at all. Also, the
V4L2_CAP_AUDIO was never set, and they are incorrect anyway for boards that
do not have an audio input at all (common for surveillance boards).

There are other drivers as well that do not implement this, so applications
cannot rely on this ioctl being present.

I will update the commit message before I do the pull request, though. It
should be extended with the information above.

Regards,

	Hans

> Don't you think that it's also somehow inconsistent, because for the
> video inputs (G/S_INPUT) the spec says:
> "This ioctl will fail only when there are no video inputs, returning
> EINVAL." ?
> 
> 
> Regards,
> Frank
> 
> 
> 
> Am 10.02.2013 13:49, schrieb Hans Verkuil:
> > From: Hans Verkuil <hans.verkuil@cisco.com>
> >
> > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > ---
> >  drivers/media/pci/bt8xx/bttv-driver.c |   19 -------------------
> >  1 file changed, 19 deletions(-)
> >
> > diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
> > index 6e61dbd..a02c031 100644
> > --- a/drivers/media/pci/bt8xx/bttv-driver.c
> > +++ b/drivers/media/pci/bt8xx/bttv-driver.c
> > @@ -3138,23 +3138,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
> >  	return 0;
> >  }
> >  
> > -static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
> > -{
> > -	if (unlikely(a->index))
> > -		return -EINVAL;
> > -
> > -	strcpy(a->name, "audio");
> > -	return 0;
> > -}
> > -
> > -static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
> > -{
> > -	if (unlikely(a->index))
> > -		return -EINVAL;
> > -
> > -	return 0;
> > -}
> > -
> >  static ssize_t bttv_read(struct file *file, char __user *data,
> >  			 size_t count, loff_t *ppos)
> >  {
> > @@ -3390,8 +3373,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
> >  	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
> >  	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
> >  	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
> > -	.vidioc_g_audio                 = bttv_g_audio,
> > -	.vidioc_s_audio                 = bttv_s_audio,
> >  	.vidioc_cropcap                 = bttv_cropcap,
> >  	.vidioc_reqbufs                 = bttv_reqbufs,
> >  	.vidioc_querybuf                = bttv_querybuf,
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input.
  2013-02-11 14:22       ` Hans Verkuil
@ 2013-02-11 16:53         ` Frank Schäfer
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Schäfer @ 2013-02-11 16:53 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Linux Media Mailing List

Am 11.02.2013 15:22, schrieb Hans Verkuil:
> On Sun February 10 2013 21:22:41 Frank Schäfer wrote:
>> Hmm... G/S_AUDIO is also used to query/set the capabilities and the mode
>> of an input, which IMHO makes sense even if the input is the only one
>> the device has ?
> You are right, but there are problems with the implementation in this driver.
> First of all, there is no ENUMAUDIO ioctl implemented, so applications were
> never able to enumerate the audio inputs.

Argh, ok.

> Now, it is possible to add this (and I have done this in this tree:
> http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/bttv2).
> However, the card definitions are unreliable with respect to the number of
> audio inputs. So you may end up with a driver reporting incorrect information.
>
> I tried it in the bttv2 branch and frankly it became rather messy.
>
> Given the fact that there was never an ENUMAUDIO ioctl in the first place
> I decided that it was better not to have these ioctls at all. Also, the
> V4L2_CAP_AUDIO was never set, and they are incorrect anyway for boards that
> do not have an audio input at all (common for surveillance boards).

I checked your bttv2 branch and it's looking not that bad !
If I'm understanding correctly, your main concern is, that the board
information isn't reliable/correct ?
Hmm... it seems that (although commented out) nearly all boards have the
.audio_inputs field set, which leaves rooms for hope...

OTOH, even if the board info about the audio inputs is wrong, this
wouldn't have any consequences for the video input, right ?
The additional audio inputs just won't work. And that's something we can
fix step by step (if anybody cares ;) ).

So there is no risk of regressions and a good chance to get a missing
functionality work.
In that case I would vote for adding ENUM/G/S_AUDIO.

>
> There are other drivers as well that do not implement this, so applications
> cannot rely on this ioctl being present.

Sure, they _shouldn't_.

> I will update the commit message before I do the pull request, though. It
> should be extended with the information above.

That's probably the best solution for 3.9.

Regards,
Frank

>
> Regards,
>
> 	Hans
>
>> Don't you think that it's also somehow inconsistent, because for the
>> video inputs (G/S_INPUT) the spec says:
>> "This ioctl will fail only when there are no video inputs, returning
>> EINVAL." ?
>>
>>
>> Regards,
>> Frank
>>
>>
>>
>> Am 10.02.2013 13:49, schrieb Hans Verkuil:
>>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>>
>>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>>> ---
>>>  drivers/media/pci/bt8xx/bttv-driver.c |   19 -------------------
>>>  1 file changed, 19 deletions(-)
>>>
>>> diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
>>> index 6e61dbd..a02c031 100644
>>> --- a/drivers/media/pci/bt8xx/bttv-driver.c
>>> +++ b/drivers/media/pci/bt8xx/bttv-driver.c
>>> @@ -3138,23 +3138,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
>>>  	return 0;
>>>  }
>>>  
>>> -static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
>>> -{
>>> -	if (unlikely(a->index))
>>> -		return -EINVAL;
>>> -
>>> -	strcpy(a->name, "audio");
>>> -	return 0;
>>> -}
>>> -
>>> -static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
>>> -{
>>> -	if (unlikely(a->index))
>>> -		return -EINVAL;
>>> -
>>> -	return 0;
>>> -}
>>> -
>>>  static ssize_t bttv_read(struct file *file, char __user *data,
>>>  			 size_t count, loff_t *ppos)
>>>  {
>>> @@ -3390,8 +3373,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
>>>  	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
>>>  	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
>>>  	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
>>> -	.vidioc_g_audio                 = bttv_g_audio,
>>> -	.vidioc_s_audio                 = bttv_s_audio,
>>>  	.vidioc_cropcap                 = bttv_cropcap,
>>>  	.vidioc_reqbufs                 = bttv_reqbufs,
>>>  	.vidioc_querybuf                = bttv_querybuf,
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>


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

end of thread, other threads:[~2013-02-11 16:53 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-10 12:49 [REVIEWv2 PATCH 00/19] bttv v4l2-compliance fixes Hans Verkuil
2013-02-10 12:49 ` [REVIEWv2 PATCH 01/19] bttv: fix querycap and radio v4l2-compliance issues Hans Verkuil
2013-02-10 12:49   ` [REVIEWv2 PATCH 02/19] bttv: add VIDIOC_DBG_G_CHIP_IDENT Hans Verkuil
2013-02-10 12:49   ` [REVIEWv2 PATCH 03/19] bttv: fix ENUM_INPUT and S_INPUT Hans Verkuil
2013-02-10 12:49   ` [REVIEWv2 PATCH 04/19] bttv: remove g/s_audio since there is only one audio input Hans Verkuil
2013-02-10 20:22     ` Frank Schäfer
2013-02-11 14:22       ` Hans Verkuil
2013-02-11 16:53         ` Frank Schäfer
2013-02-10 12:50   ` [REVIEWv2 PATCH 05/19] bttv: disable g/s_tuner and g/s_freq when no tuner present, fix return codes Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 06/19] bttv: set initial tv/radio frequencies Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 07/19] bttv: G_PARM: set readbuffers Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 08/19] bttv: fill in colorspace Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 09/19] bttv: fill in fb->flags for VIDIOC_G_FBUF Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 10/19] bttv: fix field handling inside TRY_FMT Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 11/19] tda7432: convert to the control framework Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 12/19] bttv: " Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 13/19] bttv: add support for control events Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 14/19] bttv: fix priority handling Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 15/19] bttv: use centralized std and implement g_std Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 16/19] bttv: there may be multiple tvaudio/tda7432 devices Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 17/19] bttv: fix g_tuner capabilities override Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 18/19] bttv: fix try_fmt_vid_overlay and setup initial overlay size Hans Verkuil
2013-02-10 12:50   ` [REVIEWv2 PATCH 19/19] bttv: do not switch to the radio tuner unless it is accessed Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.