diff options
author | Mike Isely <isely@pobox.com> | 2009-03-06 21:42:20 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:33 -0400 |
commit | e9c64a78dbd7c4f6c4a31c4040f340f732bf4ec5 (patch) | |
tree | b8bdf899e92f241d4b7581276b62461a968f3f76 /drivers/media | |
parent | acd92d40ccaf140d27e6bd5b83573294165ebbdf (diff) |
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-devattr.h | 28 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 119 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 |
3 files changed, 144 insertions, 4 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index cb3a33eb0276..f06923986824 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h | |||
@@ -33,6 +33,31 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | 35 | ||
36 | #define PVR2_CLIENT_ID_MSP3400 1 | ||
37 | #define PVR2_CLIENT_ID_CX25840 2 | ||
38 | #define PVR2_CLIENT_ID_SAA7115 3 | ||
39 | #define PVR2_CLIENT_ID_TUNER 4 | ||
40 | #define PVR2_CLIENT_ID_CS53132A 5 | ||
41 | |||
42 | struct pvr2_device_client_desc { | ||
43 | /* One ovr PVR2_CLIENT_ID_xxxx */ | ||
44 | unsigned char module_id; | ||
45 | |||
46 | /* Null-terminated array of I2C addresses to try in order | ||
47 | initialize the module. It's safe to make this null terminated | ||
48 | since we're never going to encounter an i2c device with an | ||
49 | address of zero. If this is a null pointer or zero-length, | ||
50 | then no I2C addresses have been specified, in which case we'll | ||
51 | try some compiled in defaults for now. */ | ||
52 | unsigned char *i2c_address_list; | ||
53 | }; | ||
54 | |||
55 | struct pvr2_device_client_table { | ||
56 | const struct pvr2_device_client_desc *lst; | ||
57 | unsigned char cnt; | ||
58 | }; | ||
59 | |||
60 | |||
36 | struct pvr2_string_table { | 61 | struct pvr2_string_table { |
37 | const char **lst; | 62 | const char **lst; |
38 | unsigned int cnt; | 63 | unsigned int cnt; |
@@ -66,6 +91,9 @@ struct pvr2_device_desc { | |||
66 | /* List of additional client modules we need to load */ | 91 | /* List of additional client modules we need to load */ |
67 | struct pvr2_string_table client_modules; | 92 | struct pvr2_string_table client_modules; |
68 | 93 | ||
94 | /* List of defined client modules we need to load */ | ||
95 | struct pvr2_device_client_table client_table; | ||
96 | |||
69 | /* List of FX2 firmware file names we should search; if empty then | 97 | /* List of FX2 firmware file names we should search; if empty then |
70 | FX2 firmware check / load is skipped and we assume the device | 98 | FX2 firmware check / load is skipped and we assume the device |
71 | was initialized from internal ROM. */ | 99 | was initialized from internal ROM. */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e6c4660786a6..faa94cef2c55 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -105,6 +105,20 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); | |||
105 | /* size of a firmware chunk */ | 105 | /* size of a firmware chunk */ |
106 | #define FIRMWARE_CHUNK_SIZE 0x2000 | 106 | #define FIRMWARE_CHUNK_SIZE 0x2000 |
107 | 107 | ||
108 | static const char *module_names[] = { | ||
109 | [PVR2_CLIENT_ID_MSP3400] = "msp3400", | ||
110 | [PVR2_CLIENT_ID_CX25840] = "cx25840", | ||
111 | [PVR2_CLIENT_ID_SAA7115] = "saa7115", | ||
112 | [PVR2_CLIENT_ID_TUNER] = "tuner", | ||
113 | [PVR2_CLIENT_ID_CS53132A] = "cs53132a", | ||
114 | }; | ||
115 | |||
116 | |||
117 | static const unsigned char *module_i2c_addresses[] = { | ||
118 | [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", | ||
119 | }; | ||
120 | |||
121 | |||
108 | /* Define the list of additional controls we'll dynamically construct based | 122 | /* Define the list of additional controls we'll dynamically construct based |
109 | on query of the cx2341x module. */ | 123 | on query of the cx2341x module. */ |
110 | struct pvr2_mpeg_ids { | 124 | struct pvr2_mpeg_ids { |
@@ -1934,6 +1948,105 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1934 | } | 1948 | } |
1935 | 1949 | ||
1936 | 1950 | ||
1951 | static unsigned int pvr2_copy_i2c_addr_list( | ||
1952 | unsigned short *dst, const unsigned char *src, | ||
1953 | unsigned int dst_max) | ||
1954 | { | ||
1955 | unsigned int cnt; | ||
1956 | if (!src) return 0; | ||
1957 | while (src[cnt] && (cnt + 1) < dst_max) { | ||
1958 | dst[cnt] = src[cnt]; | ||
1959 | cnt++; | ||
1960 | } | ||
1961 | dst[cnt] = I2C_CLIENT_END; | ||
1962 | return cnt; | ||
1963 | } | ||
1964 | |||
1965 | |||
1966 | static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | ||
1967 | const struct pvr2_device_client_desc *cd) | ||
1968 | { | ||
1969 | const char *fname; | ||
1970 | unsigned char mid; | ||
1971 | struct v4l2_subdev *sd; | ||
1972 | unsigned int i2ccnt; | ||
1973 | const unsigned char *p; | ||
1974 | /* Arbitrary count - max # i2c addresses we will probe */ | ||
1975 | unsigned short i2caddr[25]; | ||
1976 | |||
1977 | mid = cd->module_id; | ||
1978 | fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; | ||
1979 | if (!fname) { | ||
1980 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1981 | "Module ID %u for device %s is unknown" | ||
1982 | " (this is probably a bad thing...)", | ||
1983 | mid, | ||
1984 | hdw->hdw_desc->description); | ||
1985 | return; | ||
1986 | } | ||
1987 | |||
1988 | i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, | ||
1989 | ARRAY_SIZE(i2caddr)); | ||
1990 | if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ? | ||
1991 | module_i2c_addresses[mid] : NULL) != NULL)) { | ||
1992 | /* Second chance: Try default i2c address list */ | ||
1993 | i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, | ||
1994 | ARRAY_SIZE(i2caddr)); | ||
1995 | } | ||
1996 | |||
1997 | if (!i2ccnt) { | ||
1998 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1999 | "Module ID %u for device %s:" | ||
2000 | " No i2c addresses" | ||
2001 | " (this is probably a bad thing...)", | ||
2002 | mid, hdw->hdw_desc->description); | ||
2003 | return; | ||
2004 | } | ||
2005 | |||
2006 | /* Note how the 2nd and 3rd arguments are the same for both | ||
2007 | * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? | ||
2008 | * Well the 2nd argument is the module name to load, while the 3rd | ||
2009 | * argument is documented in the framework as being the "chipid" - | ||
2010 | * and every other place where I can find examples of this, the | ||
2011 | * "chipid" appears to just be the module name again. So here we | ||
2012 | * just do the same thing. */ | ||
2013 | if (i2ccnt == 1) { | ||
2014 | sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, | ||
2015 | fname, fname, | ||
2016 | i2caddr[0]); | ||
2017 | } else { | ||
2018 | sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, | ||
2019 | fname, fname, | ||
2020 | i2caddr); | ||
2021 | } | ||
2022 | |||
2023 | // ????? | ||
2024 | /* Based on module ID, we should remember subdev pointers | ||
2025 | so that we can send certain custom commands where | ||
2026 | needed. */ | ||
2027 | // ????? | ||
2028 | |||
2029 | } | ||
2030 | |||
2031 | |||
2032 | static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) | ||
2033 | { | ||
2034 | unsigned int idx; | ||
2035 | const struct pvr2_string_table *cm; | ||
2036 | const struct pvr2_device_client_table *ct; | ||
2037 | |||
2038 | cm = &hdw->hdw_desc->client_modules; | ||
2039 | for (idx = 0; idx < cm->cnt; idx++) { | ||
2040 | request_module(cm->lst[idx]); | ||
2041 | } | ||
2042 | |||
2043 | ct = &hdw->hdw_desc->client_table; | ||
2044 | for (idx = 0; idx < ct->cnt; idx++) { | ||
2045 | pvr2_hdw_load_subdev(hdw,&ct->lst[idx]); | ||
2046 | } | ||
2047 | } | ||
2048 | |||
2049 | |||
1937 | static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | 2050 | static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) |
1938 | { | 2051 | { |
1939 | int ret; | 2052 | int ret; |
@@ -1973,10 +2086,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1973 | 2086 | ||
1974 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2087 | if (!pvr2_hdw_dev_ok(hdw)) return; |
1975 | 2088 | ||
1976 | for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { | ||
1977 | request_module(hdw->hdw_desc->client_modules.lst[idx]); | ||
1978 | } | ||
1979 | |||
1980 | if (!hdw->hdw_desc->flag_no_powerup) { | 2089 | if (!hdw->hdw_desc->flag_no_powerup) { |
1981 | pvr2_hdw_cmd_powerup(hdw); | 2090 | pvr2_hdw_cmd_powerup(hdw); |
1982 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2091 | if (!pvr2_hdw_dev_ok(hdw)) return; |
@@ -1995,6 +2104,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1995 | pvr2_i2c_core_init(hdw); | 2104 | pvr2_i2c_core_init(hdw); |
1996 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2105 | if (!pvr2_hdw_dev_ok(hdw)) return; |
1997 | 2106 | ||
2107 | pvr2_hdw_load_modules(hdw); | ||
2108 | |||
1998 | for (idx = 0; idx < CTRLDEF_COUNT; idx++) { | 2109 | for (idx = 0; idx < CTRLDEF_COUNT; idx++) { |
1999 | cptr = hdw->controls + idx; | 2110 | cptr = hdw->controls + idx; |
2000 | if (cptr->info->skip_init) continue; | 2111 | if (cptr->info->skip_init) continue; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 2ba429f1bc8e..1129fe40c04c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -608,6 +608,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
608 | hdw->i2c_adap.algo = &hdw->i2c_algo; | 608 | hdw->i2c_adap.algo = &hdw->i2c_algo; |
609 | hdw->i2c_adap.algo_data = hdw; | 609 | hdw->i2c_adap.algo_data = hdw; |
610 | hdw->i2c_linked = !0; | 610 | hdw->i2c_linked = !0; |
611 | i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); | ||
611 | i2c_add_adapter(&hdw->i2c_adap); | 612 | i2c_add_adapter(&hdw->i2c_adap); |
612 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { | 613 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { |
613 | /* Probe for a different type of IR receiver on this | 614 | /* Probe for a different type of IR receiver on this |