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:
Родитель
9fc4d219b9
Коммит
f2cf250af1
|
@ -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 */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче