diff options
author | Erik Andr?n <erik.andren@gmail.com> | 2009-01-03 10:10:11 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-04-06 20:44:46 -0400 |
commit | d9c700d415f05760f0129f798223cb4ac6a46d4b (patch) | |
tree | df82be24a75ad853e69a5304a096eb7962b46ded /drivers/media | |
parent | 1a3dd5d91a46417e887e285e6d7ceb68097a8535 (diff) |
V4L/DVB (11423): gspca - m5602-ov9650: Add a disconnect hook, setup a ctrl cache ctrl.
Reading and writing to a register doesn't always work reliably. Add a cache
and ensure that it is deallocated properly upon module disconnect.
Signed-off-by: Erik Andr?n <erik.andren@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_bridge.h | 3 | ||||
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_core.c | 13 | ||||
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_ov9650.c | 42 | ||||
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 | ||||
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_sensor.h | 3 |
5 files changed, 54 insertions, 9 deletions
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h index de76a1613015..8f1cea6fd3bf 100644 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h | |||
@@ -117,6 +117,9 @@ struct sd { | |||
117 | 117 | ||
118 | struct sd_desc *desc; | 118 | struct sd_desc *desc; |
119 | 119 | ||
120 | /* Sensor private data */ | ||
121 | void *sensor_priv; | ||
122 | |||
120 | /* The current frame's id, used to detect frame boundaries */ | 123 | /* The current frame's id, used to detect frame boundaries */ |
121 | u8 frame_id; | 124 | u8 frame_id; |
122 | 125 | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 0d84a12d59f0..1aac2985fee6 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
@@ -362,6 +362,17 @@ static int m5602_probe(struct usb_interface *intf, | |||
362 | THIS_MODULE); | 362 | THIS_MODULE); |
363 | } | 363 | } |
364 | 364 | ||
365 | void m5602_disconnect(struct usb_interface *intf) | ||
366 | { | ||
367 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | ||
368 | struct sd *sd = (struct sd *) gspca_dev; | ||
369 | |||
370 | if (sd->sensor->disconnect) | ||
371 | sd->sensor->disconnect(sd); | ||
372 | |||
373 | gspca_disconnect(intf); | ||
374 | } | ||
375 | |||
365 | static struct usb_driver sd_driver = { | 376 | static struct usb_driver sd_driver = { |
366 | .name = MODULE_NAME, | 377 | .name = MODULE_NAME, |
367 | .id_table = m5602_table, | 378 | .id_table = m5602_table, |
@@ -370,7 +381,7 @@ static struct usb_driver sd_driver = { | |||
370 | .suspend = gspca_suspend, | 381 | .suspend = gspca_suspend, |
371 | .resume = gspca_resume, | 382 | .resume = gspca_resume, |
372 | #endif | 383 | #endif |
373 | .disconnect = gspca_disconnect | 384 | .disconnect = m5602_disconnect |
374 | }; | 385 | }; |
375 | 386 | ||
376 | /* -- module insert / remove -- */ | 387 | /* -- module insert / remove -- */ |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 15288a114fe2..39902652d24a 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -220,6 +220,7 @@ int ov9650_probe(struct sd *sd) | |||
220 | { | 220 | { |
221 | int err = 0; | 221 | int err = 0; |
222 | u8 prod_id = 0, ver_id = 0, i; | 222 | u8 prod_id = 0, ver_id = 0, i; |
223 | s32 *sensor_settings; | ||
223 | 224 | ||
224 | if (force_sensor) { | 225 | if (force_sensor) { |
225 | if (force_sensor == OV9650_SENSOR) { | 226 | if (force_sensor == OV9650_SENSOR) { |
@@ -238,9 +239,10 @@ int ov9650_probe(struct sd *sd) | |||
238 | u8 data = preinit_ov9650[i][2]; | 239 | u8 data = preinit_ov9650[i][2]; |
239 | if (preinit_ov9650[i][0] == SENSOR) | 240 | if (preinit_ov9650[i][0] == SENSOR) |
240 | err = m5602_write_sensor(sd, | 241 | err = m5602_write_sensor(sd, |
241 | preinit_ov9650[i][1], &data, 1); | 242 | preinit_ov9650[i][1], &data, 1); |
242 | else | 243 | else |
243 | err = m5602_write_bridge(sd, preinit_ov9650[i][1], data); | 244 | err = m5602_write_bridge(sd, |
245 | preinit_ov9650[i][1], data); | ||
244 | } | 246 | } |
245 | 247 | ||
246 | if (err < 0) | 248 | if (err < 0) |
@@ -260,10 +262,21 @@ int ov9650_probe(struct sd *sd) | |||
260 | return -ENODEV; | 262 | return -ENODEV; |
261 | 263 | ||
262 | sensor_found: | 264 | sensor_found: |
265 | |||
266 | sensor_settings = kmalloc( | ||
267 | ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL); | ||
268 | if (!sensor_settings) | ||
269 | return -ENOMEM; | ||
270 | |||
263 | sd->gspca_dev.cam.cam_mode = ov9650_modes; | 271 | sd->gspca_dev.cam.cam_mode = ov9650_modes; |
264 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); | 272 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); |
265 | sd->desc->ctrls = ov9650_ctrls; | 273 | sd->desc->ctrls = ov9650_ctrls; |
266 | sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); | 274 | sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); |
275 | |||
276 | for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++) | ||
277 | sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; | ||
278 | sd->sensor_priv = sensor_settings; | ||
279 | |||
267 | return 0; | 280 | return 0; |
268 | } | 281 | } |
269 | 282 | ||
@@ -324,7 +337,8 @@ int ov9650_start(struct sd *sd) | |||
324 | if (err < 0) | 337 | if (err < 0) |
325 | return err; | 338 | return err; |
326 | 339 | ||
327 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff)); | 340 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, |
341 | ((ver_offs >> 8) & 0xff)); | ||
328 | if (err < 0) | 342 | if (err < 0) |
329 | return err; | 343 | return err; |
330 | 344 | ||
@@ -344,13 +358,13 @@ int ov9650_start(struct sd *sd) | |||
344 | if (err < 0) | 358 | if (err < 0) |
345 | return err; | 359 | return err; |
346 | 360 | ||
347 | for (i = 0; i < 2 && !err; i++) { | 361 | for (i = 0; i < 2 && !err; i++) |
348 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); | 362 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); |
349 | } | ||
350 | if (err < 0) | 363 | if (err < 0) |
351 | return err; | 364 | return err; |
352 | 365 | ||
353 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff); | 366 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, |
367 | (hor_offs >> 8) & 0xff); | ||
354 | if (err < 0) | 368 | if (err < 0) |
355 | return err; | 369 | return err; |
356 | 370 | ||
@@ -358,11 +372,13 @@ int ov9650_start(struct sd *sd) | |||
358 | if (err < 0) | 372 | if (err < 0) |
359 | return err; | 373 | return err; |
360 | 374 | ||
361 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff); | 375 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, |
376 | ((width + hor_offs) >> 8) & 0xff); | ||
362 | if (err < 0) | 377 | if (err < 0) |
363 | return err; | 378 | return err; |
364 | 379 | ||
365 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff)); | 380 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, |
381 | ((width + hor_offs) & 0xff)); | ||
366 | if (err < 0) | 382 | if (err < 0) |
367 | return err; | 383 | return err; |
368 | 384 | ||
@@ -431,6 +447,16 @@ int ov9650_power_down(struct sd *sd) | |||
431 | return err; | 447 | return err; |
432 | } | 448 | } |
433 | 449 | ||
450 | void ov9650_disconnect(struct sd *sd) | ||
451 | { | ||
452 | ov9650_stop(sd); | ||
453 | ov9650_power_down(sd); | ||
454 | |||
455 | sd->sensor = NULL; | ||
456 | |||
457 | kfree(sd->sensor_priv); | ||
458 | } | ||
459 | |||
434 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | 460 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) |
435 | { | 461 | { |
436 | struct sd *sd = (struct sd *) gspca_dev; | 462 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h index eafe4216beef..1f27a857bf3f 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h | |||
@@ -138,6 +138,7 @@ int ov9650_init(struct sd *sd); | |||
138 | int ov9650_start(struct sd *sd); | 138 | int ov9650_start(struct sd *sd); |
139 | int ov9650_stop(struct sd *sd); | 139 | int ov9650_stop(struct sd *sd); |
140 | int ov9650_power_down(struct sd *sd); | 140 | int ov9650_power_down(struct sd *sd); |
141 | void ov9650_disconnect(struct sd *sd); | ||
141 | 142 | ||
142 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | 143 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); |
143 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | 144 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); |
@@ -167,6 +168,7 @@ const static struct m5602_sensor ov9650 = { | |||
167 | .start = ov9650_start, | 168 | .start = ov9650_start, |
168 | .stop = ov9650_stop, | 169 | .stop = ov9650_stop, |
169 | .power_down = ov9650_power_down, | 170 | .power_down = ov9650_power_down, |
171 | .disconnect = ov9650_disconnect, | ||
170 | }; | 172 | }; |
171 | 173 | ||
172 | static const unsigned char preinit_ov9650[][3] = | 174 | static const unsigned char preinit_ov9650[][3] = |
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h index 5c8fb7abae54..0d3026936f2e 100644 --- a/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/drivers/media/video/gspca/m5602/m5602_sensor.h | |||
@@ -59,6 +59,9 @@ struct m5602_sensor { | |||
59 | /* Executed when the camera ends to send data */ | 59 | /* Executed when the camera ends to send data */ |
60 | int (*stop)(struct sd *sd); | 60 | int (*stop)(struct sd *sd); |
61 | 61 | ||
62 | /* Executed when the device is disconnected */ | ||
63 | void (*disconnect)(struct sd *sd); | ||
64 | |||
62 | /* Performs a power down sequence */ | 65 | /* Performs a power down sequence */ |
63 | int (*power_down)(struct sd *sd); | 66 | int (*power_down)(struct sd *sd); |
64 | }; | 67 | }; |