Em 13-12-2010 11:04, Jean-Francois Moine escreveu:
>
> The initial values of the registers 0x01 and 0x17 are taken from the
> senso table at capture start and updated according to the flag PDN_INV.
>
> Their values are updated at each step of the capture initialization and
> memorized for reuse in capture stop.
>
> This patch also fixed automatically some bad hardcoded values of these
> registers.
>
> Signed-off-by: Jean-François Moine <[email protected]>
>
> diff --git a/drivers/media/video/gspca/sonixj.c
> b/drivers/media/video/gspca/sonixj.c
> index 4c10324..880e931 100644
> --- a/drivers/media/video/gspca/sonixj.c
> +++ b/drivers/media/video/gspca/sonixj.c
> @@ -63,6 +63,8 @@ struct sd {
> #define QUALITY_DEF 80
> u8 jpegqual; /* webcam quality */
>
> + u8 reg01;
> + u8 reg17;
> u8 reg18;
> u8 flags;
>
> @@ -2306,8 +2308,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
> {
> struct sd *sd = (struct sd *) gspca_dev;
> int i;
> + u8 reg01, reg17;
> u8 reg0102[2];
> - u8 reg1, reg17;
> const u8 *sn9c1xx;
> const u8 (*init)[8];
> const u8 *reg9a;
> @@ -2341,10 +2343,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
>
> /* sensor clock already enabled in sd_init */
> /* reg_w1(gspca_dev, 0xf1, 0x00); */
> - reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
> + reg01 = sn9c1xx[1];
> + if (sd->flags & PDN_INV)
> + reg01 ^= S_PDN_INV; /* power down inverted */
> + reg_w1(gspca_dev, 0x01, reg01);
>
> /* configure gpio */
> - reg0102[0] = sn9c1xx[1];
> + reg0102[0] = reg01;
> reg0102[1] = sn9c1xx[2];
> if (gspca_dev->audio)
> reg0102[1] |= 0x04; /* keep the audio connection */
> @@ -2370,95 +2375,49 @@ static int sd_start(struct gspca_dev *gspca_dev)
>
> reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
>
> + reg17 = sn9c1xx[0x17];
> switch (sd->sensor) {
> - case SENSOR_ADCM1700:
> - reg_w1(gspca_dev, 0x01, 0x43);
> - reg_w1(gspca_dev, 0x17, 0x62);
> - reg_w1(gspca_dev, 0x01, 0x42);
> - reg_w1(gspca_dev, 0x01, 0x42);
> - break;
> case SENSOR_GC0307:
> - msleep(50);
> - reg_w1(gspca_dev, 0x01, 0x61);
> - reg_w1(gspca_dev, 0x17, 0x22);
> - reg_w1(gspca_dev, 0x01, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x40);
> - msleep(50);
> - break;
> - case SENSOR_MI0360B:
> - reg_w1(gspca_dev, 0x01, 0x61);
> - reg_w1(gspca_dev, 0x17, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x40);
> - break;
> - case SENSOR_MT9V111:
> - reg_w1(gspca_dev, 0x01, 0x61);
> - reg_w1(gspca_dev, 0x17, 0x61);
> - reg_w1(gspca_dev, 0x01, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x40);
> + msleep(50); /*fixme: is it useful? */
> break;
> case SENSOR_OM6802:
> msleep(10);
> reg_w1(gspca_dev, 0x02, 0x73);
> - reg_w1(gspca_dev, 0x17, 0x60);
> + reg17 |= SEN_CLK_EN;
> + reg_w1(gspca_dev, 0x17, reg17);
> reg_w1(gspca_dev, 0x01, 0x22);
> msleep(100);
> - reg_w1(gspca_dev, 0x01, 0x62);
> - reg_w1(gspca_dev, 0x17, 0x64);
> - reg_w1(gspca_dev, 0x17, 0x64);
> - reg_w1(gspca_dev, 0x01, 0x42);
> + reg01 = SCL_SEL_OD | S_PDN_INV;
> + reg17 &= MCK_SIZE_MASK;
> + reg17 |= 0x04; /* clock / 4 */
> + break;
> + }
> + reg01 |= SYS_SEL_48M;
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg17 |= SEN_CLK_EN;
> + reg_w1(gspca_dev, 0x17, reg17);
> + reg01 &= ~S_PWR_DN; /* sensor power on */
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg01 &= ~SYS_SEL_48M;
> + reg_w1(gspca_dev, 0x01, reg01);
> +
> + switch (sd->sensor) {
> + case SENSOR_HV7131R:
> + hv7131r_probe(gspca_dev); /*fixme: is it useful? */
> + break;
> + case SENSOR_OM6802:
> msleep(10);
> - reg_w1(gspca_dev, 0x01, 0x42);
> + reg_w1(gspca_dev, 0x01, reg01);
> i2c_w8(gspca_dev, om6802_init0[0]);
> i2c_w8(gspca_dev, om6802_init0[1]);
> msleep(15);
> reg_w1(gspca_dev, 0x02, 0x71);
> msleep(150);
> break;
> - case SENSOR_OV7630:
> - reg_w1(gspca_dev, 0x01, 0x61);
> - reg_w1(gspca_dev, 0x17, 0xe2);
> - reg_w1(gspca_dev, 0x01, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x40);
> - break;
> - case SENSOR_OV7648:
> - reg_w1(gspca_dev, 0x01, 0x63);
> - reg_w1(gspca_dev, 0x17, 0x20);
> - reg_w1(gspca_dev, 0x01, 0x62);
> - reg_w1(gspca_dev, 0x01, 0x42);
> - break;
> - case SENSOR_PO1030:
> - case SENSOR_SOI768:
> - reg_w1(gspca_dev, 0x01, 0x61);
> - reg_w1(gspca_dev, 0x17, 0x20);
> - reg_w1(gspca_dev, 0x01, 0x60);
> - reg_w1(gspca_dev, 0x01, 0x40);
> - break;
> - case SENSOR_PO2030N:
> - case SENSOR_OV7660:
> - reg_w1(gspca_dev, 0x01, 0x63);
> - reg_w1(gspca_dev, 0x17, 0x20);
> - reg_w1(gspca_dev, 0x01, 0x62);
> - reg_w1(gspca_dev, 0x01, 0x42);
> - break;
> case SENSOR_SP80708:
> - reg_w1(gspca_dev, 0x01, 0x63);
> - reg_w1(gspca_dev, 0x17, 0x20);
> - reg_w1(gspca_dev, 0x01, 0x62);
> - reg_w1(gspca_dev, 0x01, 0x42);
> msleep(100);
> reg_w1(gspca_dev, 0x02, 0x62);
> break;
> - default:
> -/* case SENSOR_HV7131R: */
> -/* case SENSOR_MI0360: */
> -/* case SENSOR_MO4000: */
> - reg_w1(gspca_dev, 0x01, 0x43);
> - reg_w1(gspca_dev, 0x17, 0x61);
> - reg_w1(gspca_dev, 0x01, 0x42);
> - if (sd->sensor == SENSOR_HV7131R)
> - hv7131r_probe(gspca_dev);
> - break;
> }
>
> /* initialize the sensor */
> @@ -2487,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
> }
> reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
> switch (sd->sensor) {
> - case SENSOR_GC0307:
> - reg17 = 0xa2;
> - break;
> - case SENSOR_MT9V111:
> - case SENSOR_MI0360B:
> - reg17 = 0xe0;
> - break;
> - case SENSOR_ADCM1700:
> - case SENSOR_OV7630:
> - reg17 = 0xe2;
> - break;
> - case SENSOR_OV7648:
> - reg17 = 0x20;
> - break;
> - case SENSOR_OV7660:
> - case SENSOR_SOI768:
> - reg17 = 0xa0;
> - break;
> - case SENSOR_PO1030:
> - case SENSOR_PO2030N:
> - reg17 = 0xa0;
> + case SENSOR_OM6802:
> +/* case SENSOR_OV7648: * fixme: sometimes */
> break;
> default:
> - reg17 = 0x60;
> + reg17 |= DEF_EN;
> break;
> }
> reg_w1(gspca_dev, 0x17, reg17);
> @@ -2557,95 +2497,64 @@ static int sd_start(struct gspca_dev *gspca_dev)
>
> init = NULL;
> mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
> + reg01 |= V_TX_EN;
> if (mode)
> - reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
> + reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */
> else
> - reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
> - reg17 = 0x61; /* 0x:20: enable sensor clock */
> + reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */
> + reg17 &= ~MCK_SIZE_MASK;
> + reg17 |= 0x02; /* clock / 2 */
> switch (sd->sensor) {
> case SENSOR_ADCM1700:
> init = adcm1700_sensor_param1;
> - reg1 = 0x46;
> - reg17 = 0xe2;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_GC0307:
> init = gc0307_sensor_param1;
> - reg17 = 0xa2;
> - reg1 = 0x44;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_MI0360B:
> init = mi0360b_sensor_param1;
> - reg1 &= ~0x02; /* don't inverse pin S_PWR_DN */
> - reg17 = 0xe2;
> break;
> case SENSOR_MO4000:
> if (mode) {
> -/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
> - reg1 = 0x06; /* clk 24Mz */
> + reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
> } else {
> - reg17 = 0x22; /* 640 MCKSIZE */
> -/* reg1 = 0x06; * 640 clk 24Mz (done) */
> + reg17 = SEN_CLK_EN | 0x02; /* clock / 2 */
> }
> break;
> case SENSOR_MT9V111:
> init = mt9v111_sensor_param1;
> - if (mode) {
> - reg1 = 0x04; /* 320 clk 48Mhz */
> - } else {
> -/* reg1 = 0x06; * 640 clk 24Mz (done) */
> - reg17 = 0xc2;
> - }
> break;
> case SENSOR_OM6802:
> init = om6802_sensor_param1;
> - reg17 = 0x64; /* 640 MCKSIZE */
> break;
> case SENSOR_OV7630:
> init = ov7630_sensor_param1;
> - reg17 = 0xe2;
> - reg1 = 0x44;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_OV7648:
> init = ov7648_sensor_param1;
> - reg17 = 0x21;
> -/* reg1 = 0x42; * 42 - 46? */
> + reg17 &= ~MCK_SIZE_MASK;
> + reg17 |= 0x01; /* clock / 1 */
> break;
> case SENSOR_OV7660:
> init = ov7660_sensor_param1;
> - if (sd->bridge == BRIDGE_SN9C120) {
> - if (mode) { /* 320x240 - 160x120 */
> - reg17 = 0xa2;
> - reg1 = 0x44; /* 48 Mhz, video trf eneble */
> - }
> - } else {
> - reg17 = 0x22;
> - reg1 = 0x06; /* 24 Mhz, video trf eneble
> - * inverse power down */
> - }
I'm not sure about this... On my tests with the two devices I have with ov7660
(sn9c105 and sn9c120), the original driver uses 48 MHz for all resolutions.
> break;
> case SENSOR_PO1030:
> init = po1030_sensor_param1;
> - reg17 = 0xa2;
> - reg1 = 0x44;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_PO2030N:
> init = po2030n_sensor_param1;
> - reg1 = 0x46;
> - reg17 = 0xa2;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_SOI768:
> init = soi768_sensor_param1;
> - reg1 = 0x44;
> - reg17 = 0xa2;
> + reg01 |= SYS_SEL_48M;
> break;
> case SENSOR_SP80708:
> init = sp80708_sensor_param1;
> - if (mode) {
> -/*?? reg1 = 0x04; * 320 clk 48Mhz */
> - } else {
> - reg1 = 0x46; /* 640 clk 48Mz */
> - reg17 = 0xa2;
> - }
> break;
> }
>
> @@ -2695,7 +2604,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
> setjpegqual(gspca_dev);
>
> reg_w1(gspca_dev, 0x17, reg17);
> - reg_w1(gspca_dev, 0x01, reg1);
> + reg_w1(gspca_dev, 0x01, reg01);
> + sd->reg01 = reg01;
> + sd->reg17 = reg17;
>
> sethvflip(gspca_dev);
> setbrightness(gspca_dev);
> @@ -2717,41 +2628,69 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
> { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
> static const u8 stopsoi768[] =
> { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
> - u8 data;
> - const u8 *sn9c1xx;
> + u8 reg01;
> + u8 reg17;
>
> - data = 0x0b;
> + reg01 = sd->reg01;
> + reg17 = sd->reg17 & ~SEN_CLK_EN;
> switch (sd->sensor) {
> + case SENSOR_ADCM1700:
> + case SENSOR_PO2030N:
> + case SENSOR_SP80708:
> + reg01 |= LED;
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg01 &= ~(LED | V_TX_EN);
> + reg_w1(gspca_dev, 0x01, reg01);
> +/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */
> + break;
> case SENSOR_GC0307:
> - data = 0x29;
> + reg01 |= LED | S_PDN_INV;
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg01 &= ~(LED | V_TX_EN | S_PDN_INV);
Touching at S_PDN_INV here seems wrong. sd->reg01 has already the S_PDN_INV
value stored there, for devices that require it.
The right thing would be to use S_PWR_DN. If you got this from the original
driver USB dump, my guess is that the developer of the original driver got
the wrong bit by mistake. Of course, I may be wrong here.
> + reg_w1(gspca_dev, 0x01, reg01);
> break;
> case SENSOR_HV7131R:
> + reg01 &= ~V_TX_EN;
> + reg_w1(gspca_dev, 0x01, reg01);
> i2c_w8(gspca_dev, stophv7131);
> - data = 0x2b;
> break;
> case SENSOR_MI0360:
> case SENSOR_MI0360B:
> + reg01 &= ~V_TX_EN;
> + reg_w1(gspca_dev, 0x01, reg01);
> +/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */
> i2c_w8(gspca_dev, stopmi0360);
> - data = 0x29;
> break;
> - case SENSOR_OV7648:
> - i2c_w8(gspca_dev, stopov7648);
> - /* fall thru */
> case SENSOR_MT9V111:
> - case SENSOR_OV7630:
> + case SENSOR_OM6802:
> case SENSOR_PO1030:
> - data = 0x29;
> + reg01 &= ~V_TX_EN;
> + reg_w1(gspca_dev, 0x01, reg01);
> + break;
> + case SENSOR_OV7630:
> + case SENSOR_OV7648:
> + reg01 &= ~V_TX_EN;
> + reg_w1(gspca_dev, 0x01, reg01);
> + i2c_w8(gspca_dev, stopov7648);
> + break;
> + case SENSOR_OV7660:
> + reg01 &= ~V_TX_EN;
> + reg_w1(gspca_dev, 0x01, reg01);
> break;
> case SENSOR_SOI768:
> i2c_w8(gspca_dev, stopsoi768);
> - data = 0x29;
> break;
> }
> - sn9c1xx = sn_tb[sd->sensor];
> - reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
> - reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
> - reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
> - reg_w1(gspca_dev, 0x01, data);
> +
> + reg01 |= SCL_SEL_OD;
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg01 |= S_PWR_DN; /* sensor power down */
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg_w1(gspca_dev, 0x17, reg17);
> + reg01 &= ~SYS_SEL_48M; /* clock 24MHz */
> + reg_w1(gspca_dev, 0x01, reg01);
> + reg01 |= LED;
> + reg_w1(gspca_dev, 0x01, reg01);
> /* Don't disable sensor clock as that disables the button on the cam */
> /* reg_w1(gspca_dev, 0xf1, 0x01); */
> }
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html