diff options
Diffstat (limited to 'drivers/media/video/gspca/mr97310a.c')
-rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 226 |
1 files changed, 193 insertions, 33 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 9154870e07d2..33744e724eaa 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -57,6 +57,14 @@ | |||
57 | #define MR97310A_GAIN_MAX 31 | 57 | #define MR97310A_GAIN_MAX 31 |
58 | #define MR97310A_GAIN_DEFAULT 25 | 58 | #define MR97310A_GAIN_DEFAULT 25 |
59 | 59 | ||
60 | #define MR97310A_CONTRAST_MIN 0 | ||
61 | #define MR97310A_CONTRAST_MAX 31 | ||
62 | #define MR97310A_CONTRAST_DEFAULT 23 | ||
63 | |||
64 | #define MR97310A_CS_GAIN_MIN 0 | ||
65 | #define MR97310A_CS_GAIN_MAX 0x7ff | ||
66 | #define MR97310A_CS_GAIN_DEFAULT 0x110 | ||
67 | |||
60 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | 68 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
61 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | 69 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
62 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | 70 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
@@ -82,7 +90,8 @@ struct sd { | |||
82 | 90 | ||
83 | int brightness; | 91 | int brightness; |
84 | u16 exposure; | 92 | u16 exposure; |
85 | u8 gain; | 93 | u32 gain; |
94 | u8 contrast; | ||
86 | u8 min_clockdiv; | 95 | u8 min_clockdiv; |
87 | }; | 96 | }; |
88 | 97 | ||
@@ -98,6 +107,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
98 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
99 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 108 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 109 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
110 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 112 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 113 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
103 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | 114 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); |
@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | |||
105 | static void setbrightness(struct gspca_dev *gspca_dev); | 116 | static void setbrightness(struct gspca_dev *gspca_dev); |
106 | static void setexposure(struct gspca_dev *gspca_dev); | 117 | static void setexposure(struct gspca_dev *gspca_dev); |
107 | static void setgain(struct gspca_dev *gspca_dev); | 118 | static void setgain(struct gspca_dev *gspca_dev); |
119 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
108 | 120 | ||
109 | /* V4L2 controls supported by the driver */ | 121 | /* V4L2 controls supported by the driver */ |
110 | static struct ctrl sd_ctrls[] = { | 122 | static const struct ctrl sd_ctrls[] = { |
111 | /* Separate brightness control description for Argus QuickClix as it has | 123 | /* Separate brightness control description for Argus QuickClix as it has |
112 | different limits from the other mr97310a cameras */ | 124 | * different limits from the other mr97310a cameras, and separate gain |
125 | * control for Sakar CyberPix camera. */ | ||
113 | { | 126 | { |
114 | #define NORM_BRIGHTNESS_IDX 0 | 127 | #define NORM_BRIGHTNESS_IDX 0 |
115 | { | 128 | { |
@@ -171,7 +184,37 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .get = sd_getgain, | 184 | .get = sd_getgain, |
172 | }, | 185 | }, |
173 | { | 186 | { |
174 | #define MIN_CLOCKDIV_IDX 4 | 187 | #define SAKAR_CS_GAIN_IDX 4 |
188 | { | ||
189 | .id = V4L2_CID_GAIN, | ||
190 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
191 | .name = "Gain", | ||
192 | .minimum = MR97310A_CS_GAIN_MIN, | ||
193 | .maximum = MR97310A_CS_GAIN_MAX, | ||
194 | .step = 1, | ||
195 | .default_value = MR97310A_CS_GAIN_DEFAULT, | ||
196 | .flags = 0, | ||
197 | }, | ||
198 | .set = sd_setgain, | ||
199 | .get = sd_getgain, | ||
200 | }, | ||
201 | { | ||
202 | #define CONTRAST_IDX 5 | ||
203 | { | ||
204 | .id = V4L2_CID_CONTRAST, | ||
205 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
206 | .name = "Contrast", | ||
207 | .minimum = MR97310A_CONTRAST_MIN, | ||
208 | .maximum = MR97310A_CONTRAST_MAX, | ||
209 | .step = 1, | ||
210 | .default_value = MR97310A_CONTRAST_DEFAULT, | ||
211 | .flags = 0, | ||
212 | }, | ||
213 | .set = sd_setcontrast, | ||
214 | .get = sd_getcontrast, | ||
215 | }, | ||
216 | { | ||
217 | #define MIN_CLOCKDIV_IDX 6 | ||
175 | { | 218 | { |
176 | .id = V4L2_CID_PRIVATE_BASE, | 219 | .id = V4L2_CID_PRIVATE_BASE, |
177 | .type = V4L2_CTRL_TYPE_INTEGER, | 220 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -327,7 +370,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
327 | if (err_code < 0) | 370 | if (err_code < 0) |
328 | return err_code; | 371 | return err_code; |
329 | 372 | ||
330 | err_code = mr_write(gspca_dev, 1); | ||
331 | data[0] = 0x19; | 373 | data[0] = 0x19; |
332 | data[1] = 0x51; | 374 | data[1] = 0x51; |
333 | err_code = mr_write(gspca_dev, 2); | 375 | err_code = mr_write(gspca_dev, 2); |
@@ -437,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
437 | { | 479 | { |
438 | struct sd *sd = (struct sd *) gspca_dev; | 480 | struct sd *sd = (struct sd *) gspca_dev; |
439 | struct cam *cam; | 481 | struct cam *cam; |
482 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
440 | int err_code; | 483 | int err_code; |
441 | 484 | ||
442 | cam = &gspca_dev->cam; | 485 | cam = &gspca_dev->cam; |
@@ -460,12 +503,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
460 | if (err_code < 0) | 503 | if (err_code < 0) |
461 | return err_code; | 504 | return err_code; |
462 | 505 | ||
506 | /* Now, the query for sensor type. */ | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
463 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { | 511 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { |
464 | sd->cam_type = CAM_TYPE_CIF; | 512 | sd->cam_type = CAM_TYPE_CIF; |
465 | cam->nmodes--; | 513 | cam->nmodes--; |
466 | err_code = cam_get_response16(gspca_dev, 0x06, 1); | ||
467 | if (err_code < 0) | ||
468 | return err_code; | ||
469 | /* | 514 | /* |
470 | * All but one of the known CIF cameras share the same USB ID, | 515 | * All but one of the known CIF cameras share the same USB ID, |
471 | * but two different init routines are in use, and the control | 516 | * but two different init routines are in use, and the control |
@@ -473,12 +518,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
473 | * of the two known varieties is connected! | 518 | * of the two known varieties is connected! |
474 | * | 519 | * |
475 | * A list of known CIF cameras follows. They all report either | 520 | * A list of known CIF cameras follows. They all report either |
476 | * 0002 for type 0 or 0003 for type 1. | 521 | * 0200 for type 0 or 0300 for type 1. |
477 | * If you have another to report, please do | 522 | * If you have another to report, please do |
478 | * | 523 | * |
479 | * Name sd->sensor_type reported by | 524 | * Name sd->sensor_type reported by |
480 | * | 525 | * |
481 | * Sakar Spy-shot 0 T. Kilgore | 526 | * Sakar 56379 Spy-shot 0 T. Kilgore |
482 | * Innovage 0 T. Kilgore | 527 | * Innovage 0 T. Kilgore |
483 | * Vivitar Mini 0 H. De Goede | 528 | * Vivitar Mini 0 H. De Goede |
484 | * Vivitar Mini 0 E. Rodriguez | 529 | * Vivitar Mini 0 E. Rodriguez |
@@ -487,7 +532,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
487 | * Philips dig. keych. 1 T. Kilgore | 532 | * Philips dig. keych. 1 T. Kilgore |
488 | * Trust Spyc@m 100 1 A. Jacobs | 533 | * Trust Spyc@m 100 1 A. Jacobs |
489 | */ | 534 | */ |
490 | switch (gspca_dev->usb_buf[1]) { | 535 | switch (gspca_dev->usb_buf[0]) { |
491 | case 2: | 536 | case 2: |
492 | sd->sensor_type = 0; | 537 | sd->sensor_type = 0; |
493 | break; | 538 | break; |
@@ -504,20 +549,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
504 | } else { | 549 | } else { |
505 | sd->cam_type = CAM_TYPE_VGA; | 550 | sd->cam_type = CAM_TYPE_VGA; |
506 | 551 | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
511 | /* | 552 | /* |
512 | * Here is a table of the responses to the previous command | 553 | * Here is a table of the responses to the query for sensor |
513 | * from the known MR97310A VGA cameras. | 554 | * type, from the known MR97310A VGA cameras. Six different |
555 | * cameras of which five share the same USB ID. | ||
514 | * | 556 | * |
515 | * Name gspca_dev->usb_buf[] sd->sensor_type | 557 | * Name gspca_dev->usb_buf[] sd->sensor_type |
516 | * sd->do_lcd_stop | 558 | * sd->do_lcd_stop |
517 | * Aiptek Pencam VGA+ 0300 0 1 | 559 | * Aiptek Pencam VGA+ 0300 0 1 |
518 | * ION digital 0350 0 1 | 560 | * ION digital 0300 0 1 |
519 | * Argus DC-1620 0450 1 0 | 561 | * Argus DC-1620 0450 1 0 |
520 | * Argus QuickClix 0420 1 1 | 562 | * Argus QuickClix 0420 1 1 |
563 | * Sakar 77379 Digital 0350 0 1 | ||
564 | * Sakar 1638x CyberPix 0120 0 2 | ||
521 | * | 565 | * |
522 | * Based upon these results, we assume default settings | 566 | * Based upon these results, we assume default settings |
523 | * and then correct as necessary, as follows. | 567 | * and then correct as necessary, as follows. |
@@ -527,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
527 | sd->sensor_type = 1; | 571 | sd->sensor_type = 1; |
528 | sd->do_lcd_stop = 0; | 572 | sd->do_lcd_stop = 0; |
529 | sd->adj_colors = 0; | 573 | sd->adj_colors = 0; |
530 | if ((gspca_dev->usb_buf[0] != 0x03) && | 574 | if (gspca_dev->usb_buf[0] == 0x01) { |
575 | sd->sensor_type = 2; | ||
576 | } else if ((gspca_dev->usb_buf[0] != 0x03) && | ||
531 | (gspca_dev->usb_buf[0] != 0x04)) { | 577 | (gspca_dev->usb_buf[0] != 0x04)) { |
532 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | 578 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", |
533 | gspca_dev->usb_buf[1]); | 579 | gspca_dev->usb_buf[0]); |
534 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | 580 | PDEBUG(D_ERR, "Defaults assumed, may not work"); |
535 | PDEBUG(D_ERR, "Please report this"); | 581 | PDEBUG(D_ERR, "Please report this"); |
536 | } | 582 | } |
@@ -560,7 +606,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
560 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", | 606 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", |
561 | sd->sensor_type); | 607 | sd->sensor_type); |
562 | } | 608 | } |
563 | /* Stop streaming as we've started it to probe the sensor type. */ | 609 | /* Stop streaming as we've started it only to probe the sensor type. */ |
564 | sd_stopN(gspca_dev); | 610 | sd_stopN(gspca_dev); |
565 | 611 | ||
566 | if (force_sensor_type != -1) { | 612 | if (force_sensor_type != -1) { |
@@ -574,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
574 | /* No brightness for sensor_type 0 */ | 620 | /* No brightness for sensor_type 0 */ |
575 | if (sd->sensor_type == 0) | 621 | if (sd->sensor_type == 0) |
576 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
577 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
624 | (1 << CONTRAST_IDX) | | ||
625 | (1 << SAKAR_CS_GAIN_IDX); | ||
578 | else | 626 | else |
579 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 627 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
628 | (1 << CONTRAST_IDX) | | ||
629 | (1 << SAKAR_CS_GAIN_IDX) | | ||
580 | (1 << MIN_CLOCKDIV_IDX); | 630 | (1 << MIN_CLOCKDIV_IDX); |
581 | } else { | 631 | } else { |
582 | /* All controls need to be disabled if VGA sensor_type is 0 */ | 632 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
@@ -585,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
585 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
586 | (1 << EXPOSURE_IDX) | | 636 | (1 << EXPOSURE_IDX) | |
587 | (1 << GAIN_IDX) | | 637 | (1 << GAIN_IDX) | |
638 | (1 << CONTRAST_IDX) | | ||
639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
588 | (1 << MIN_CLOCKDIV_IDX); | 640 | (1 << MIN_CLOCKDIV_IDX); |
589 | else if (sd->do_lcd_stop) | 641 | else if (sd->sensor_type == 2) { |
642 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
643 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
644 | (1 << GAIN_IDX) | | ||
645 | (1 << MIN_CLOCKDIV_IDX); | ||
646 | gain_default = MR97310A_CS_GAIN_DEFAULT; | ||
647 | } else if (sd->do_lcd_stop) | ||
590 | /* Argus QuickClix has different brightness limits */ | 648 | /* Argus QuickClix has different brightness limits */ |
591 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | 649 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
650 | (1 << CONTRAST_IDX) | | ||
651 | (1 << SAKAR_CS_GAIN_IDX); | ||
592 | else | 652 | else |
593 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | 653 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
654 | (1 << CONTRAST_IDX) | | ||
655 | (1 << SAKAR_CS_GAIN_IDX); | ||
594 | } | 656 | } |
595 | 657 | ||
596 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
597 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
598 | sd->gain = MR97310A_GAIN_DEFAULT; | 660 | sd->gain = gain_default; |
661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
599 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | 662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; |
600 | 663 | ||
601 | return 0; | 664 | return 0; |
@@ -697,6 +760,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) | |||
697 | {0x13, 0x00, {0x01}, 1}, | 760 | {0x13, 0x00, {0x01}, 1}, |
698 | {0, 0, {0}, 0} | 761 | {0, 0, {0}, 0} |
699 | }; | 762 | }; |
763 | /* Without this command the cam won't work with USB-UHCI */ | ||
764 | gspca_dev->usb_buf[0] = 0x0a; | ||
765 | gspca_dev->usb_buf[1] = 0x00; | ||
766 | err_code = mr_write(gspca_dev, 2); | ||
767 | if (err_code < 0) | ||
768 | return err_code; | ||
700 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, | 769 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, |
701 | ARRAY_SIZE(cif_sensor1_init_data)); | 770 | ARRAY_SIZE(cif_sensor1_init_data)); |
702 | } | 771 | } |
@@ -717,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
717 | data[5] = 0x00; | 786 | data[5] = 0x00; |
718 | data[10] = 0x91; | 787 | data[10] = 0x91; |
719 | } | 788 | } |
789 | if (sd->sensor_type == 2) { | ||
790 | data[5] = 0x00; | ||
791 | data[10] = 0x18; | ||
792 | } | ||
720 | 793 | ||
721 | switch (gspca_dev->width) { | 794 | switch (gspca_dev->width) { |
722 | case 160: | 795 | case 160: |
@@ -731,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
731 | data[4] = 0x78; /* reg 3, V size/4 */ | 804 | data[4] = 0x78; /* reg 3, V size/4 */ |
732 | data[6] = 0x04; /* reg 5, H start */ | 805 | data[6] = 0x04; /* reg 5, H start */ |
733 | data[8] = 0x03; /* reg 7, V start */ | 806 | data[8] = 0x03; /* reg 7, V start */ |
807 | if (sd->sensor_type == 2) { | ||
808 | data[6] = 2; | ||
809 | data[8] = 1; | ||
810 | } | ||
734 | if (sd->do_lcd_stop) | 811 | if (sd->do_lcd_stop) |
735 | data[8] = 0x04; /* Bayer tile shifted */ | 812 | data[8] = 0x04; /* Bayer tile shifted */ |
736 | break; | 813 | break; |
@@ -753,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
753 | return err_code; | 830 | return err_code; |
754 | 831 | ||
755 | if (!sd->sensor_type) { | 832 | if (!sd->sensor_type) { |
756 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ | ||
757 | const struct sensor_w_data vga_sensor0_init_data[] = { | 833 | const struct sensor_w_data vga_sensor0_init_data[] = { |
758 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, | 834 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
759 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, | 835 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
@@ -764,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
764 | }; | 840 | }; |
765 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 841 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
766 | ARRAY_SIZE(vga_sensor0_init_data)); | 842 | ARRAY_SIZE(vga_sensor0_init_data)); |
767 | } else { /* sd->sensor_type = 1 */ | 843 | } else if (sd->sensor_type == 1) { |
768 | const struct sensor_w_data color_adj[] = { | 844 | const struct sensor_w_data color_adj[] = { |
769 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 845 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
770 | /* adjusted blue, green, red gain correct | 846 | /* adjusted blue, green, red gain correct |
@@ -802,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
802 | 878 | ||
803 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 879 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
804 | ARRAY_SIZE(vga_sensor1_init_data)); | 880 | ARRAY_SIZE(vga_sensor1_init_data)); |
881 | } else { /* sensor type == 2 */ | ||
882 | const struct sensor_w_data vga_sensor2_init_data[] = { | ||
883 | |||
884 | {0x01, 0x00, {0x48}, 1}, | ||
885 | {0x02, 0x00, {0x22}, 1}, | ||
886 | /* Reg 3 msb and 4 is lsb of the exposure setting*/ | ||
887 | {0x05, 0x00, {0x10}, 1}, | ||
888 | {0x06, 0x00, {0x00}, 1}, | ||
889 | {0x07, 0x00, {0x00}, 1}, | ||
890 | {0x08, 0x00, {0x00}, 1}, | ||
891 | {0x09, 0x00, {0x00}, 1}, | ||
892 | /* The following are used in the gain control | ||
893 | * which is BTW completely borked in the OEM driver | ||
894 | * The values for each color go from 0 to 0x7ff | ||
895 | *{0x0a, 0x00, {0x01}, 1}, green1 gain msb | ||
896 | *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb | ||
897 | *{0x0c, 0x00, {0x01}, 1}, red gain msb | ||
898 | *{0x0d, 0x00, {0x10}, 1}, red gain lsb | ||
899 | *{0x0e, 0x00, {0x01}, 1}, blue gain msb | ||
900 | *{0x0f, 0x00, {0x10}, 1}, blue gain lsb | ||
901 | *{0x10, 0x00, {0x01}, 1}, green2 gain msb | ||
902 | *{0x11, 0x00, {0x10}, 1}, green2 gain lsb | ||
903 | */ | ||
904 | {0x12, 0x00, {0x00}, 1}, | ||
905 | {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ | ||
906 | {0x14, 0x00, {0x00}, 1}, | ||
907 | {0x15, 0x00, {0x06}, 1}, | ||
908 | {0x16, 0x00, {0x01}, 1}, | ||
909 | {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ | ||
910 | {0x18, 0x00, {0x02}, 1}, | ||
911 | {0x19, 0x00, {0x82}, 1}, /* don't mess with */ | ||
912 | {0x1a, 0x00, {0x00}, 1}, | ||
913 | {0x1b, 0x00, {0x20}, 1}, | ||
914 | /* {0x1c, 0x00, {0x17}, 1}, contrast control */ | ||
915 | {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ | ||
916 | {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ | ||
917 | {0x1f, 0x00, {0x0c}, 1}, | ||
918 | {0x20, 0x00, {0x00}, 1}, | ||
919 | {0, 0, {0}, 0} | ||
920 | }; | ||
921 | err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data, | ||
922 | ARRAY_SIZE(vga_sensor2_init_data)); | ||
805 | } | 923 | } |
806 | return err_code; | 924 | return err_code; |
807 | } | 925 | } |
@@ -834,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
834 | return err_code; | 952 | return err_code; |
835 | 953 | ||
836 | setbrightness(gspca_dev); | 954 | setbrightness(gspca_dev); |
955 | setcontrast(gspca_dev); | ||
837 | setexposure(gspca_dev); | 956 | setexposure(gspca_dev); |
838 | setgain(gspca_dev); | 957 | setgain(gspca_dev); |
839 | 958 | ||
@@ -893,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
893 | static void setexposure(struct gspca_dev *gspca_dev) | 1012 | static void setexposure(struct gspca_dev *gspca_dev) |
894 | { | 1013 | { |
895 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
896 | int exposure; | 1015 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
897 | u8 buf[2]; | 1016 | u8 buf[2]; |
898 | 1017 | ||
899 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 1018 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
@@ -905,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
905 | exposure = (sd->exposure * 9267) / 10000 + 300; | 1024 | exposure = (sd->exposure * 9267) / 10000 + 300; |
906 | sensor_write1(gspca_dev, 3, exposure >> 4); | 1025 | sensor_write1(gspca_dev, 3, exposure >> 4); |
907 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | 1026 | sensor_write1(gspca_dev, 4, exposure & 0x0f); |
1027 | } else if (sd->sensor_type == 2) { | ||
1028 | exposure = sd->exposure; | ||
1029 | exposure >>= 3; | ||
1030 | sensor_write1(gspca_dev, 3, exposure >> 8); | ||
1031 | sensor_write1(gspca_dev, 4, exposure & 0xff); | ||
908 | } else { | 1032 | } else { |
909 | /* We have both a clock divider and an exposure register. | 1033 | /* We have both a clock divider and an exposure register. |
910 | We first calculate the clock divider, as that determines | 1034 | We first calculate the clock divider, as that determines |
@@ -943,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
943 | static void setgain(struct gspca_dev *gspca_dev) | 1067 | static void setgain(struct gspca_dev *gspca_dev) |
944 | { | 1068 | { |
945 | struct sd *sd = (struct sd *) gspca_dev; | 1069 | struct sd *sd = (struct sd *) gspca_dev; |
1070 | u8 gainreg; | ||
946 | 1071 | ||
947 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) | 1072 | if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && |
1073 | (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) | ||
948 | return; | 1074 | return; |
949 | 1075 | ||
950 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 1076 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
951 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 1077 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
952 | } else { | 1078 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
1079 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { | ||
1080 | sensor_write1(gspca_dev, gainreg, sd->gain >> 8); | ||
1081 | sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); | ||
1082 | } | ||
1083 | else | ||
953 | sensor_write1(gspca_dev, 0x10, sd->gain); | 1084 | sensor_write1(gspca_dev, 0x10, sd->gain); |
954 | } | ||
955 | } | 1085 | } |
956 | 1086 | ||
1087 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
1088 | { | ||
1089 | struct sd *sd = (struct sd *) gspca_dev; | ||
1090 | |||
1091 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
1092 | return; | ||
1093 | |||
1094 | sensor_write1(gspca_dev, 0x1c, sd->contrast); | ||
1095 | } | ||
1096 | |||
1097 | |||
957 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1098 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
958 | { | 1099 | { |
959 | struct sd *sd = (struct sd *) gspca_dev; | 1100 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1008,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
1008 | return 0; | 1149 | return 0; |
1009 | } | 1150 | } |
1010 | 1151 | ||
1152 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1153 | { | ||
1154 | struct sd *sd = (struct sd *) gspca_dev; | ||
1155 | |||
1156 | sd->contrast = val; | ||
1157 | if (gspca_dev->streaming) | ||
1158 | setcontrast(gspca_dev); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1164 | { | ||
1165 | struct sd *sd = (struct sd *) gspca_dev; | ||
1166 | |||
1167 | *val = sd->contrast; | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1011 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | 1171 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) |
1012 | { | 1172 | { |
1013 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |