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>
This commit is contained in:
Douglas Schilling Landgraf 2009-03-31 17:10:58 -03:00 committed by Mauro Carvalho Chehab
parent 9fc4d219b9
commit f2cf250af1
5 changed files with 171 additions and 140 deletions

View File

@ -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.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 @@ 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);
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 @@ 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 "

View File

@ -1021,11 +1021,12 @@ void em28xx_wake_i2c(struct em28xx *dev)
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);
}
/*

View File

@ -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) {

View File

@ -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.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 @@ 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,11 +1958,12 @@ 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->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);

View File

@ -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,11 +581,9 @@ 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);
int em28xx_i2c_register(struct em28xx *dev);
int em28xx_i2c_unregister(struct em28xx *dev);
/* Provided by em28xx-core.c */