Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9c700d4 authored by Erik Andr?n's avatar Erik Andr?n Committed by Mauro Carvalho Chehab
Browse files

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: default avatarErik Andr?n <erik.andren@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 1a3dd5d9
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -117,6 +117,9 @@ struct sd {


	struct sd_desc *desc;
	struct sd_desc *desc;


	/* Sensor private data */
	void *sensor_priv;

	/* The current frame's id, used to detect frame boundaries */
	/* The current frame's id, used to detect frame boundaries */
	u8 frame_id;
	u8 frame_id;


+12 −1
Original line number Original line Diff line number Diff line
@@ -362,6 +362,17 @@ static int m5602_probe(struct usb_interface *intf,
			       THIS_MODULE);
			       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 = {
static struct usb_driver sd_driver = {
	.name = MODULE_NAME,
	.name = MODULE_NAME,
	.id_table = m5602_table,
	.id_table = m5602_table,
@@ -370,7 +381,7 @@ static struct usb_driver sd_driver = {
	.suspend = gspca_suspend,
	.suspend = gspca_suspend,
	.resume = gspca_resume,
	.resume = gspca_resume,
#endif
#endif
	.disconnect = gspca_disconnect
	.disconnect = m5602_disconnect
};
};


/* -- module insert / remove -- */
/* -- module insert / remove -- */
+34 −8
Original line number Original line Diff line number Diff line
@@ -220,6 +220,7 @@ int ov9650_probe(struct sd *sd)
{
{
	int err = 0;
	int err = 0;
	u8 prod_id = 0, ver_id = 0, i;
	u8 prod_id = 0, ver_id = 0, i;
	s32 *sensor_settings;


	if (force_sensor) {
	if (force_sensor) {
		if (force_sensor == OV9650_SENSOR) {
		if (force_sensor == OV9650_SENSOR) {
@@ -240,7 +241,8 @@ int ov9650_probe(struct sd *sd)
			err = m5602_write_sensor(sd,
			err = m5602_write_sensor(sd,
				preinit_ov9650[i][1], &data, 1);
				preinit_ov9650[i][1], &data, 1);
		else
		else
			err = m5602_write_bridge(sd, preinit_ov9650[i][1], data);
			err = m5602_write_bridge(sd,
				preinit_ov9650[i][1], data);
	}
	}


	if (err < 0)
	if (err < 0)
@@ -260,10 +262,21 @@ int ov9650_probe(struct sd *sd)
	return -ENODEV;
	return -ENODEV;


sensor_found:
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.cam_mode = ov9650_modes;
	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
	sd->desc->ctrls = ov9650_ctrls;
	sd->desc->ctrls = ov9650_ctrls;
	sd->desc->nctrls = ARRAY_SIZE(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;
	return 0;
}
}


@@ -324,7 +337,8 @@ int ov9650_start(struct sd *sd)
	if (err < 0)
	if (err < 0)
		return err;
		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)
	if (err < 0)
		return err;
		return err;


@@ -344,13 +358,13 @@ int ov9650_start(struct sd *sd)
	if (err < 0)
	if (err < 0)
		return err;
		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);
		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
	}
	if (err < 0)
	if (err < 0)
		return err;
		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)
	if (err < 0)
		return err;
		return err;


@@ -358,11 +372,13 @@ int ov9650_start(struct sd *sd)
	if (err < 0)
	if (err < 0)
		return err;
		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)
	if (err < 0)
		return err;
		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)
	if (err < 0)
		return err;
		return err;


@@ -431,6 +447,16 @@ int ov9650_power_down(struct sd *sd)
	return err;
	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)
int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
{
	struct sd *sd = (struct sd *) gspca_dev;
	struct sd *sd = (struct sd *) gspca_dev;
+2 −0
Original line number Original line Diff line number Diff line
@@ -138,6 +138,7 @@ int ov9650_init(struct sd *sd);
int ov9650_start(struct sd *sd);
int ov9650_start(struct sd *sd);
int ov9650_stop(struct sd *sd);
int ov9650_stop(struct sd *sd);
int ov9650_power_down(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_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
int ov9650_get_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,
	.start = ov9650_start,
	.stop = ov9650_stop,
	.stop = ov9650_stop,
	.power_down = ov9650_power_down,
	.power_down = ov9650_power_down,
	.disconnect = ov9650_disconnect,
};
};


static const unsigned char preinit_ov9650[][3] =
static const unsigned char preinit_ov9650[][3] =
+3 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,9 @@ struct m5602_sensor {
	/* Executed when the camera ends to send data */
	/* Executed when the camera ends to send data */
	int (*stop)(struct sd *sd);
	int (*stop)(struct sd *sd);


	/* Executed when the device is disconnected */
	void (*disconnect)(struct sd *sd);

	/* Performs a power down sequence */
	/* Performs a power down sequence */
	int (*power_down)(struct sd *sd);
	int (*power_down)(struct sd *sd);
};
};