V4L/DVB (11331): em28xx: convert to v4l2_subdev

Converted em28xx driver to v4l2_subdev.
Thanks to Hans Verkuil <hverkuil@xs4all.nl> for helping this conversion.

Signed-off-by: Douglas Schilling Landgraf <dougsland@redhat.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 0f48c0f..fe96da0 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -31,6 +31,8 @@
 #include <media/msp3400.h>
 #include <media/saa7115.h>
 #include <media/tvp5150.h>
+#include <media/tvaudio.h>
+#include <media/i2c-addr.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
@@ -1240,6 +1242,7 @@
 	[EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
 		.name         = "Compro VideoMate ForYou/Stereo",
 		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+		.tvaudio_addr = 0xb0,
 		.tda9887_conf = TDA9887_PRESENT,
 		.decoder      = EM28XX_TVP5150,
 		.adecoder     = EM28XX_TVAUDIO,
@@ -1444,6 +1447,24 @@
 	{0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
 };
 
+/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
+static unsigned short saa711x_addrs[] = {
+	0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
+	0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
+	I2C_CLIENT_END };
+
+static unsigned short tvp5150_addrs[] = {
+	0xb8 >> 1,
+	0xba >> 1,
+	I2C_CLIENT_END
+};
+
+static unsigned short msp3400_addrs[] = {
+	0x80 >> 1,
+	0x88 >> 1,
+	I2C_CLIENT_END
+};
+
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
 {
 	int rc = 0;
@@ -1672,31 +1693,55 @@
 	}
 }
 
-static void em28xx_config_tuner(struct em28xx *dev)
+static void em28xx_tuner_setup(struct em28xx *dev)
 {
-	struct v4l2_priv_tun_config  xc2028_cfg;
 	struct tuner_setup           tun_setup;
 	struct v4l2_frequency        f;
 
 	if (dev->tuner_type == TUNER_ABSENT)
 		return;
 
+	memset(&tun_setup, 0, sizeof(tun_setup));
+
 	tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-	tun_setup.type = dev->tuner_type;
-	tun_setup.addr = dev->tuner_addr;
 	tun_setup.tuner_callback = em28xx_tuner_callback;
 
-	em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+	if (dev->board.radio.type) {
+		tun_setup.type = dev->board.radio.type;
+		tun_setup.addr = dev->board.radio_addr;
+
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+	}
+
+	if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
+		tun_setup.type   = dev->tuner_type;
+		tun_setup.addr   = dev->tuner_addr;
+
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+	}
+
+	if (dev->tda9887_conf) {
+		struct v4l2_priv_tun_config tda9887_cfg;
+
+		tda9887_cfg.tuner = TUNER_TDA9887;
+		tda9887_cfg.priv = &dev->tda9887_conf;
+
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
+	}
 
 	if (dev->tuner_type == TUNER_XC2028) {
+		struct v4l2_priv_tun_config  xc2028_cfg;
 		struct xc2028_ctrl           ctl;
 
+		memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+		memset(&ctl, 0, sizeof(ctl));
+
 		em28xx_setup_xc3028(dev, &ctl);
 
 		xc2028_cfg.tuner = TUNER_XC2028;
 		xc2028_cfg.priv  = &ctl;
 
-		em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
 	}
 
 	/* configure tuner */
@@ -1704,7 +1749,7 @@
 	f.type = V4L2_TUNER_ANALOG_TV;
 	f.frequency = 9076;     /* just a magic number */
 	dev->ctl_freq = f.frequency;
-	em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
 }
 
 static int em28xx_hint_board(struct em28xx *dev)
@@ -1911,22 +1956,50 @@
 	if (tuner >= 0)
 		dev->tuner_type = tuner;
 
-#ifdef CONFIG_MODULES
 	/* request some modules */
 	if (dev->board.has_msp34xx)
-		request_module("msp3400");
+		v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "msp3400",
+			"msp3400", msp3400_addrs);
+
 	if (dev->board.decoder == EM28XX_SAA711X)
-		request_module("saa7115");
+		v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa7115",
+			"saa7115_auto", saa711x_addrs);
+
 	if (dev->board.decoder == EM28XX_TVP5150)
-		request_module("tvp5150");
-	if (dev->board.tuner_type != TUNER_ABSENT)
-		request_module("tuner");
+		v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tvp5150",
+			"tvp5150", tvp5150_addrs);
+
 	if (dev->board.adecoder == EM28XX_TVAUDIO)
-		request_module("tvaudio");
-#endif
+		v4l2_i2c_new_subdev(&dev->i2c_adap, "tvaudio",
+			"tvaudio", dev->board.tvaudio_addr);
 
-	em28xx_config_tuner(dev);
+	if (dev->board.tuner_type != TUNER_ABSENT) {
+		int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
 
+		if (dev->board.radio.type)
+			v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner",
+				dev->board.radio_addr);
+
+		if (has_demod)
+			v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		if (dev->tuner_addr == 0) {
+			enum v4l2_i2c_tuner_type type =
+				has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+			struct v4l2_subdev *sd;
+
+			sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(type));
+
+			if (sd)
+				dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
+		} else {
+			v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner",
+				"tuner", dev->tuner_addr);
+		}
+	}
+
+	em28xx_tuner_setup(dev);
 	em28xx_ir_init(dev);
 }
 
@@ -1975,6 +2048,9 @@
 	em28xx_remove_from_devlist(dev);
 
 	em28xx_i2c_unregister(dev);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
@@ -2019,9 +2095,16 @@
 		}
 	}
 
+	retval = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+	if (retval < 0) {
+		em28xx_errdev("Call to v4l2_device_register() failed!\n");
+		return retval;
+	}
+
 	/* register i2c bus */
 	errCode = em28xx_i2c_register(dev);
 	if (errCode < 0) {
+		v4l2_device_unregister(&dev->v4l2_dev);
 		em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
 			__func__, errCode);
 		return errCode;
@@ -2033,6 +2116,7 @@
 	/* Configure audio */
 	errCode = em28xx_audio_setup(dev);
 	if (errCode < 0) {
+		v4l2_device_unregister(&dev->v4l2_dev);
 		em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
 			__func__, errCode);
 	}
@@ -2077,7 +2161,7 @@
 	em28xx_init_extension(dev);
 
 	/* Save some power by putting tuner to sleep */
-	em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0);
 
 	return 0;
 
@@ -2096,7 +2180,7 @@
 	struct usb_device *udev;
 	struct usb_interface *uif;
 	struct em28xx *dev = NULL;
-	int retval = -ENODEV;
+	int retval;
 	int i, nr, ifnum, isoc_pipe;
 	char *speed;
 	char descr[255] = "";
@@ -2118,7 +2202,8 @@
 			interface->altsetting[0].desc.bInterfaceClass);
 
 		em28xx_devused &= ~(1<<nr);
-		return -ENODEV;
+		retval = -ENODEV;
+		goto err;
 	}
 
 	endpoint = &interface->cur_altsetting->endpoint[0].desc;
@@ -2151,7 +2236,8 @@
 				"interface not used by the driver\n");
 
 			em28xx_devused &= ~(1<<nr);
-			return -ENODEV;
+			retval = -ENODEV;
+			goto err;
 		}
 	}
 
@@ -2194,7 +2280,8 @@
 		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
 				EM28XX_MAXBOARDS);
 		em28xx_devused &= ~(1<<nr);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err;
 	}
 
 	/* allocate memory for our device state and initialize it */
@@ -2202,7 +2289,8 @@
 	if (dev == NULL) {
 		em28xx_err(DRIVER_NAME ": out of memory!\n");
 		em28xx_devused &= ~(1<<nr);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err;
 	}
 
 	snprintf(dev->name, 29, "em28xx #%d", nr);
