diff options
| author | Theodore Kilgore <kilgota@banach.math.auburn.edu> | 2010-02-09 16:05:25 -0500 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:11:09 -0500 |
| commit | 9d3103d061224e939272d05d54192038f66ffd54 (patch) | |
| tree | e8e62612089e374cf3f3b4e7d94cddb573e09336 /drivers/media | |
| parent | 10bb7530108cc11fedd0d615467a54f341079778 (diff) | |
V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix
This camera has a sensor type we did not support sofar, this patch adds
support for the new sensor type found in the Sakar 1638x CyberPix.
Signed-off-by: Theodore Kilgore <kilgota@banach.math.auburn.edu>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
| -rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 197 |
1 files changed, 177 insertions, 20 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 959ea2a530a..33744e724ea 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 const 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 const 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, |
| @@ -436,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 436 | { | 479 | { |
| 437 | struct sd *sd = (struct sd *) gspca_dev; | 480 | struct sd *sd = (struct sd *) gspca_dev; |
| 438 | struct cam *cam; | 481 | struct cam *cam; |
| 482 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
| 439 | int err_code; | 483 | int err_code; |
| 440 | 484 | ||
| 441 | cam = &gspca_dev->cam; | 485 | cam = &gspca_dev->cam; |
| @@ -479,7 +523,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 479 | * | 523 | * |
| 480 | * Name sd->sensor_type reported by | 524 | * Name sd->sensor_type reported by |
| 481 | * | 525 | * |
| 482 | * Sakar Spy-shot 0 T. Kilgore | 526 | * Sakar 56379 Spy-shot 0 T. Kilgore |
| 483 | * Innovage 0 T. Kilgore | 527 | * Innovage 0 T. Kilgore |
| 484 | * Vivitar Mini 0 H. De Goede | 528 | * Vivitar Mini 0 H. De Goede |
| 485 | * Vivitar Mini 0 E. Rodriguez | 529 | * Vivitar Mini 0 E. Rodriguez |
| @@ -507,14 +551,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 507 | 551 | ||
| 508 | /* | 552 | /* |
| 509 | * Here is a table of the responses to the query for sensor | 553 | * Here is a table of the responses to the query for sensor |
| 510 | * type, 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. | ||
| 511 | * | 556 | * |
| 512 | * Name gspca_dev->usb_buf[] sd->sensor_type | 557 | * Name gspca_dev->usb_buf[] sd->sensor_type |
| 513 | * sd->do_lcd_stop | 558 | * sd->do_lcd_stop |
| 514 | * Aiptek Pencam VGA+ 0300 0 1 | 559 | * Aiptek Pencam VGA+ 0300 0 1 |
| 515 | * ION digital 0350 0 1 | 560 | * ION digital 0300 0 1 |
| 516 | * Argus DC-1620 0450 1 0 | 561 | * Argus DC-1620 0450 1 0 |
| 517 | * 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 | ||
| 518 | * | 565 | * |
| 519 | * Based upon these results, we assume default settings | 566 | * Based upon these results, we assume default settings |
| 520 | * and then correct as necessary, as follows. | 567 | * and then correct as necessary, as follows. |
| @@ -524,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 524 | sd->sensor_type = 1; | 571 | sd->sensor_type = 1; |
| 525 | sd->do_lcd_stop = 0; | 572 | sd->do_lcd_stop = 0; |
| 526 | sd->adj_colors = 0; | 573 | sd->adj_colors = 0; |
| 527 | 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) && | ||
| 528 | (gspca_dev->usb_buf[0] != 0x04)) { | 577 | (gspca_dev->usb_buf[0] != 0x04)) { |
| 529 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | 578 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", |
| 530 | gspca_dev->usb_buf[1]); | 579 | gspca_dev->usb_buf[0]); |
| 531 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | 580 | PDEBUG(D_ERR, "Defaults assumed, may not work"); |
| 532 | PDEBUG(D_ERR, "Please report this"); | 581 | PDEBUG(D_ERR, "Please report this"); |
| 533 | } | 582 | } |
| @@ -571,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 571 | /* No brightness for sensor_type 0 */ | 620 | /* No brightness for sensor_type 0 */ |
| 572 | if (sd->sensor_type == 0) | 621 | if (sd->sensor_type == 0) |
| 573 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
| 574 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
| 624 | (1 << CONTRAST_IDX) | | ||
| 625 | (1 << SAKAR_CS_GAIN_IDX); | ||
| 575 | else | 626 | else |
| 576 | 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) | | ||
| 577 | (1 << MIN_CLOCKDIV_IDX); | 630 | (1 << MIN_CLOCKDIV_IDX); |
| 578 | } else { | 631 | } else { |
| 579 | /* 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 */ |
| @@ -582,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 582 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
| 583 | (1 << EXPOSURE_IDX) | | 636 | (1 << EXPOSURE_IDX) | |
| 584 | (1 << GAIN_IDX) | | 637 | (1 << GAIN_IDX) | |
| 638 | (1 << CONTRAST_IDX) | | ||
| 639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
| 585 | (1 << MIN_CLOCKDIV_IDX); | 640 | (1 << MIN_CLOCKDIV_IDX); |
| 586 | 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) | ||
| 587 | /* Argus QuickClix has different brightness limits */ | 648 | /* Argus QuickClix has different brightness limits */ |
| 588 | 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); | ||
| 589 | else | 652 | else |
| 590 | 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); | ||
| 591 | } | 656 | } |
| 592 | 657 | ||
| 593 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
| 594 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
| 595 | sd->gain = MR97310A_GAIN_DEFAULT; | 660 | sd->gain = gain_default; |
| 661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
| 596 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | 662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; |
| 597 | 663 | ||
| 598 | return 0; | 664 | return 0; |
| @@ -720,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
| 720 | data[5] = 0x00; | 786 | data[5] = 0x00; |
| 721 | data[10] = 0x91; | 787 | data[10] = 0x91; |
| 722 | } | 788 | } |
| 789 | if (sd->sensor_type == 2) { | ||
| 790 | data[5] = 0x00; | ||
| 791 | data[10] = 0x18; | ||
| 792 | } | ||
| 723 | 793 | ||
| 724 | switch (gspca_dev->width) { | 794 | switch (gspca_dev->width) { |
| 725 | case 160: | 795 | case 160: |
| @@ -734,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
| 734 | data[4] = 0x78; /* reg 3, V size/4 */ | 804 | data[4] = 0x78; /* reg 3, V size/4 */ |
| 735 | data[6] = 0x04; /* reg 5, H start */ | 805 | data[6] = 0x04; /* reg 5, H start */ |
| 736 | 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 | } | ||
| 737 | if (sd->do_lcd_stop) | 811 | if (sd->do_lcd_stop) |
| 738 | data[8] = 0x04; /* Bayer tile shifted */ | 812 | data[8] = 0x04; /* Bayer tile shifted */ |
| 739 | break; | 813 | break; |
| @@ -756,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
| 756 | return err_code; | 830 | return err_code; |
| 757 | 831 | ||
| 758 | if (!sd->sensor_type) { | 832 | if (!sd->sensor_type) { |
| 759 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ | ||
| 760 | const struct sensor_w_data vga_sensor0_init_data[] = { | 833 | const struct sensor_w_data vga_sensor0_init_data[] = { |
| 761 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, | 834 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
| 762 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, | 835 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
| @@ -767,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
| 767 | }; | 840 | }; |
| 768 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 841 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
| 769 | ARRAY_SIZE(vga_sensor0_init_data)); | 842 | ARRAY_SIZE(vga_sensor0_init_data)); |
| 770 | } else { /* sd->sensor_type = 1 */ | 843 | } else if (sd->sensor_type == 1) { |
| 771 | const struct sensor_w_data color_adj[] = { | 844 | const struct sensor_w_data color_adj[] = { |
| 772 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 845 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
| 773 | /* adjusted blue, green, red gain correct | 846 | /* adjusted blue, green, red gain correct |
| @@ -805,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
| 805 | 878 | ||
| 806 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 879 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
| 807 | 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)); | ||
| 808 | } | 923 | } |
| 809 | return err_code; | 924 | return err_code; |
| 810 | } | 925 | } |
| @@ -837,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 837 | return err_code; | 952 | return err_code; |
| 838 | 953 | ||
| 839 | setbrightness(gspca_dev); | 954 | setbrightness(gspca_dev); |
| 955 | setcontrast(gspca_dev); | ||
| 840 | setexposure(gspca_dev); | 956 | setexposure(gspca_dev); |
| 841 | setgain(gspca_dev); | 957 | setgain(gspca_dev); |
| 842 | 958 | ||
| @@ -896,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
| 896 | static void setexposure(struct gspca_dev *gspca_dev) | 1012 | static void setexposure(struct gspca_dev *gspca_dev) |
| 897 | { | 1013 | { |
| 898 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
| 899 | int exposure; | 1015 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
| 900 | u8 buf[2]; | 1016 | u8 buf[2]; |
| 901 | 1017 | ||
| 902 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 1018 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
| @@ -908,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
| 908 | exposure = (sd->exposure * 9267) / 10000 + 300; | 1024 | exposure = (sd->exposure * 9267) / 10000 + 300; |
| 909 | sensor_write1(gspca_dev, 3, exposure >> 4); | 1025 | sensor_write1(gspca_dev, 3, exposure >> 4); |
| 910 | 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); | ||
| 911 | } else { | 1032 | } else { |
| 912 | /* We have both a clock divider and an exposure register. | 1033 | /* We have both a clock divider and an exposure register. |
| 913 | We first calculate the clock divider, as that determines | 1034 | We first calculate the clock divider, as that determines |
| @@ -946,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
| 946 | static void setgain(struct gspca_dev *gspca_dev) | 1067 | static void setgain(struct gspca_dev *gspca_dev) |
| 947 | { | 1068 | { |
| 948 | struct sd *sd = (struct sd *) gspca_dev; | 1069 | struct sd *sd = (struct sd *) gspca_dev; |
| 1070 | u8 gainreg; | ||
| 949 | 1071 | ||
| 950 | 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))) | ||
| 951 | return; | 1074 | return; |
| 952 | 1075 | ||
| 953 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 1076 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
| 954 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 1077 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
| 955 | } 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 | ||
| 956 | sensor_write1(gspca_dev, 0x10, sd->gain); | 1084 | sensor_write1(gspca_dev, 0x10, sd->gain); |
| 957 | } | ||
| 958 | } | 1085 | } |
| 959 | 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 | |||
| 960 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1098 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
| 961 | { | 1099 | { |
| 962 | struct sd *sd = (struct sd *) gspca_dev; | 1100 | struct sd *sd = (struct sd *) gspca_dev; |
| @@ -1011,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
| 1011 | return 0; | 1149 | return 0; |
| 1012 | } | 1150 | } |
| 1013 | 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 | |||
| 1014 | 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) |
| 1015 | { | 1172 | { |
| 1016 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |
