V4L/DVB (11300): cx88: convert to v4l2_subdev.

Convert cx88 to use v4l2_subdev since the old i2c autoprobing mechanism
will be removed.

Added code to explicitly load tvaudio where needed. Also fix the rtc-isl1208
support: since that driver no longer supports autoprobing it has to be
loaded using the new i2c API.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2009-03-29 08:26:01 -03:00 committed by Mauro Carvalho Chehab
parent b6198ade55
commit b8341e1d2a
7 changed files with 80 additions and 68 deletions

View file

@ -915,7 +915,7 @@ static int vidioc_log_status (struct file *file, void *priv)
snprintf(name, sizeof(name), "%s/2", core->name);
printk("%s/2: ============ START LOG STATUS ============\n",
core->name);
cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
call_all(core, core, log_status);
cx2341x_log_status(&dev->params, name);
printk("%s/2: ============= END LOG STATUS =============\n",
core->name);
@ -970,7 +970,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = core->freq;
cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
call_all(core, tuner, g_frequency, f);
return 0;
}

View file

@ -732,6 +732,8 @@ static const struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
/* Some variants use a tda9874 and so need the tvaudio module. */
.audio_chip = V4L2_IDENT_TVAUDIO,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@ -2985,7 +2987,7 @@ static void cx88_card_setup(struct cx88_core *core)
tea5767_cfg.tuner = TUNER_TEA5767;
tea5767_cfg.priv = &ctl;
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
call_all(core, tuner, s_config, &tea5767_cfg);
break;
}
case CX88_BOARD_TEVII_S420:
@ -3010,7 +3012,7 @@ static void cx88_card_setup(struct cx88_core *core)
tun_setup.type = core->board.radio_type;
tun_setup.addr = core->board.radio_addr;
tun_setup.tuner_callback = cx88_tuner_callback;
cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
call_all(core, tuner, s_type_addr, &tun_setup);
mode_mask &= ~T_RADIO;
}
@ -3020,7 +3022,7 @@ static void cx88_card_setup(struct cx88_core *core)
tun_setup.addr = core->board.tuner_addr;
tun_setup.tuner_callback = cx88_tuner_callback;
cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
call_all(core, tuner, s_type_addr, &tun_setup);
}
if (core->board.tda9887_conf) {
@ -3029,7 +3031,7 @@ static void cx88_card_setup(struct cx88_core *core)
tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &core->board.tda9887_conf;
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg);
call_all(core, tuner, s_config, &tda9887_cfg);
}
if (core->board.tuner_type == TUNER_XC2028) {
@ -3045,9 +3047,9 @@ static void cx88_card_setup(struct cx88_core *core)
xc2028_cfg.priv = &ctl;
info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
ctl.fname);
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
call_all(core, tuner, s_config, &xc2028_cfg);
}
cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
call_all(core, core, s_standby, 0);
}
/* ------------------------------------------------------------------ */
@ -3202,8 +3204,30 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
cx88_i2c_init(core, pci);
/* load tuner module, if needed */
if (TUNER_ABSENT != core->board.tuner_type)
request_module("tuner");
if (TUNER_ABSENT != core->board.tuner_type) {
int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
/* I don't trust the radio_type as is stored in the card
definitions, so we just probe for it.
The radio_type is sometimes missing, or set to UNSET but
later code configures a tea5767.
*/
v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_RADIO));
if (has_demod)
v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner",
"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
if (core->board.tuner_addr == ADDR_UNSET) {
enum v4l2_i2c_tuner_type type =
has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner",
"tuner", v4l2_i2c_tuner_addrs(type));
} else {
v4l2_i2c_new_subdev(&core->i2c_adap,
"tuner", "tuner", core->board.tuner_addr);
}
}
cx88_card_setup(core);
cx88_ir_init(core, pci);

View file

@ -991,7 +991,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
set_tvaudio(core);
// tell i2c chips
cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
call_all(core, tuner, s_std, norm);
// done
return 0;
@ -1059,8 +1059,11 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
mutex_lock(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
if (0 == core->i2c_rc) {
if (core->i2c_rtc)
i2c_unregister_device(core->i2c_rtc);
i2c_del_adapter(&core->i2c_adap);
}
list_del(&core->devlist);
iounmap(core->lmmio);
cx88_devcount--;

View file

@ -1168,7 +1168,7 @@ static int dvb_register(struct cx8802_dev *dev)
fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
/* Put the analog decoder in standby to keep it quiet */
cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
call_all(core, core, s_standby, 0);
/* register everything */
return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,

View file

@ -97,39 +97,6 @@ static int cx8800_bit_getsda(void *data)
/* ----------------------------------------------------------------------- */
static int attach_inform(struct i2c_client *client)
{
struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
struct cx88_core *core = to_core(v4l2_dev);
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
client->driver->driver.name, client->addr, client->name);
return 0;
}
static int detach_inform(struct i2c_client *client)
{
struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
struct cx88_core *core = to_core(v4l2_dev);
dprintk(1, "i2c detach [client=%s]\n", client->name);
return 0;
}
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
if (0 != core->i2c_rc)
return;
if (core->gate_ctrl)
core->gate_ctrl(core, 1);
i2c_clients_command(&core->i2c_adap, cmd, arg);
if (core->gate_ctrl)
core->gate_ctrl(core, 0);
}
static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
.setsda = cx8800_bit_setsda,
.setscl = cx8800_bit_setscl,
@ -175,17 +142,11 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
sizeof(core->i2c_algo));
if (core->board.tuner_type != TUNER_ABSENT)
core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
if (core->board.mpeg & CX88_MPEG_DVB)
core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
core->i2c_adap.dev.parent = &pci->dev;
strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
core->i2c_adap.owner = THIS_MODULE;
core->i2c_adap.id = I2C_HW_B_CX2388x;
core->i2c_adap.client_register = attach_inform;
core->i2c_adap.client_unregister = detach_inform;
core->i2c_algo.udelay = i2c_udelay;
core->i2c_algo.data = core;
i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
@ -224,8 +185,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
/* ----------------------------------------------------------------------- */
EXPORT_SYMBOL(cx88_call_i2c_clients);
/*
* Local variables:
* c-basic-offset: 8

View file

@ -431,8 +431,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
struct v4l2_routing route;
route.input = INPUT(input).audioroute;
cx88_call_i2c_clients(core,
VIDIOC_INT_S_AUDIO_ROUTING, &route);
call_all(core, audio, s_routing, &route);
}
/* cx2388's C-ADC is connected to the tuner only.
When used with S-Video, that ADC is busy dealing with
@ -827,8 +826,7 @@ static int video_open(struct file *file)
struct v4l2_routing route;
route.input = core->board.radio.audioroute;
cx88_call_i2c_clients(core,
VIDIOC_INT_S_AUDIO_ROUTING, &route);
call_all(core, audio, s_routing, &route);
}
/* "I2S ADC mode" */
core->tvaudio = WW_I2SADC;
@ -839,7 +837,7 @@ static int video_open(struct file *file)
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
}
cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
call_all(core, tuner, s_radio);
}
unlock_kernel();
@ -933,7 +931,7 @@ static int video_release(struct file *file)
kfree(fh);
if(atomic_dec_and_test(&dev->core->users))
cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
call_all(dev->core, core, s_standby, 0);
return 0;
}
@ -1395,7 +1393,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
f->frequency = core->freq;
cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
call_all(core, tuner, g_frequency, f);
return 0;
}
@ -1411,7 +1409,7 @@ int cx88_set_freq (struct cx88_core *core,
mutex_lock(&core->lock);
core->freq = f->frequency;
cx88_newstation(core);
cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
call_all(core, tuner, s_frequency, f);
/* When changing channels it is required to reset TVAUDIO */
msleep (10);
@ -1493,7 +1491,7 @@ static int radio_g_tuner (struct file *file, void *priv,
strcpy(t->name, "Radio");
t->type = V4L2_TUNER_RADIO;
cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
call_all(core, tuner, g_tuner, t);
return 0;
}
@ -1527,7 +1525,7 @@ static int radio_s_tuner (struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
call_all(core, tuner, s_tuner, t);
return 0;
}
@ -1884,12 +1882,30 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
/* load and configure helper modules */
if (core->board.audio_chip == V4L2_IDENT_WM8775)
request_module("wm8775");
v4l2_i2c_new_subdev(&core->i2c_adap,
"wm8775", "wm8775", 0x36 >> 1);
if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
/* This probes for a tda9874 as is used on some
Pixelview Ultra boards. */
static const unsigned short i2c_addr[] = {
0xb0 >> 1, I2C_CLIENT_END
};
v4l2_i2c_new_probed_subdev(&core->i2c_adap,
"tvaudio", "tvaudio", i2c_addr);
}
switch (core->boardnr) {
case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
static struct i2c_board_info rtc_info = {
I2C_BOARD_INFO("isl1208", 0x6f)
};
request_module("rtc-isl1208");
core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
}
/* break intentionally omitted */
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
request_module("ir-kbd-i2c");

View file

@ -328,6 +328,7 @@ struct cx88_core {
/* config info -- analog */
struct v4l2_device v4l2_dev;
struct i2c_client *i2c_rtc;
unsigned int boardnr;
struct cx88_board board;
@ -371,6 +372,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
}
#define call_all(core, o, f, args...) \
do { \
if (!core->i2c_rc) { \
if (core->gate_ctrl) \
core->gate_ctrl(core, 1); \
v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
if (core->gate_ctrl) \
core->gate_ctrl(core, 0); \
} \
} while (0)
struct cx8800_dev;
struct cx8802_dev;
@ -616,8 +628,6 @@ extern struct videobuf_queue_ops cx8800_vbi_qops;
/* cx88-i2c.c */
extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
extern void cx88_call_i2c_clients(struct cx88_core *core,
unsigned int cmd, void *arg);
/* ----------------------------------------------------------- */