@@ -2229,7 +2317,8 @@
 		em28xx_errdev("out of memory!\n");
 		em28xx_devused &= ~(1<<nr);
 		kfree(dev);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err;
 	}
 
 	for (i = 0; i < dev->num_alt ; i++) {
@@ -2248,8 +2337,7 @@
 	if (retval) {
 		em28xx_devused &= ~(1<<dev->devno);
 		kfree(dev);
-
-		return retval;
+		goto err;
 	}
 
 	/* save our data pointer in this interface device */
@@ -2263,6 +2351,9 @@
 	mutex_unlock(&dev->lock);
 
 	return 0;
+
+err:
+	return retval;
 }
 
 /*
@@ -2288,6 +2379,8 @@
 
 	wake_up_interruptible_all(&dev->open);
 
+	v4l2_device_disconnect(&dev->v4l2_dev);
+
 	if (dev->users) {
 		em28xx_warn
 		    ("device /dev/video%d is open! Deregistration and memory "
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 8f1999c..8f8f20e 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -1021,11 +1021,12 @@
 	struct v4l2_routing route;
 	int zero = 0;
 
-	route.input = INPUT(dev->ctl_input)->vmux;
+	route.input  = INPUT(dev->ctl_input)->vmux;
 	route.output = 0;
-	em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero);
-	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
-	em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core,  reset, zero);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
 }
 
 /*
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 02c12fe..f0bf1d9 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -459,70 +459,15 @@
 static int attach_inform(struct i2c_client *client)
 {
 	struct em28xx *dev = client->adapter->algo_data;
+	struct IR_i2c *ir = i2c_get_clientdata(client);
 
 	switch (client->addr << 1) {
-	case 0x86:
-	case 0x84:
-	case 0x96:
-	case 0x94:
-	{
-		struct v4l2_priv_tun_config tda9887_cfg;
-
-		struct tuner_setup tun_setup;
-
-		tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-		tun_setup.type = TUNER_TDA9887;
-		tun_setup.addr = client->addr;
-
-		em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
-			&tun_setup);
-
-		tda9887_cfg.tuner = TUNER_TDA9887;
-		tda9887_cfg.priv = &dev->tda9887_conf;
-		em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
-					&tda9887_cfg);
-		break;
-	}
-	case 0x42:
-		dprintk1(1, "attach_inform: saa7114 detected.\n");
-		break;
-	case 0x4a:
-		dprintk1(1, "attach_inform: saa7113 detected.\n");
-		break;
-	case 0xa0:
-		dprintk1(1, "attach_inform: eeprom detected.\n");
-		break;
 	case 0x60:
 	case 0x8e:
-	{
-		struct IR_i2c *ir = i2c_get_clientdata(client);
-		dprintk1(1, "attach_inform: IR detected (%s).\n",
-			ir->phys);
+		dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys);
 		em28xx_set_ir(dev, ir);
 		break;
 	}
-	case 0x80:
-	case 0x88:
-		dprintk1(1, "attach_inform: msp34xx detected.\n");
-		break;
-	case 0xb8:
-	case 0xba:
-		dprintk1(1, "attach_inform: tvp5150 detected.\n");
-		break;
-
-	case 0xb0:
-		dprintk1(1, "attach_inform: tda9874 detected\n");
-		break;
-
-	default:
-		if (!dev->tuner_addr)
-			dev->tuner_addr = client->addr;
-
-		dprintk1(1, "attach inform: detected I2C address %x\n",
-				client->addr << 1);
-		dprintk1(1, "driver id %d\n", client->driver->id);
-
-	}
 
 	return 0;
 }
@@ -534,7 +479,6 @@
 
 static struct i2c_adapter em28xx_adap_template = {
 	.owner = THIS_MODULE,
-	.class = I2C_CLASS_TV_ANALOG,
 	.name = "em28xx",
 	.id = I2C_HW_B_EM28XX,
 	.algo = &em28xx_algo,
@@ -595,16 +539,6 @@
 }
 
 /*
- * em28xx_i2c_call_clients()
- * send commands to all attached i2c devices
- */
-void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg)
-{
-	BUG_ON(NULL == dev->i2c_adap.algo_data);
-	i2c_clients_command(&dev->i2c_adap, cmd, arg);
-}
-
-/*
  * em28xx_i2c_register()
  * register i2c bus
  */
