aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorErik Andr?n <erik.andren@gmail.com>2009-01-03 10:10:11 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-04-06 20:44:46 -0400
commitd9c700d415f05760f0129f798223cb4ac6a46d4b (patch)
treedf82be24a75ad853e69a5304a096eb7962b46ded /drivers/media
parent1a3dd5d91a46417e887e285e6d7ceb68097a8535 (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.h3
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c13
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c42
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_sensor.h3
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
365void 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
365static struct usb_driver sd_driver = { 376static 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
262sensor_found: 264sensor_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
450void 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
434int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 460int 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);
138int ov9650_start(struct sd *sd); 138int ov9650_start(struct sd *sd);
139int ov9650_stop(struct sd *sd); 139int ov9650_stop(struct sd *sd);
140int ov9650_power_down(struct sd *sd); 140int ov9650_power_down(struct sd *sd);
141void ov9650_disconnect(struct sd *sd);
141 142
142int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 143int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
143int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 144int 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
172static const unsigned char preinit_ov9650[][3] = 174static 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};