Web lists-archives.com

[Spca50x-devs] PATCH: gspca-mercurial OV7630 control settings




Hi!

With this patch, almost all the controls for my webcam (OV7630) works. The control that works are brightness, exposure and gain (based on Hans patches).

The auto gain control doesn't work, I don't know why, because it should be working. It's disabled by default but if it's enabled, the image gets darker until you can't see anything. Hans, any hints?

The other patch is to correct the i2c_w() function, according to the datasheet, the 3rd status bit is set if there's an error, else is clear. I've patched this, because with the current code, all the calls to i2c_w() returned error but worked fine (the values in the sensor where changed). This is the same behaviour of the sn9c102 kernel driver.

Regards,

Andoni
diff -r 7035f61808ba linux/drivers/media/video/gspca/sonixb.c
--- a/linux/drivers/media/video/gspca/sonixb.c	Tue Jul 15 11:36:42 2008 +0200
+++ b/linux/drivers/media/video/gspca/sonixb.c	Tue Jul 15 08:19:11 2008 -0300
@@ -280,7 +280,7 @@
 	{0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
 	{0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
 /*	{0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},	   jfm */
-	{0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10},	/* jfm */
+	{0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10},	/* jfm */
 	{0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
@@ -289,7 +289,7 @@
 	{0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
 	{0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
 /*	{0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},	   jfm */
-	{0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10},	/* jfm */
+	{0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},	/* jfm */
 	{0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
 	{0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
 	{0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
@@ -515,6 +516,7 @@
 			 goto err;
 		break;
 	    }
+	case  SENSOR_OV7630_3:
 	case  SENSOR_OV7630: {
 		__u8 i2cOV[] =
 			{0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
@@ -609,6 +611,14 @@
 			goto err;
 		break;
 	    }
+	case SENSOR_OV7630_3: {
+		__u8 i2c[] = {0xa0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
+
+		i2c[3] = sd->gain >> 2;
+		if (i2c_w(gspca_dev, i2c) < 0)
+			goto err;
+		break;
+	    }
 	}
 	return;
 err:
@@ -696,6 +706,34 @@
 			PDEBUG(D_ERR, "i2c error exposure");
 		break;
 	    }
+	case SENSOR_OV7630_3: {
+		__u8 i2c[] = {0xb0, 0x21, 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;
+	    }		
 	}
 }
 
@@ -731,6 +769,7 @@
 
 	sd->fr_h_sz = 12;		/* default size of the frame header */
 	sd->sd_desc.nctrls = 2;		/* default nb of ctrls */
+	sd->autogain = AUTOGAIN_DEF;    /* default is autogain active */
 
 	product = id->idProduct;
 /*	switch (id->idVendor) { */
@@ -766,6 +805,10 @@
 		case 0x60b0:			/* SN9C103 */
 			sd->sensor = SENSOR_OV7630_3;
 			sd->fr_h_sz = 18;	/* size of frame header */
+			sd->sensor_has_gain = 1;
+			sd->sd_desc.nctrls = 4;
+			sd->sd_desc.dq_callback = do_autogain;
+			sd->autogain = 0;
 			break;
 		case 0x6024:			/* SN9C102 */
 		case 0x6025:			/* SN9C102 */
@@ -803,7 +846,6 @@
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->gain = GAIN_DEF;
 	sd->exposure = EXPOSURE_DEF;
-	sd->autogain = AUTOGAIN_DEF;
 	if (sd->sensor == SENSOR_OV7630_3)	/* jfm: from win trace */
 		reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
 	return 0;
@@ -966,18 +1008,15 @@
 	reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
 	/* compression register */
 	reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
-	if (sd->sensor != SENSOR_OV7630_3) {
-		/* H_start */
-		reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
-		/* V_START */
-		reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
-	}
+	/* H_start */
+	reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
+	/* V_START */
+	reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
 	/* reset 0x17 SensorClk enable inv Clk 0x60 */
 				/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
 	reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
 	/*MCKSIZE ->3 */	/*fixme: not ov7630*/
-	if (sd->sensor != SENSOR_OV7630_3)
-		reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
+	reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
 	/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
 	reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
 	/* Enable video transfert */
diff -r 7035f61808ba linux/drivers/media/video/gspca/sonixb.c
--- a/linux/drivers/media/video/gspca/sonixb.c	Tue Jul 15 11:36:42 2008 +0200
+++ b/linux/drivers/media/video/gspca/sonixb.c	Tue Jul 15 08:19:11 2008 -0300
@@ -482,8 +482,9 @@
 	while (retry--) {
 		msleep(10);
 		reg_r(gspca_dev, 0x08);
-		if (gspca_dev->usb_buf[0] == 4)
+		if (!(gspca_dev->usb_buf[0] & 0x8))
 			return 0;
+		PDEBUG(D_ERR, "res: %d", gspca_dev->usb_buf[0]);
 	}
 	return -1;
 }
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Spca50x-devs mailing list
Spca50x-devs@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/spca50x-devs