@@ -618,6 +552,7 @@
 	dev->i2c_adap.dev.parent = &dev->udev->dev;
 	strcpy(dev->i2c_adap.name, dev->name);
 	dev->i2c_adap.algo_data = dev;
+	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 
 	retval = i2c_add_adapter(&dev->i2c_adap);
 	if (retval < 0) {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 575472f..6c09a37 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -49,7 +49,7 @@
 		      "Sascha Sommer <saschasommer@freenet.de>"
 
 #define DRIVER_DESC         "Empia em28xx based USB video device driver"
-#define EM28XX_VERSION_CODE  KERNEL_VERSION(0, 1, 1)
+#define EM28XX_VERSION_CODE  KERNEL_VERSION(0, 1, 2)
 
 #define em28xx_videodbg(fmt, arg...) do {\
 	if (video_debug) \
@@ -400,7 +400,7 @@
 	f.frequency = dev->ctl_freq;
 	f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 
-	em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
 
 	return 0;
 }
@@ -526,25 +526,25 @@
 	if (!dev->ctl_aoutput)
 		dev->ctl_aoutput = EM28XX_AOUT_MASTER;
 
-	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route);
 
 	if (dev->board.has_msp34xx) {
 		if (dev->i2s_speed) {
-			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
-				&dev->i2s_speed);
+			v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
+				s_i2s_clock_freq, dev->i2s_speed);
 		}
-		route.input = dev->ctl_ainput;
+		route.input  = dev->ctl_ainput;
 		route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+
 		/* Note: this is msp3400 specific */
-		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
-			&route);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route);
 	}
 
 	if (dev->board.adecoder != EM28XX_NOADECODER) {
-		route.input = dev->ctl_ainput;
+		route.input  = dev->ctl_ainput;
 		route.output = dev->ctl_aoutput;
-		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
-			&route);
+
+		v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route);
 	}
 
 	em28xx_audio_analog_set(dev);
@@ -829,7 +829,7 @@
 	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
 	em28xx_resolution_set(dev);
-	em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, dev->norm);
 
 	mutex_unlock(&dev->lock);
 	return 0;
@@ -995,8 +995,9 @@
 			}
 		}
 	}
+
 	mutex_lock(&dev->lock);
-	em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
 	mutex_unlock(&dev->lock);
 
 	if (qc->type)
@@ -1020,11 +1021,11 @@
 	mutex_lock(&dev->lock);
 
 	if (dev->board.has_msp34xx)
-		em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
 	else {
 		rc = em28xx_get_ctrl(dev, ctrl);
 		if (rc < 0) {
-			em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
+			v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
 			rc = 0;
 		}
 	}
@@ -1048,7 +1049,7 @@
 	mutex_lock(&dev->lock);
 
 	if (dev->board.has_msp34xx)
-		em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
 	else {
 		rc = 1;
 		for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
@@ -1067,7 +1068,7 @@
 
 	/* Control not found - try to send it to the attached devices */
 	if (rc == 1) {
-		em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
 		rc = 0;
 	}
 
@@ -1092,10 +1093,9 @@
 	strcpy(t->name, "Tuner");
 
 	mutex_lock(&dev->lock);
-
-	em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
-
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
 	mutex_unlock(&dev->lock);
+
 	return 0;
 }
 
@@ -1114,10 +1114,9 @@
 		return -EINVAL;
 
 	mutex_lock(&dev->lock);
-
-	em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
-
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
 	mutex_unlock(&dev->lock);
+
 	return 0;
 }
 
@@ -1157,7 +1156,7 @@
 	mutex_lock(&dev->lock);
 
 	dev->ctl_freq = f->frequency;
-	em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
 
 	mutex_unlock(&dev->lock);
 
@@ -1186,7 +1185,7 @@
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
 
