V4L/DVB (11158): pvrusb2: New device attribute mechanism to specify sub-devices

Set up new mechanism for declaring and loading appropriate sub-devices
when driver initializes.  This is another part of the v4l2-subdev
adoption.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Mike Isely 2009-03-06 23:42:20 -03:00 committed by Mauro Carvalho Chehab
parent acd92d40cc
commit e9c64a78db
3 changed files with 144 additions and 4 deletions

View File

@ -33,6 +33,31 @@
*/
#define PVR2_CLIENT_ID_MSP3400 1
#define PVR2_CLIENT_ID_CX25840 2
#define PVR2_CLIENT_ID_SAA7115 3
#define PVR2_CLIENT_ID_TUNER 4
#define PVR2_CLIENT_ID_CS53132A 5
struct pvr2_device_client_desc {
/* One ovr PVR2_CLIENT_ID_xxxx */
unsigned char module_id;
/* Null-terminated array of I2C addresses to try in order
initialize the module. It's safe to make this null terminated
since we're never going to encounter an i2c device with an
address of zero. If this is a null pointer or zero-length,
then no I2C addresses have been specified, in which case we'll
try some compiled in defaults for now. */
unsigned char *i2c_address_list;
};
struct pvr2_device_client_table {
const struct pvr2_device_client_desc *lst;
unsigned char cnt;
};
struct pvr2_string_table {
const char **lst;
unsigned int cnt;
@ -66,6 +91,9 @@ struct pvr2_device_desc {
/* List of additional client modules we need to load */
struct pvr2_string_table client_modules;
/* List of defined client modules we need to load */
struct pvr2_device_client_table client_table;
/* List of FX2 firmware file names we should search; if empty then
FX2 firmware check / load is skipped and we assume the device
was initialized from internal ROM. */

View File

@ -105,6 +105,20 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
/* size of a firmware chunk */
#define FIRMWARE_CHUNK_SIZE 0x2000
static const char *module_names[] = {
[PVR2_CLIENT_ID_MSP3400] = "msp3400",
[PVR2_CLIENT_ID_CX25840] = "cx25840",
[PVR2_CLIENT_ID_SAA7115] = "saa7115",
[PVR2_CLIENT_ID_TUNER] = "tuner",
[PVR2_CLIENT_ID_CS53132A] = "cs53132a",
};
static const unsigned char *module_i2c_addresses[] = {
[PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63",
};
/* Define the list of additional controls we'll dynamically construct based
on query of the cx2341x module. */
struct pvr2_mpeg_ids {
@ -1934,6 +1948,105 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
}
static unsigned int pvr2_copy_i2c_addr_list(
unsigned short *dst, const unsigned char *src,
unsigned int dst_max)
{
unsigned int cnt;
if (!src) return 0;
while (src[cnt] && (cnt + 1) < dst_max) {
dst[cnt] = src[cnt];
cnt++;
}
dst[cnt] = I2C_CLIENT_END;
return cnt;
}
static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
const struct pvr2_device_client_desc *cd)
{
const char *fname;
unsigned char mid;
struct v4l2_subdev *sd;
unsigned int i2ccnt;
const unsigned char *p;
/* Arbitrary count - max # i2c addresses we will probe */
unsigned short i2caddr[25];
mid = cd->module_id;
fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
if (!fname) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Module ID %u for device %s is unknown"
" (this is probably a bad thing...)",
mid,
hdw->hdw_desc->description);
return;
}
i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
ARRAY_SIZE(i2caddr));
if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
module_i2c_addresses[mid] : NULL) != NULL)) {
/* Second chance: Try default i2c address list */
i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
ARRAY_SIZE(i2caddr));
}
if (!i2ccnt) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Module ID %u for device %s:"
" No i2c addresses"
" (this is probably a bad thing...)",
mid, hdw->hdw_desc->description);
return;
}
/* Note how the 2nd and 3rd arguments are the same for both
* v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why?
* Well the 2nd argument is the module name to load, while the 3rd
* argument is documented in the framework as being the "chipid" -
* and every other place where I can find examples of this, the
* "chipid" appears to just be the module name again. So here we
* just do the same thing. */
if (i2ccnt == 1) {
sd = v4l2_i2c_new_subdev(&hdw->i2c_adap,
fname, fname,
i2caddr[0]);
} else {
sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap,
fname, fname,
i2caddr);
}
// ?????
/* Based on module ID, we should remember subdev pointers
so that we can send certain custom commands where
needed. */
// ?????
}
static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw)
{
unsigned int idx;
const struct pvr2_string_table *cm;
const struct pvr2_device_client_table *ct;
cm = &hdw->hdw_desc->client_modules;
for (idx = 0; idx < cm->cnt; idx++) {
request_module(cm->lst[idx]);
}
ct = &hdw->hdw_desc->client_table;
for (idx = 0; idx < ct->cnt; idx++) {
pvr2_hdw_load_subdev(hdw,&ct->lst[idx]);
}
}
static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
{
int ret;
@ -1973,10 +2086,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
if (!pvr2_hdw_dev_ok(hdw)) return;
for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
request_module(hdw->hdw_desc->client_modules.lst[idx]);
}
if (!hdw->hdw_desc->flag_no_powerup) {
pvr2_hdw_cmd_powerup(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
@ -1995,6 +2104,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
pvr2_i2c_core_init(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
pvr2_hdw_load_modules(hdw);
for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
cptr = hdw->controls + idx;
if (cptr->info->skip_init) continue;

View File

@ -608,6 +608,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
hdw->i2c_adap.algo = &hdw->i2c_algo;
hdw->i2c_adap.algo_data = hdw;
hdw->i2c_linked = !0;
i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
i2c_add_adapter(&hdw->i2c_adap);
if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
/* Probe for a different type of IR receiver on this