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

Commit f4d52025 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (8357): gspca: Perfect exposure for sn9c10x, sensor ov6650.

parent 3647fea8
Loading
Loading
Loading
Loading
+43 −11
Original line number Diff line number Diff line
@@ -121,8 +121,8 @@ static struct ctrl sd_ctrls[] = {
			.id = V4L2_CID_EXPOSURE,
			.type = V4L2_CTRL_TYPE_INTEGER,
			.name = "Exposure",
#define EXPOSURE_DEF 0
#define EXPOSURE_KNEE 176 /* 10 fps */
#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
			.minimum = 0,
			.maximum = 255,
			.step = 1,
@@ -611,8 +611,6 @@ static void setgain(struct gspca_dev *gspca_dev)
static void setexposure(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
	/* translate 0 - 255 to a number of fps in a 30 - 1 scale */
	int fps = 30 - sd->exposure * 29 / 255;

	switch (sd->sensor) {
	case SENSOR_TAS5110: {
@@ -621,19 +619,53 @@ static void setexposure(struct gspca_dev *gspca_dev)
		/* register 19's high nibble contains the sn9c10x clock divider
		   The high nibble configures the no fps according to the
		   formula: 60 / high_nibble. With a maximum of 30 fps */
		reg = 60 / fps;
		if (reg > 15)
		reg = 120 * sd->exposure / 1000;
		if (reg < 2)
			reg = 2;
		else if (reg > 15)
			reg = 15;
		reg = (reg << 4) | 0x0b;
		reg_w(gspca_dev, 0x19, &reg, 1);
		break;
	    }
	case SENSOR_OV6650: {
		__u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
		i2c[3] = 30 / fps - 1;
		if (i2c[3] > 15)
			i2c[3] = 15;
		i2c[3] |= 0xc0;
		/* The ov6650 has 2 registers which both influence exposure,
		   first there is register 11, whose low nibble sets the no fps
		   according to: fps = 30 / (low_nibble + 1)

		   The fps configures the maximum exposure setting, but it is
		   possible to use less exposure then what the fps maximum
		   allows by setting register 10. register 10 configures the
		   actual exposure as quotient of the full exposure, with 0
		   being no exposure at all (not very usefull) and reg10_max
		   being max exposure possible at that framerate.

		   The code maps our 0 - 510 ms exposure ctrl to these 2
		   registers, trying to keep fps as high as possible.
		*/
		__u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
		int reg10, reg11;
		/* No clear idea why, but setting reg10 above this value
		   results in no change */
		const int reg10_max = 0x4d;

		reg11 = (60 * sd->exposure + 999) / 1000;
		if (reg11 < 1)
			reg11 = 1;
		else if (reg11 > 16)
			reg11 = 16;

		/* frame exposure time in ms = 1000 * reg11 / 30    ->
		reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
		reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
		if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
			reg10 = 1;
		else if (reg10 > reg10_max)
			reg10 = reg10_max;

		/* Write reg 10 and reg11 low nibble */
		i2c[3] = reg10;
		i2c[4] |= reg11 - 1;
		if (i2c_w(gspca_dev, i2c) < 0)
			PDEBUG(D_ERR, "i2c error exposure");
		break;