Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2cf250a authored by Douglas Schilling Landgraf's avatar Douglas Schilling Landgraf Committed by Mauro Carvalho Chehab
Browse files

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: default avatarDouglas Schilling Landgraf <dougsland@redhat.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 9fc4d219
Loading
Loading
Loading
Loading
+119 −26
Original line number Diff line number Diff line
@@ -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 @@ struct em28xx_board em28xx_boards[] = {
	[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 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
	{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_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
	}
}

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.tuner_callback = em28xx_tuner_callback;

	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;
	tun_setup.tuner_callback = em28xx_tuner_callback;

	em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
		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 @@ static void em28xx_config_tuner(struct em28xx *dev)
	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 @@ void em28xx_card_setup(struct em28xx *dev)
	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);

	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;

	em28xx_config_tuner(dev);
			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 @@ void em28xx_release_resources(struct em28xx *dev)
	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 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
		}
	}

	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 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
	/* 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 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
	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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
	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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
			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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
				"interface not used by the driver\n");

			em28xx_devused &= ~(1<<nr);
			return -ENODEV;
			retval = -ENODEV;
			goto err;
		}
	}

@@ -2194,7 +2280,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
		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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
	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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
		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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
	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 @@ static int em28xx_usb_probe(struct usb_interface *interface,
	mutex_unlock(&dev->lock);

	return 0;

err:
	return retval;
}

/*
@@ -2288,6 +2379,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)

	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 "
+5 −4
Original line number Diff line number Diff line
@@ -1023,9 +1023,10 @@ void em28xx_wake_i2c(struct em28xx *dev)

	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);
}

/*
+3 −68
Original line number Diff line number Diff line
@@ -459,70 +459,15 @@ static u32 functionality(struct i2c_adapter *adap)
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_algorithm em28xx_algo = {

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,
@@ -594,16 +538,6 @@ void em28xx_do_i2c_scan(struct em28xx *dev)
					ARRAY_SIZE(i2c_devicelist), 32);
}

/*
 * 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 @@ int em28xx_i2c_register(struct em28xx *dev)
	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) {
+39 −39
Original line number Diff line number Diff line
@@ -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 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
	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 @@ static void video_mux(struct em28xx *dev, int index)
	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.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.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 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
	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 @@ static int vidioc_queryctrl(struct file *file, void *priv,
			}
		}
	}

	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 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
	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 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
	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 @@ static int vidioc_s_ctrl(struct file *file, void *priv,

	/* 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 @@ static int vidioc_g_tuner(struct file *file, void *priv,
	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 @@ static int vidioc_s_tuner(struct file *file, void *priv,
		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 @@ static int vidioc_s_frequency(struct file *file, void *priv,
	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 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
	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 @@ static int vidioc_g_register(struct file *file, void *priv,
		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 @@ static int vidioc_s_register(struct file *file, void *priv,

		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 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
	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 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
		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 @@ static int radio_g_tuner(struct file *file, void *priv,
	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 @@ static int radio_s_tuner(struct file *file, void *priv,
		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 @@ static int em28xx_v4l2_open(struct file *filp)
	}
	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 @@ static int em28xx_v4l2_close(struct file *filp)
		}

		/* 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,9 +1958,10 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
	vfd = video_device_alloc();
	if (NULL == vfd)
		return NULL;

	*vfd		= *template;
	vfd->minor	= -1;
	vfd->parent = &dev->udev->dev;
	vfd->v4l2_dev	= &dev->v4l2_dev;
	vfd->release	= video_device_release;
	vfd->debug	= video_debug;

+6 −4
Original line number Diff line number Diff line
@@ -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 @@ struct em28xx_board {
	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 @@ struct em28xx {
	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,8 +581,6 @@ struct em28xx_ops {
};

/* 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);