diff options
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r-- | drivers/media/video/gspca/spca561.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index d2f689e366af..1c29c279a982 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -38,9 +38,9 @@ struct sd { | |||
38 | #define CONTRAST_MAX 0x3fff | 38 | #define CONTRAST_MAX 0x3fff |
39 | 39 | ||
40 | __u16 exposure; /* rev12a only */ | 40 | __u16 exposure; /* rev12a only */ |
41 | #define EXPOSURE_MIN 0 | 41 | #define EXPOSURE_MIN 1 |
42 | #define EXPOSURE_DEF 200 | 42 | #define EXPOSURE_DEF 200 |
43 | #define EXPOSURE_MAX 762 | 43 | #define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ |
44 | 44 | ||
45 | __u8 brightness; /* rev72a only */ | 45 | __u8 brightness; /* rev72a only */ |
46 | #define BRIGHTNESS_MIN 0 | 46 | #define BRIGHTNESS_MIN 0 |
@@ -648,9 +648,31 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
648 | { | 648 | { |
649 | struct sd *sd = (struct sd *) gspca_dev; | 649 | struct sd *sd = (struct sd *) gspca_dev; |
650 | int expo; | 650 | int expo; |
651 | int clock_divider; | ||
651 | __u8 data[2]; | 652 | __u8 data[2]; |
652 | 653 | ||
653 | expo = sd->exposure + 0x20a8; /* from test */ | 654 | /* Register 0x8309 controls exposure for the spca561, |
655 | the basic exposure setting goes from 1-2047, where 1 is completely | ||
656 | dark and 2047 is very bright. It not only influences exposure but | ||
657 | also the framerate (to allow for longer exposure) from 1 - 300 it | ||
658 | only raises the exposure time then from 300 - 600 it halves the | ||
659 | framerate to be able to further raise the exposure time and for every | ||
660 | 300 more it halves the framerate again. This allows for a maximum | ||
661 | exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps). | ||
662 | Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12 | ||
663 | configure a divider for the base framerate which us used at the | ||
664 | exposure setting of 1-300. These bits configure the base framerate | ||
665 | according to the following formula: fps = 60 / (value + 2) */ | ||
666 | if (sd->exposure < 2048) { | ||
667 | expo = sd->exposure; | ||
668 | clock_divider = 0; | ||
669 | } else { | ||
670 | /* Add 900 to make the 0 setting of the second part of the | ||
671 | exposure equal to the 2047 setting of the first part. */ | ||
672 | expo = (sd->exposure - 2048) + 900; | ||
673 | clock_divider = 3; | ||
674 | } | ||
675 | expo |= clock_divider << 11; | ||
654 | data[0] = expo; | 676 | data[0] = expo; |
655 | data[1] = expo >> 8; | 677 | data[1] = expo >> 8; |
656 | reg_w_buf(gspca_dev, 0x8309, data, 2); | 678 | reg_w_buf(gspca_dev, 0x8309, data, 2); |
@@ -680,23 +702,11 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
680 | static void sd_start_12a(struct gspca_dev *gspca_dev) | 702 | static void sd_start_12a(struct gspca_dev *gspca_dev) |
681 | { | 703 | { |
682 | struct usb_device *dev = gspca_dev->dev; | 704 | struct usb_device *dev = gspca_dev->dev; |
683 | int Clck; | 705 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ |
684 | __u8 Reg8307[] = { 0xaa, 0x00 }; | 706 | __u8 Reg8307[] = { 0xaa, 0x00 }; |
685 | int mode; | 707 | int mode; |
686 | 708 | ||
687 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 709 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; |
688 | switch (mode) { | ||
689 | case 0: | ||
690 | case 1: | ||
691 | Clck = 0x8a; | ||
692 | break; | ||
693 | case 2: | ||
694 | Clck = 0x85; | ||
695 | break; | ||
696 | default: | ||
697 | Clck = 0x83; | ||
698 | break; | ||
699 | } | ||
700 | if (mode <= 1) { | 710 | if (mode <= 1) { |
701 | /* Use compression on 320x240 and above */ | 711 | /* Use compression on 320x240 and above */ |
702 | reg_w_val(dev, 0x8500, 0x10 | mode); | 712 | reg_w_val(dev, 0x8500, 0x10 | mode); |
@@ -714,6 +724,7 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) | |||
714 | setcontrast(gspca_dev); | 724 | setcontrast(gspca_dev); |
715 | setwhite(gspca_dev); | 725 | setwhite(gspca_dev); |
716 | setautogain(gspca_dev); | 726 | setautogain(gspca_dev); |
727 | setexposure(gspca_dev); | ||
717 | } | 728 | } |
718 | static void sd_start_72a(struct gspca_dev *gspca_dev) | 729 | static void sd_start_72a(struct gspca_dev *gspca_dev) |
719 | { | 730 | { |
@@ -849,6 +860,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
849 | __u8 *data, /* isoc packet */ | 860 | __u8 *data, /* isoc packet */ |
850 | int len) /* iso packet length */ | 861 | int len) /* iso packet length */ |
851 | { | 862 | { |
863 | struct sd *sd = (struct sd *) gspca_dev; | ||
864 | |||
852 | switch (data[0]) { | 865 | switch (data[0]) { |
853 | case 0: /* start of frame */ | 866 | case 0: /* start of frame */ |
854 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 867 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, |
@@ -861,9 +874,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
861 | frame, data, len); | 874 | frame, data, len); |
862 | } else { | 875 | } else { |
863 | /* raw bayer (with a header, which we skip) */ | 876 | /* raw bayer (with a header, which we skip) */ |
864 | /*fixme: is this specific to the rev012a? */ | 877 | if (sd->chip_revision == Rev012A) { |
865 | data += 16; | 878 | data += 20; |
866 | len -= 16; | 879 | len -= 20; |
880 | } else { | ||
881 | data += 16; | ||
882 | len -= 16; | ||
883 | } | ||
867 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 884 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
868 | frame, data, len); | 885 | frame, data, len); |
869 | } | 886 | } |