Browse Source

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>
Erik Andr?n 16 years ago
parent
commit
d9c700d415

+ 3 - 0
drivers/media/video/gspca/m5602/m5602_bridge.h

@@ -117,6 +117,9 @@ struct sd {
 
 	struct sd_desc *desc;
 
+	/* Sensor private data */
+	void *sensor_priv;
+
 	/* The current frame's id, used to detect frame boundaries */
 	u8 frame_id;
 

+ 12 - 1
drivers/media/video/gspca/m5602/m5602_core.c

@@ -362,6 +362,17 @@ static int m5602_probe(struct usb_interface *intf,
 			       THIS_MODULE);
 }
 
+void m5602_disconnect(struct usb_interface *intf)
+{
+	struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor->disconnect)
+		sd->sensor->disconnect(sd);
+
+	gspca_disconnect(intf);
+}
+
 static struct usb_driver sd_driver = {
 	.name = MODULE_NAME,
 	.id_table = m5602_table,
@@ -370,7 +381,7 @@ static struct usb_driver sd_driver = {
 	.suspend = gspca_suspend,
 	.resume = gspca_resume,
 #endif
-	.disconnect = gspca_disconnect
+	.disconnect = m5602_disconnect
 };
 
 /* -- module insert / remove -- */

+ 34 - 8
drivers/media/video/gspca/m5602/m5602_ov9650.c

@@ -220,6 +220,7 @@ int ov9650_probe(struct sd *sd)
 {
 	int err = 0;
 	u8 prod_id = 0, ver_id = 0, i;
+	s32 *sensor_settings;
 
 	if (force_sensor) {
 		if (force_sensor == OV9650_SENSOR) {
@@ -238,9 +239,10 @@ int ov9650_probe(struct sd *sd)
 		u8 data = preinit_ov9650[i][2];
 		if (preinit_ov9650[i][0] == SENSOR)
 			err = m5602_write_sensor(sd,
-					    preinit_ov9650[i][1], &data, 1);
+				preinit_ov9650[i][1], &data, 1);
 		else
-			err = m5602_write_bridge(sd, preinit_ov9650[i][1], data);
+			err = m5602_write_bridge(sd,
+				preinit_ov9650[i][1], data);
 	}
 
 	if (err < 0)
@@ -260,10 +262,21 @@ int ov9650_probe(struct sd *sd)
 	return -ENODEV;
 
 sensor_found:
+
+	sensor_settings = kmalloc(
+		ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
 	sd->gspca_dev.cam.cam_mode = ov9650_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
 	sd->desc->ctrls = ov9650_ctrls;
 	sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
+		sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
+	sd->sensor_priv = sensor_settings;
+
 	return 0;
 }
 
@@ -324,7 +337,8 @@ int ov9650_start(struct sd *sd)
 	if (err < 0)
 		return err;
 
-	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff));
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
+				 ((ver_offs >> 8) & 0xff));
 	if (err < 0)
 		return err;
 
@@ -344,13 +358,13 @@ int ov9650_start(struct sd *sd)
 	if (err < 0)
 		return err;
 
-	for (i = 0; i < 2 && !err; i++) {
+	for (i = 0; i < 2 && !err; i++)
 		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-	}
 	if (err < 0)
 		return err;
 
-	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff);
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+				 (hor_offs >> 8) & 0xff);
 	if (err < 0)
 		return err;
 
@@ -358,11 +372,13 @@ int ov9650_start(struct sd *sd)
 	if (err < 0)
 		return err;
 
-	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff);
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+				 ((width + hor_offs) >> 8) & 0xff);
 	if (err < 0)
 		return err;
 
-	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff));
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+				 ((width + hor_offs) & 0xff));
 	if (err < 0)
 		return err;
 
@@ -431,6 +447,16 @@ int ov9650_power_down(struct sd *sd)
 	return err;
 }
 
+void ov9650_disconnect(struct sd *sd)
+{
+	ov9650_stop(sd);
+	ov9650_power_down(sd);
+
+	sd->sensor = NULL;
+
+	kfree(sd->sensor_priv);
+}
+
 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;

+ 2 - 0
drivers/media/video/gspca/m5602/m5602_ov9650.h

@@ -138,6 +138,7 @@ int ov9650_init(struct sd *sd);
 int ov9650_start(struct sd *sd);
 int ov9650_stop(struct sd *sd);
 int ov9650_power_down(struct sd *sd);
+void ov9650_disconnect(struct sd *sd);
 
 int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -167,6 +168,7 @@ const static struct m5602_sensor ov9650 = {
 	.start = ov9650_start,
 	.stop = ov9650_stop,
 	.power_down = ov9650_power_down,
+	.disconnect = ov9650_disconnect,
 };
 
 static const unsigned char preinit_ov9650[][3] =

+ 3 - 0
drivers/media/video/gspca/m5602/m5602_sensor.h

@@ -59,6 +59,9 @@ struct m5602_sensor {
 	/* Executed when the camera ends to send data */
 	int (*stop)(struct sd *sd);
 
+	/* Executed when the device is disconnected */
+	void (*disconnect)(struct sd *sd);
+
 	/* Performs a power down sequence */
 	int (*power_down)(struct sd *sd);
 };