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 коммит произвёл Mauro Carvalho Chehab
Родитель 9fc4d219b9
Коммит f2cf250af1
5 изменённых файлов: 171 добавлений и 140 удалений

Просмотреть файл

@ -31,6 +31,8 @@
#include <media/msp3400.h> #include <media/msp3400.h>
#include <media/saa7115.h> #include <media/saa7115.h>
#include <media/tvp5150.h> #include <media/tvp5150.h>
#include <media/tvaudio.h>
#include <media/i2c-addr.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
@ -1240,6 +1242,7 @@ struct em28xx_board em28xx_boards[] = {
[EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
.name = "Compro VideoMate ForYou/Stereo", .name = "Compro VideoMate ForYou/Stereo",
.tuner_type = TUNER_LG_PAL_NEW_TAPC, .tuner_type = TUNER_LG_PAL_NEW_TAPC,
.tvaudio_addr = 0xb0,
.tda9887_conf = TDA9887_PRESENT, .tda9887_conf = TDA9887_PRESENT,
.decoder = EM28XX_TVP5150, .decoder = EM28XX_TVP5150,
.adecoder = EM28XX_TVAUDIO, .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}, {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 em28xx_tuner_callback(void *ptr, int component, int command, int arg)
{ {
int rc = 0; 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 tuner_setup tun_setup;
struct v4l2_frequency f; struct v4l2_frequency f;
if (dev->tuner_type == TUNER_ABSENT) if (dev->tuner_type == TUNER_ABSENT)
return; return;
memset(&tun_setup, 0, sizeof(tun_setup));
tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; 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; 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) { if (dev->tuner_type == TUNER_XC2028) {
struct v4l2_priv_tun_config xc2028_cfg;
struct xc2028_ctrl ctl; struct xc2028_ctrl ctl;
memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
memset(&ctl, 0, sizeof(ctl));
em28xx_setup_xc3028(dev, &ctl); em28xx_setup_xc3028(dev, &ctl);
xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.tuner = TUNER_XC2028;
xc2028_cfg.priv = &ctl; 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 */ /* configure tuner */
@ -1704,7 +1749,7 @@ static void em28xx_config_tuner(struct em28xx *dev)
f.type = V4L2_TUNER_ANALOG_TV; f.type = V4L2_TUNER_ANALOG_TV;
f.frequency = 9076; /* just a magic number */ f.frequency = 9076; /* just a magic number */
dev->ctl_freq = f.frequency; 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) static int em28xx_hint_board(struct em28xx *dev)
@ -1911,22 +1956,50 @@ void em28xx_card_setup(struct em28xx *dev)
if (tuner >= 0) if (tuner >= 0)
dev->tuner_type = tuner; dev->tuner_type = tuner;
#ifdef CONFIG_MODULES
/* request some modules */ /* request some modules */
if (dev->board.has_msp34xx) 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) 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) if (dev->board.decoder == EM28XX_TVP5150)
request_module("tvp5150"); v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tvp5150",
if (dev->board.tuner_type != TUNER_ABSENT) "tvp5150", tvp5150_addrs);
request_module("tuner");
if (dev->board.adecoder == EM28XX_TVAUDIO) if (dev->board.adecoder == EM28XX_TVAUDIO)
request_module("tvaudio"); v4l2_i2c_new_subdev(&dev->i2c_adap, "tvaudio",
#endif "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); em28xx_ir_init(dev);
} }
@ -1975,6 +2048,9 @@ void em28xx_release_resources(struct em28xx *dev)
em28xx_remove_from_devlist(dev); em28xx_remove_from_devlist(dev);
em28xx_i2c_unregister(dev); em28xx_i2c_unregister(dev);
v4l2_device_unregister(&dev->v4l2_dev);
usb_put_dev(dev->udev); usb_put_dev(dev->udev);
/* Mark device as unused */ /* 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 */ /* register i2c bus */
errCode = em28xx_i2c_register(dev); errCode = em28xx_i2c_register(dev);
if (errCode < 0) { if (errCode < 0) {
v4l2_device_unregister(&dev->v4l2_dev);
em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
__func__, errCode); __func__, errCode);
return errCode; return errCode;
@ -2033,6 +2116,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
/* Configure audio */ /* Configure audio */
errCode = em28xx_audio_setup(dev); errCode = em28xx_audio_setup(dev);
if (errCode < 0) { if (errCode < 0) {
v4l2_device_unregister(&dev->v4l2_dev);
em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
__func__, errCode); __func__, errCode);
} }
@ -2077,7 +2161,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
em28xx_init_extension(dev); em28xx_init_extension(dev);
/* Save some power by putting tuner to sleep */ /* 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; return 0;
@ -2096,7 +2180,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *uif; struct usb_interface *uif;
struct em28xx *dev = NULL; struct em28xx *dev = NULL;
int retval = -ENODEV; int retval;
int i, nr, ifnum, isoc_pipe; int i, nr, ifnum, isoc_pipe;
char *speed; char *speed;
char descr[255] = ""; char descr[255] = "";
@ -2118,7 +2202,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
interface->altsetting[0].desc.bInterfaceClass); interface->altsetting[0].desc.bInterfaceClass);
em28xx_devused &= ~(1<<nr); em28xx_devused &= ~(1<<nr);
return -ENODEV; retval = -ENODEV;
goto err;
} }
endpoint = &interface->cur_altsetting->endpoint[0].desc; 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"); "interface not used by the driver\n");
em28xx_devused &= ~(1<<nr); 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", printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
EM28XX_MAXBOARDS); EM28XX_MAXBOARDS);
em28xx_devused &= ~(1<<nr); em28xx_devused &= ~(1<<nr);
return -ENOMEM; retval = -ENOMEM;
goto err;
} }
/* allocate memory for our device state and initialize it */ /* 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) { if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n"); em28xx_err(DRIVER_NAME ": out of memory!\n");
em28xx_devused &= ~(1<<nr); em28xx_devused &= ~(1<<nr);
return -ENOMEM; retval = -ENOMEM;
goto err;
} }
snprintf(dev->name, 29, "em28xx #%d", nr); 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_errdev("out of memory!\n");
em28xx_devused &= ~(1<<nr); em28xx_devused &= ~(1<<nr);
kfree(dev); kfree(dev);
return -ENOMEM; retval = -ENOMEM;
goto err;
} }
for (i = 0; i < dev->num_alt ; i++) { for (i = 0; i < dev->num_alt ; i++) {
@ -2248,8 +2337,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (retval) { if (retval) {
em28xx_devused &= ~(1<<dev->devno); em28xx_devused &= ~(1<<dev->devno);
kfree(dev); kfree(dev);
goto err;
return retval;
} }
/* save our data pointer in this interface device */ /* 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); mutex_unlock(&dev->lock);
return 0; return 0;
err:
return retval;
} }
/* /*
@ -2288,6 +2379,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
wake_up_interruptible_all(&dev->open); wake_up_interruptible_all(&dev->open);
v4l2_device_disconnect(&dev->v4l2_dev);
if (dev->users) { if (dev->users) {
em28xx_warn em28xx_warn
("device /dev/video%d is open! Deregistration and memory " ("device /dev/video%d is open! Deregistration and memory "

Просмотреть файл

@ -1021,11 +1021,12 @@ void em28xx_wake_i2c(struct em28xx *dev)
struct v4l2_routing route; struct v4l2_routing route;
int zero = 0; int zero = 0;
route.input = INPUT(dev->ctl_input)->vmux; route.input = INPUT(dev->ctl_input)->vmux;
route.output = 0; route.output = 0;
em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero);
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, zero);
em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route);
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
} }
/* /*

Просмотреть файл

@ -459,70 +459,15 @@ static u32 functionality(struct i2c_adapter *adap)
static int attach_inform(struct i2c_client *client) static int attach_inform(struct i2c_client *client)
{ {
struct em28xx *dev = client->adapter->algo_data; struct em28xx *dev = client->adapter->algo_data;
struct IR_i2c *ir = i2c_get_clientdata(client);
switch (client->addr << 1) { 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 0x60:
case 0x8e: case 0x8e:
{ dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys);
struct IR_i2c *ir = i2c_get_clientdata(client);
dprintk1(1, "attach_inform: IR detected (%s).\n",
ir->phys);
em28xx_set_ir(dev, ir); em28xx_set_ir(dev, ir);
break; 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; return 0;
} }
@ -534,7 +479,6 @@ static struct i2c_algorithm em28xx_algo = {
static struct i2c_adapter em28xx_adap_template = { static struct i2c_adapter em28xx_adap_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_TV_ANALOG,
.name = "em28xx", .name = "em28xx",
.id = I2C_HW_B_EM28XX, .id = I2C_HW_B_EM28XX,
.algo = &em28xx_algo, .algo = &em28xx_algo,
@ -594,16 +538,6 @@ void em28xx_do_i2c_scan(struct em28xx *dev)
ARRAY_SIZE(i2c_devicelist), 32); 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() * em28xx_i2c_register()
* register i2c bus * register i2c bus
@ -618,6 +552,7 @@ int em28xx_i2c_register(struct em28xx *dev)
dev->i2c_adap.dev.parent = &dev->udev->dev; dev->i2c_adap.dev.parent = &dev->udev->dev;
strcpy(dev->i2c_adap.name, dev->name); strcpy(dev->i2c_adap.name, dev->name);
dev->i2c_adap.algo_data = dev; dev->i2c_adap.algo_data = dev;
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
retval = i2c_add_adapter(&dev->i2c_adap); retval = i2c_add_adapter(&dev->i2c_adap);
if (retval < 0) { if (retval < 0) {

Просмотреть файл

@ -49,7 +49,7 @@
"Sascha Sommer <saschasommer@freenet.de>" "Sascha Sommer <saschasommer@freenet.de>"
#define DRIVER_DESC "Empia em28xx based USB video device driver" #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 {\ #define em28xx_videodbg(fmt, arg...) do {\
if (video_debug) \ 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.frequency = dev->ctl_freq;
f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 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; return 0;
} }
@ -526,25 +526,25 @@ static void video_mux(struct em28xx *dev, int index)
if (!dev->ctl_aoutput) if (!dev->ctl_aoutput)
dev->ctl_aoutput = EM28XX_AOUT_MASTER; 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->board.has_msp34xx) {
if (dev->i2s_speed) { if (dev->i2s_speed) {
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
&dev->i2s_speed); 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); route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */ /* Note: this is msp3400 specific */
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route);
&route);
} }
if (dev->board.adecoder != EM28XX_NOADECODER) { if (dev->board.adecoder != EM28XX_NOADECODER) {
route.input = dev->ctl_ainput; route.input = dev->ctl_ainput;
route.output = dev->ctl_aoutput; 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); 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); get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_resolution_set(dev); 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); mutex_unlock(&dev->lock);
return 0; return 0;
@ -995,8 +995,9 @@ static int vidioc_queryctrl(struct file *file, void *priv,
} }
} }
} }
mutex_lock(&dev->lock); 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); mutex_unlock(&dev->lock);
if (qc->type) if (qc->type)
@ -1020,11 +1021,11 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
if (dev->board.has_msp34xx) 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 { else {
rc = em28xx_get_ctrl(dev, ctrl); rc = em28xx_get_ctrl(dev, ctrl);
if (rc < 0) { 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; rc = 0;
} }
} }
@ -1048,7 +1049,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
if (dev->board.has_msp34xx) 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 { else {
rc = 1; rc = 1;
for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { 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 */ /* Control not found - try to send it to the attached devices */
if (rc == 1) { 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; rc = 0;
} }
@ -1092,10 +1093,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
strcpy(t->name, "Tuner"); strcpy(t->name, "Tuner");
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
return 0; return 0;
} }
@ -1114,10 +1114,9 @@ static int vidioc_s_tuner(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
return 0; return 0;
} }
@ -1157,7 +1156,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->ctl_freq = f->frequency; 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); 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->ident = V4L2_IDENT_NONE;
chip->revision = 0; 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; return 0;
} }
@ -1211,7 +1210,7 @@ static int vidioc_g_register(struct file *file, void *priv,
reg->size = 1; reg->size = 1;
return 0; return 0;
case V4L2_CHIP_MATCH_I2C_DRIVER: 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; return 0;
case V4L2_CHIP_MATCH_I2C_ADDR: case V4L2_CHIP_MATCH_I2C_ADDR:
/* Not supported yet */ /* Not supported yet */
@ -1263,7 +1262,7 @@ static int vidioc_s_register(struct file *file, void *priv,
return rc; return rc;
case V4L2_CHIP_MATCH_I2C_DRIVER: 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; return 0;
case V4L2_CHIP_MATCH_I2C_ADDR: case V4L2_CHIP_MATCH_I2C_ADDR:
/* Not supported yet */ /* Not supported yet */
@ -1406,13 +1405,13 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
f->fmt.sliced.service_set = 0; f->fmt.sliced.service_set = 0;
v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f);
em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
if (f->fmt.sliced.service_set == 0) if (f->fmt.sliced.service_set == 0)
rc = -EINVAL; rc = -EINVAL;
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
return rc; return rc;
} }
@ -1428,7 +1427,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
return rc; return rc;
mutex_lock(&dev->lock); 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); mutex_unlock(&dev->lock);
if (f->fmt.sliced.service_set == 0) 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; t->type = V4L2_TUNER_RADIO;
mutex_lock(&dev->lock); 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); mutex_unlock(&dev->lock);
return 0; return 0;
@ -1567,7 +1566,7 @@ static int radio_s_tuner(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock); 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); mutex_unlock(&dev->lock);
return 0; return 0;
@ -1655,7 +1654,7 @@ static int em28xx_v4l2_open(struct file *filp)
} }
if (fh->radio) { if (fh->radio) {
em28xx_videodbg("video_open: setting radio device\n"); 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++; dev->users++;
@ -1738,7 +1737,7 @@ static int em28xx_v4l2_close(struct file *filp)
} }
/* Save some power by putting tuner to sleep */ /* 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! */ /* do this before setting alternate! */
em28xx_uninit_isoc(dev); em28xx_uninit_isoc(dev);
@ -1959,11 +1958,12 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
vfd = video_device_alloc(); vfd = video_device_alloc();
if (NULL == vfd) if (NULL == vfd)
return NULL; return NULL;
*vfd = *template;
vfd->minor = -1; *vfd = *template;
vfd->parent = &dev->udev->dev; vfd->minor = -1;
vfd->release = video_device_release; vfd->v4l2_dev = &dev->v4l2_dev;
vfd->debug = video_debug; vfd->release = video_device_release;
vfd->debug = video_debug;
snprintf(vfd->name, sizeof(vfd->name), "%s %s", snprintf(vfd->name, sizeof(vfd->name), "%s %s",
dev->name, type_name); dev->name, type_name);

Просмотреть файл

@ -27,6 +27,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/videobuf-vmalloc.h> #include <media/videobuf-vmalloc.h>
#include <media/v4l2-device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h> #include <linux/mutex.h>
@ -385,6 +386,8 @@ struct em28xx_board {
unsigned int valid:1; unsigned int valid:1;
unsigned char xclk, i2c_speed; unsigned char xclk, i2c_speed;
unsigned char radio_addr;
unsigned short tvaudio_addr;
enum em28xx_decoder decoder; enum em28xx_decoder decoder;
enum em28xx_adecoder adecoder; enum em28xx_adecoder adecoder;
@ -460,6 +463,7 @@ struct em28xx {
int devno; /* marks the number of this device */ int devno; /* marks the number of this device */
enum em28xx_chip_id chip_id; enum em28xx_chip_id chip_id;
struct v4l2_device v4l2_dev;
struct em28xx_board board; struct em28xx_board board;
unsigned int stream_on:1; /* Locks streams */ unsigned int stream_on:1; /* Locks streams */
@ -577,11 +581,9 @@ struct em28xx_ops {
}; };
/* Provided by em28xx-i2c.c */ /* 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); void em28xx_do_i2c_scan(struct em28xx *dev);
int em28xx_i2c_register(struct em28xx *dev); int em28xx_i2c_register(struct em28xx *dev);
int em28xx_i2c_unregister(struct em28xx *dev); int em28xx_i2c_unregister(struct em28xx *dev);
/* Provided by em28xx-core.c */ /* Provided by em28xx-core.c */