-	em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
 
 	return 0;
 }
@@ -1211,7 +1210,7 @@
 		reg->size = 1;
 		return 0;
 	case V4L2_CHIP_MATCH_I2C_DRIVER:
-		em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
 		return 0;
 	case V4L2_CHIP_MATCH_I2C_ADDR:
 		/* Not supported yet */
@@ -1263,7 +1262,7 @@
 
 		return rc;
 	case V4L2_CHIP_MATCH_I2C_DRIVER:
-		em28xx_i2c_call_clients(dev, VIDIOC_DBG_S_REGISTER, reg);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
 		return 0;
 	case V4L2_CHIP_MATCH_I2C_ADDR:
 		/* Not supported yet */
@@ -1406,13 +1405,13 @@
 	mutex_lock(&dev->lock);
 
 	f->fmt.sliced.service_set = 0;
-
-	em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f);
 
 	if (f->fmt.sliced.service_set == 0)
 		rc = -EINVAL;
 
 	mutex_unlock(&dev->lock);
+
 	return rc;
 }
 
@@ -1428,7 +1427,7 @@
 		return rc;
 
 	mutex_lock(&dev->lock);
-	em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f);
 	mutex_unlock(&dev->lock);
 
 	if (f->fmt.sliced.service_set == 0)
@@ -1532,7 +1531,7 @@
 	t->type = V4L2_TUNER_RADIO;
 
 	mutex_lock(&dev->lock);
-	em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
 	mutex_unlock(&dev->lock);
 
 	return 0;
@@ -1567,7 +1566,7 @@
 		return -EINVAL;
 
 	mutex_lock(&dev->lock);
-	em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
 	mutex_unlock(&dev->lock);
 
 	return 0;
@@ -1655,7 +1654,7 @@
 	}
 	if (fh->radio) {
 		em28xx_videodbg("video_open: setting radio device\n");
-		em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
 	}
 
 	dev->users++;
@@ -1738,7 +1737,7 @@
 		}
 
 		/* Save some power by putting tuner to sleep */
-		em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0);
 
 		/* do this before setting alternate! */
 		em28xx_uninit_isoc(dev);
@@ -1959,11 +1958,12 @@
 	vfd = video_device_alloc();
 	if (NULL == vfd)
 		return NULL;
-	*vfd = *template;
-	vfd->minor   = -1;
-	vfd->parent = &dev->udev->dev;
-	vfd->release = video_device_release;
-	vfd->debug = video_debug;
+
+	*vfd		= *template;
+	vfd->minor	= -1;
+	vfd->v4l2_dev	= &dev->v4l2_dev;
+	vfd->release	= video_device_release;
+	vfd->debug	= video_debug;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s",
 		 dev->name, type_name);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index a33a58d..4c4e580 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -27,6 +27,7 @@
 
 #include <linux/videodev2.h>
 #include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
 
 #include <linux/i2c.h>
 #include <linux/mutex.h>
@@ -385,6 +386,8 @@
 	unsigned int valid:1;
 
 	unsigned char xclk, i2c_speed;
+	unsigned char radio_addr;
+	unsigned short tvaudio_addr;
 
 	enum em28xx_decoder decoder;
 	enum em28xx_adecoder adecoder;
@@ -460,6 +463,7 @@
 	int devno;		/* marks the number of this device */
 	enum em28xx_chip_id chip_id;
 
+	struct v4l2_device v4l2_dev;
 	struct em28xx_board board;
 
 	unsigned int stream_on:1;	/* Locks streams */
@@ -577,11 +581,9 @@
 };
 
 /* Provided by em28xx-i2c.c */
-
-void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg);
 void em28xx_do_i2c_scan(struct em28xx *dev);
-int em28xx_i2c_register(struct em28xx *dev);
-int em28xx_i2c_unregister(struct em28xx *dev);
+int  em28xx_i2c_register(struct em28xx *dev);
+int  em28xx_i2c_unregister(struct em28xx *dev);
 
 /* Provided by em28xx-core.c */