diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-07 01:16:47 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:20:15 -0400 |
commit | d2ebd0f806fdb6104903365e355675934eec22b2 (patch) | |
tree | 8455ec9d42ac4a8cff60a4b5261a88814bca5818 /drivers | |
parent | 4d708a5e9e5db74da28965fa00082d8c9323f523 (diff) |
V4L/DVB (12698): em28xx: ir-kbd-i2c init data needs a persistent object
ir-kbd-i2c's ir_probe() function can be called much later (i.e. at
ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data
allocated off of the stack in cx18_i2c_new_ir() at registration time.
Make sure we pass a pointer to a persistent IR_i2c_init_data object at
i2c registration time.
Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to
rise this question.
Before this patch, if ir-kbd-i2c were probed after em28xx, trash data
were used. After the patch, no matter what order, it is properly
reported as tested by me:
input: i2c IR (i2c IR (EM2840 Hauppaug as /class/input/input10
ir-kbd-i2c: i2c IR (i2c IR (EM2840 Hauppaug detected at i2c-4/4-0030/ir0 [em28xx #0]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 32 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 4 |
2 files changed, 19 insertions, 17 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f46b8a5c3a61..c55634a674ba 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -2196,8 +2196,6 @@ static int em28xx_hint_board(struct em28xx *dev) | |||
2196 | /* ----------------------------------------------------------------------- */ | 2196 | /* ----------------------------------------------------------------------- */ |
2197 | void em28xx_register_i2c_ir(struct em28xx *dev) | 2197 | void em28xx_register_i2c_ir(struct em28xx *dev) |
2198 | { | 2198 | { |
2199 | struct i2c_board_info info; | ||
2200 | struct IR_i2c_init_data init_data; | ||
2201 | const unsigned short addr_list[] = { | 2199 | const unsigned short addr_list[] = { |
2202 | 0x30, 0x47, I2C_CLIENT_END | 2200 | 0x30, 0x47, I2C_CLIENT_END |
2203 | }; | 2201 | }; |
@@ -2205,9 +2203,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2205 | if (disable_ir) | 2203 | if (disable_ir) |
2206 | return; | 2204 | return; |
2207 | 2205 | ||
2208 | memset(&info, 0, sizeof(struct i2c_board_info)); | 2206 | memset(&dev->info, 0, sizeof(&dev->info)); |
2209 | memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); | 2207 | memset(&dev->init_data, 0, sizeof(dev->init_data)); |
2210 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 2208 | strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); |
2211 | 2209 | ||
2212 | /* detect & configure */ | 2210 | /* detect & configure */ |
2213 | switch (dev->model) { | 2211 | switch (dev->model) { |
@@ -2217,19 +2215,19 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2217 | break; | 2215 | break; |
2218 | case (EM2800_BOARD_TERRATEC_CINERGY_200): | 2216 | case (EM2800_BOARD_TERRATEC_CINERGY_200): |
2219 | case (EM2820_BOARD_TERRATEC_CINERGY_250): | 2217 | case (EM2820_BOARD_TERRATEC_CINERGY_250): |
2220 | init_data.ir_codes = &ir_codes_em_terratec_table; | 2218 | dev->init_data.ir_codes = &ir_codes_em_terratec_table; |
2221 | init_data.get_key = em28xx_get_key_terratec; | 2219 | dev->init_data.get_key = em28xx_get_key_terratec; |
2222 | init_data.name = "i2c IR (EM28XX Terratec)"; | 2220 | dev->init_data.name = "i2c IR (EM28XX Terratec)"; |
2223 | break; | 2221 | break; |
2224 | case (EM2820_BOARD_PINNACLE_USB_2): | 2222 | case (EM2820_BOARD_PINNACLE_USB_2): |
2225 | init_data.ir_codes = &ir_codes_pinnacle_grey_table; | 2223 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; |
2226 | init_data.get_key = em28xx_get_key_pinnacle_usb_grey; | 2224 | dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; |
2227 | init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; | 2225 | dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; |
2228 | break; | 2226 | break; |
2229 | case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): | 2227 | case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): |
2230 | init_data.ir_codes = &ir_codes_hauppauge_new_table; | 2228 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; |
2231 | init_data.get_key = em28xx_get_key_em_haup; | 2229 | dev->init_data.get_key = em28xx_get_key_em_haup; |
2232 | init_data.name = "i2c IR (EM2840 Hauppauge)"; | 2230 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; |
2233 | break; | 2231 | break; |
2234 | case (EM2820_BOARD_MSI_VOX_USB_2): | 2232 | case (EM2820_BOARD_MSI_VOX_USB_2): |
2235 | break; | 2233 | break; |
@@ -2241,9 +2239,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2241 | break; | 2239 | break; |
2242 | } | 2240 | } |
2243 | 2241 | ||
2244 | if (init_data.name) | 2242 | if (dev->init_data.name) |
2245 | info.platform_data = &init_data; | 2243 | dev->info.platform_data = &dev->init_data; |
2246 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); | 2244 | i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); |
2247 | } | 2245 | } |
2248 | 2246 | ||
2249 | void em28xx_card_setup(struct em28xx *dev) | 2247 | void em28xx_card_setup(struct em28xx *dev) |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 217f948e03d7..bc825bdd65be 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -596,6 +596,10 @@ struct em28xx { | |||
596 | struct delayed_work sbutton_query_work; | 596 | struct delayed_work sbutton_query_work; |
597 | 597 | ||
598 | struct em28xx_dvb *dvb; | 598 | struct em28xx_dvb *dvb; |
599 | |||
600 | /* I2C keyboard data */ | ||
601 | struct i2c_board_info info; | ||
602 | struct IR_i2c_init_data init_data; | ||
599 | }; | 603 | }; |
600 | 604 | ||
601 | struct em28xx_ops { | 605 | struct em28xx_ops { |