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>
+ /* Sensor private data */
+ void *sensor_priv;
+
/* The current frame's id, used to detect frame boundaries */
u8 frame_id;
/* The current frame's id, used to detect frame boundaries */
u8 frame_id;
+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,
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = m5602_table,
.suspend = gspca_suspend,
.resume = gspca_resume,
#endif
.suspend = gspca_suspend,
.resume = gspca_resume,
#endif
- .disconnect = gspca_disconnect
+ .disconnect = m5602_disconnect
};
/* -- module insert / remove -- */
};
/* -- module insert / remove -- */
{
int err = 0;
u8 prod_id = 0, ver_id = 0, i;
{
int err = 0;
u8 prod_id = 0, ver_id = 0, i;
if (force_sensor) {
if (force_sensor == OV9650_SENSOR) {
if (force_sensor) {
if (force_sensor == OV9650_SENSOR) {
u8 data = preinit_ov9650[i][2];
if (preinit_ov9650[i][0] == SENSOR)
err = m5602_write_sensor(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);
- err = m5602_write_bridge(sd, preinit_ov9650[i][1], data);
+ err = m5602_write_bridge(sd,
+ preinit_ov9650[i][1], data);
return -ENODEV;
sensor_found:
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);
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;
+
- 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));
- for (i = 0; i < 2 && !err; i++) {
+ for (i = 0; i < 2 && !err; i++)
err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
- 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);
- 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);
- 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));
+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;
int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
int ov9650_start(struct sd *sd);
int ov9650_stop(struct sd *sd);
int ov9650_power_down(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);
int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
.start = ov9650_start,
.stop = ov9650_stop,
.power_down = ov9650_power_down,
.start = ov9650_start,
.stop = ov9650_stop,
.power_down = ov9650_power_down,
+ .disconnect = ov9650_disconnect,
};
static const unsigned char preinit_ov9650[][3] =
};
static const unsigned char preinit_ov9650[][3] =
/* Executed when the camera ends to send data */
int (*stop)(struct sd *sd);
/* 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);
};
/* Performs a power down sequence */
int (*power_down)(struct sd *sd);
};