diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 7303df0dc16b..054ce4e3ece7 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -254,7 +254,7 @@ static const __u8 ov7630_sensor_init_com[][8] = { | |||
254 | {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, | 254 | {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, |
255 | {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, | 255 | {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, |
256 | /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ | 256 | /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ |
257 | {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */ | 257 | {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */ |
258 | {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10}, | 258 | {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10}, |
259 | {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10}, | 259 | {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10}, |
260 | {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10}, | 260 | {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10}, |
@@ -262,8 +262,8 @@ static const __u8 ov7630_sensor_init_com[][8] = { | |||
262 | {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10}, | 262 | {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10}, |
263 | {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10}, | 263 | {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10}, |
264 | {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10}, | 264 | {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10}, |
265 | /* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */ | 265 | {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, |
266 | {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */ | 266 | /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */ |
267 | {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10}, | 267 | {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10}, |
268 | {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10}, | 268 | {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10}, |
269 | {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10}, | 269 | {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10}, |
@@ -489,6 +489,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
489 | goto err; | 489 | goto err; |
490 | break; | 490 | break; |
491 | } | 491 | } |
492 | case SENSOR_OV7630_3: | ||
492 | case SENSOR_OV7630: { | 493 | case SENSOR_OV7630: { |
493 | __u8 i2cOV[] = | 494 | __u8 i2cOV[] = |
494 | {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16}; | 495 | {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16}; |
@@ -583,6 +584,14 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
583 | goto err; | 584 | goto err; |
584 | break; | 585 | break; |
585 | } | 586 | } |
587 | case SENSOR_OV7630_3: { | ||
588 | __u8 i2c[] = {0xa0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; | ||
589 | |||
590 | i2c[3] = sd->gain >> 2; | ||
591 | if (i2c_w(gspca_dev, i2c) < 0) | ||
592 | goto err; | ||
593 | break; | ||
594 | } | ||
586 | } | 595 | } |
587 | return; | 596 | return; |
588 | err: | 597 | err: |
@@ -670,6 +679,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
670 | PDEBUG(D_ERR, "i2c error exposure"); | 679 | PDEBUG(D_ERR, "i2c error exposure"); |
671 | break; | 680 | break; |
672 | } | 681 | } |
682 | case SENSOR_OV7630_3: { | ||
683 | __u8 i2c[] = {0xb0, 0x21, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10}; | ||
684 | int reg10, reg11; | ||
685 | /* No clear idea why, but setting reg10 above this value | ||
686 | results in no change */ | ||
687 | const int reg10_max = 0x4d; | ||
688 | |||
689 | reg11 = (60 * sd->exposure + 999) / 1000; | ||
690 | if (reg11 < 1) | ||
691 | reg11 = 1; | ||
692 | else if (reg11 > 16) | ||
693 | reg11 = 16; | ||
694 | |||
695 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | ||
696 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ | ||
697 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); | ||
698 | if (reg10 < 1) /* 0 is a valid value, but is very _black_ */ | ||
699 | reg10 = 1; | ||
700 | else if (reg10 > reg10_max) | ||
701 | reg10 = reg10_max; | ||
702 | |||
703 | /* Write reg 10 and reg11 low nibble */ | ||
704 | i2c[3] = reg10; | ||
705 | i2c[4] |= reg11 - 1; | ||
706 | if (i2c_w(gspca_dev, i2c) < 0) | ||
707 | PDEBUG(D_ERR, "i2c error exposure"); | ||
708 | break; | ||
709 | } | ||
673 | } | 710 | } |
674 | } | 711 | } |
675 | 712 | ||
@@ -705,6 +742,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
705 | 742 | ||
706 | sd->fr_h_sz = 12; /* default size of the frame header */ | 743 | sd->fr_h_sz = 12; /* default size of the frame header */ |
707 | sd->sd_desc.nctrls = 2; /* default nb of ctrls */ | 744 | sd->sd_desc.nctrls = 2; /* default nb of ctrls */ |
745 | sd->autogain = AUTOGAIN_DEF; /* default is autogain active */ | ||
708 | 746 | ||
709 | product = id->idProduct; | 747 | product = id->idProduct; |
710 | /* switch (id->idVendor) { */ | 748 | /* switch (id->idVendor) { */ |
@@ -740,6 +778,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
740 | case 0x60b0: /* SN9C103 */ | 778 | case 0x60b0: /* SN9C103 */ |
741 | sd->sensor = SENSOR_OV7630_3; | 779 | sd->sensor = SENSOR_OV7630_3; |
742 | sd->fr_h_sz = 18; /* size of frame header */ | 780 | sd->fr_h_sz = 18; /* size of frame header */ |
781 | sd->sensor_has_gain = 1; | ||
782 | sd->sd_desc.nctrls = 4; | ||
783 | sd->sd_desc.dq_callback = do_autogain; | ||
784 | sd->autogain = 0; | ||
743 | break; | 785 | break; |
744 | case 0x6024: /* SN9C102 */ | 786 | case 0x6024: /* SN9C102 */ |
745 | case 0x6025: /* SN9C102 */ | 787 | case 0x6025: /* SN9C102 */ |
@@ -777,7 +819,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
777 | sd->brightness = BRIGHTNESS_DEF; | 819 | sd->brightness = BRIGHTNESS_DEF; |
778 | sd->gain = GAIN_DEF; | 820 | sd->gain = GAIN_DEF; |
779 | sd->exposure = EXPOSURE_DEF; | 821 | sd->exposure = EXPOSURE_DEF; |
780 | sd->autogain = AUTOGAIN_DEF; | ||
781 | if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */ | 822 | if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */ |
782 | reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630); | 823 | reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630); |
783 | return 0; | 824 | return 0; |
@@ -940,18 +981,15 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
940 | reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); | 981 | reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); |
941 | /* compression register */ | 982 | /* compression register */ |
942 | reg_w(gspca_dev, 0x18, ®17_19[1], 1); | 983 | reg_w(gspca_dev, 0x18, ®17_19[1], 1); |
943 | if (sd->sensor != SENSOR_OV7630_3) { | 984 | /* H_start */ |
944 | /* H_start */ | 985 | reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); |
945 | reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); | 986 | /* V_START */ |
946 | /* V_START */ | 987 | reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); |
947 | reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); | ||
948 | } | ||
949 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ | 988 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ |
950 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ | 989 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ |
951 | reg_w(gspca_dev, 0x17, ®17_19[0], 1); | 990 | reg_w(gspca_dev, 0x17, ®17_19[0], 1); |
952 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ | 991 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ |
953 | if (sd->sensor != SENSOR_OV7630_3) | 992 | reg_w(gspca_dev, 0x19, ®17_19[2], 1); |
954 | reg_w(gspca_dev, 0x19, ®17_19[2], 1); | ||
955 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ | 993 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ |
956 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); | 994 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); |
957 | /* Enable video transfert */ | 995 | /* Enable video transfert */ |