diff options
Diffstat (limited to 'drivers/media/video/gspca/pac7302.c')
-rw-r--r-- | drivers/media/video/gspca/pac7302.c | 185 |
1 files changed, 109 insertions, 76 deletions
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 30662fccb0cf..a0369a58c4bb 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -23,43 +23,58 @@ | |||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* Some documentation about various registers as determined by trial and error. | 26 | /* |
27 | 27 | * Some documentation about various registers as determined by trial and error. | |
28 | Register page 1: | 28 | * |
29 | 29 | * Register page 1: | |
30 | Address Description | 30 | * |
31 | 0x78 Global control, bit 6 controls the LED (inverted) | 31 | * Address Description |
32 | 32 | * 0x78 Global control, bit 6 controls the LED (inverted) | |
33 | Register page 3: | 33 | * 0x80 Compression balance, 2 interesting settings: |
34 | 34 | * 0x0f Default | |
35 | Address Description | 35 | * 0x50 Values >= this switch the camera to a lower compression, |
36 | 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on | 36 | * using the same table for both luminance and chrominance. |
37 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? | 37 | * This gives a sharper picture. Only usable when running |
38 | 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps | 38 | * at < 15 fps! Note currently the driver does not use this |
39 | 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, | 39 | * as the quality gain is small and the generated JPG-s are |
40 | 63 -> ~27 fps, the 2 msb's must always be 1 !! | 40 | * only understood by v4l-utils >= 0.8.9 |
41 | 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: | 41 | * |
42 | 1 -> ~30 fps, 2 -> ~20 fps | 42 | * Register page 3: |
43 | 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time | 43 | * |
44 | 0x0f Exposure bit 8, 0-448, 448 = no exposure at all | 44 | * Address Description |
45 | 0x10 Master gain 0-31 | 45 | * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on |
46 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused | 46 | * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? |
47 | 47 | * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps | |
48 | The registers are accessed in the following functions: | 48 | * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, |
49 | 49 | * 63 -> ~27 fps, the 2 msb's must always be 1 !! | |
50 | Page | Register | Function | 50 | * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: |
51 | -----+------------+--------------------------------------------------- | 51 | * 1 -> ~30 fps, 2 -> ~20 fps |
52 | 0 | 0x0f..0x20 | setcolors() | 52 | * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time |
53 | 0 | 0xa2..0xab | setbrightcont() | 53 | * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all |
54 | 0 | 0xc5 | setredbalance() | 54 | * 0x10 Gain 0-31 |
55 | 0 | 0xc6 | setwhitebalance() | 55 | * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an |
56 | 0 | 0xc7 | setbluebalance() | 56 | * amplification value of 1 rather then 0 at its lowest setting |
57 | 0 | 0xdc | setbrightcont(), setcolors() | 57 | * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused |
58 | 3 | 0x02 | setexposure() | 58 | * 0x80 Another framerate control, best left at 1, moving it from 1 to |
59 | 3 | 0x10 | setgain() | 59 | * 2 causes the framerate to become 3/4th of what it was, and |
60 | 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() | 60 | * also seems to cause pixel averaging, resulting in an effective |
61 | 3 | 0x21 | sethvflip() | 61 | * resolution of 320x240 and thus a much blockier image |
62 | */ | 62 | * |
63 | * The registers are accessed in the following functions: | ||
64 | * | ||
65 | * Page | Register | Function | ||
66 | * -----+------------+--------------------------------------------------- | ||
67 | * 0 | 0x0f..0x20 | setcolors() | ||
68 | * 0 | 0xa2..0xab | setbrightcont() | ||
69 | * 0 | 0xc5 | setredbalance() | ||
70 | * 0 | 0xc6 | setwhitebalance() | ||
71 | * 0 | 0xc7 | setbluebalance() | ||
72 | * 0 | 0xdc | setbrightcont(), setcolors() | ||
73 | * 3 | 0x02 | setexposure() | ||
74 | * 3 | 0x10, 0x12 | setgain() | ||
75 | * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() | ||
76 | * 3 | 0x21 | sethvflip() | ||
77 | */ | ||
63 | 78 | ||
64 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 79 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
65 | 80 | ||
@@ -89,7 +104,6 @@ enum e_ctrl { | |||
89 | NCTRLS /* number of controls */ | 104 | NCTRLS /* number of controls */ |
90 | }; | 105 | }; |
91 | 106 | ||
92 | /* specific webcam descriptor for pac7302 */ | ||
93 | struct sd { | 107 | struct sd { |
94 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 108 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
95 | 109 | ||
@@ -198,10 +212,10 @@ static const struct ctrl sd_ctrls[] = { | |||
198 | .type = V4L2_CTRL_TYPE_INTEGER, | 212 | .type = V4L2_CTRL_TYPE_INTEGER, |
199 | .name = "Gain", | 213 | .name = "Gain", |
200 | .minimum = 0, | 214 | .minimum = 0, |
201 | .maximum = 255, | 215 | .maximum = 62, |
202 | .step = 1, | 216 | .step = 1, |
203 | #define GAIN_DEF 127 | 217 | #define GAIN_DEF 15 |
204 | #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ | 218 | #define GAIN_KNEE 46 |
205 | .default_value = GAIN_DEF, | 219 | .default_value = GAIN_DEF, |
206 | }, | 220 | }, |
207 | .set_control = setgain | 221 | .set_control = setgain |
@@ -270,7 +284,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
270 | #define LOAD_PAGE3 255 | 284 | #define LOAD_PAGE3 255 |
271 | #define END_OF_SEQUENCE 0 | 285 | #define END_OF_SEQUENCE 0 |
272 | 286 | ||
273 | /* pac 7302 */ | ||
274 | static const u8 init_7302[] = { | 287 | static const u8 init_7302[] = { |
275 | /* index,value */ | 288 | /* index,value */ |
276 | 0xff, 0x01, /* page 1 */ | 289 | 0xff, 0x01, /* page 1 */ |
@@ -509,7 +522,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
509 | return 0; | 522 | return 0; |
510 | } | 523 | } |
511 | 524 | ||
512 | /* This function is used by pac7302 only */ | ||
513 | static void setbrightcont(struct gspca_dev *gspca_dev) | 525 | static void setbrightcont(struct gspca_dev *gspca_dev) |
514 | { | 526 | { |
515 | struct sd *sd = (struct sd *) gspca_dev; | 527 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -536,7 +548,6 @@ static void setbrightcont(struct gspca_dev *gspca_dev) | |||
536 | reg_w(gspca_dev, 0xdc, 0x01); | 548 | reg_w(gspca_dev, 0xdc, 0x01); |
537 | } | 549 | } |
538 | 550 | ||
539 | /* This function is used by pac7302 only */ | ||
540 | static void setcolors(struct gspca_dev *gspca_dev) | 551 | static void setcolors(struct gspca_dev *gspca_dev) |
541 | { | 552 | { |
542 | struct sd *sd = (struct sd *) gspca_dev; | 553 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -590,9 +601,19 @@ static void setbluebalance(struct gspca_dev *gspca_dev) | |||
590 | static void setgain(struct gspca_dev *gspca_dev) | 601 | static void setgain(struct gspca_dev *gspca_dev) |
591 | { | 602 | { |
592 | struct sd *sd = (struct sd *) gspca_dev; | 603 | struct sd *sd = (struct sd *) gspca_dev; |
604 | u8 reg10, reg12; | ||
605 | |||
606 | if (sd->ctrls[GAIN].val < 32) { | ||
607 | reg10 = sd->ctrls[GAIN].val; | ||
608 | reg12 = 0; | ||
609 | } else { | ||
610 | reg10 = 31; | ||
611 | reg12 = sd->ctrls[GAIN].val - 31; | ||
612 | } | ||
593 | 613 | ||
594 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 614 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
595 | reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3); | 615 | reg_w(gspca_dev, 0x10, reg10); |
616 | reg_w(gspca_dev, 0x12, reg12); | ||
596 | 617 | ||
597 | /* load registers to sensor (Bit 0, auto clear) */ | 618 | /* load registers to sensor (Bit 0, auto clear) */ |
598 | reg_w(gspca_dev, 0x11, 0x01); | 619 | reg_w(gspca_dev, 0x11, 0x01); |
@@ -604,28 +625,36 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
604 | u8 clockdiv; | 625 | u8 clockdiv; |
605 | u16 exposure; | 626 | u16 exposure; |
606 | 627 | ||
607 | /* register 2 of frame 3 contains the clock divider configuring the | 628 | /* |
608 | no fps according to the formula: 90 / reg. sd->exposure is the | 629 | * Register 2 of frame 3 contains the clock divider configuring the |
609 | desired exposure time in 0.5 ms. */ | 630 | * no fps according to the formula: 90 / reg. sd->exposure is the |
631 | * desired exposure time in 0.5 ms. | ||
632 | */ | ||
610 | clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; | 633 | clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; |
611 | 634 | ||
612 | /* Note clockdiv = 3 also works, but when running at 30 fps, depending | 635 | /* |
613 | on the scene being recorded, the camera switches to another | 636 | * Note clockdiv = 3 also works, but when running at 30 fps, depending |
614 | quantization table for certain JPEG blocks, and we don't know how | 637 | * on the scene being recorded, the camera switches to another |
615 | to decompress these blocks. So we cap the framerate at 15 fps */ | 638 | * quantization table for certain JPEG blocks, and we don't know how |
639 | * to decompress these blocks. So we cap the framerate at 15 fps. | ||
640 | */ | ||
616 | if (clockdiv < 6) | 641 | if (clockdiv < 6) |
617 | clockdiv = 6; | 642 | clockdiv = 6; |
618 | else if (clockdiv > 63) | 643 | else if (clockdiv > 63) |
619 | clockdiv = 63; | 644 | clockdiv = 63; |
620 | 645 | ||
621 | /* reg2 MUST be a multiple of 3, except when between 6 and 12? | 646 | /* |
622 | Always round up, otherwise we cannot get the desired frametime | 647 | * Register 2 MUST be a multiple of 3, except when between 6 and 12? |
623 | using the partial frame time exposure control */ | 648 | * Always round up, otherwise we cannot get the desired frametime |
649 | * using the partial frame time exposure control. | ||
650 | */ | ||
624 | if (clockdiv < 6 || clockdiv > 12) | 651 | if (clockdiv < 6 || clockdiv > 12) |
625 | clockdiv = ((clockdiv + 2) / 3) * 3; | 652 | clockdiv = ((clockdiv + 2) / 3) * 3; |
626 | 653 | ||
627 | /* frame exposure time in ms = 1000 * clockdiv / 90 -> | 654 | /* |
628 | exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ | 655 | * frame exposure time in ms = 1000 * clockdiv / 90 -> |
656 | * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) | ||
657 | */ | ||
629 | exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); | 658 | exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); |
630 | /* 0 = use full frametime, 448 = no exposure, reverse it */ | 659 | /* 0 = use full frametime, 448 = no exposure, reverse it */ |
631 | exposure = 448 - exposure; | 660 | exposure = 448 - exposure; |
@@ -643,10 +672,12 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
643 | { | 672 | { |
644 | struct sd *sd = (struct sd *) gspca_dev; | 673 | struct sd *sd = (struct sd *) gspca_dev; |
645 | 674 | ||
646 | /* when switching to autogain set defaults to make sure | 675 | /* |
647 | we are on a valid point of the autogain gain / | 676 | * When switching to autogain set defaults to make sure |
648 | exposure knee graph, and give this change time to | 677 | * we are on a valid point of the autogain gain / |
649 | take effect before doing autogain. */ | 678 | * exposure knee graph, and give this change time to |
679 | * take effect before doing autogain. | ||
680 | */ | ||
650 | if (sd->ctrls[AUTOGAIN].val) { | 681 | if (sd->ctrls[AUTOGAIN].val) { |
651 | sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; | 682 | sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; |
652 | sd->ctrls[GAIN].val = GAIN_DEF; | 683 | sd->ctrls[GAIN].val = GAIN_DEF; |
@@ -700,8 +731,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
700 | setautogain(gspca_dev); | 731 | setautogain(gspca_dev); |
701 | sethvflip(gspca_dev); | 732 | sethvflip(gspca_dev); |
702 | 733 | ||
703 | /* only resolution 640x480 is supported for pac7302 */ | ||
704 | |||
705 | sd->sof_read = 0; | 734 | sd->sof_read = 0; |
706 | atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); | 735 | atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); |
707 | 736 | ||
@@ -729,9 +758,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
729 | reg_w(gspca_dev, 0x78, 0x40); | 758 | reg_w(gspca_dev, 0x78, 0x40); |
730 | } | 759 | } |
731 | 760 | ||
732 | /* !! coarse_grained_expo_autogain is not used !! */ | 761 | #define WANT_REGULAR_AUTOGAIN |
733 | #define exp_too_low_cnt flags | ||
734 | #define exp_too_high_cnt sof_read | ||
735 | #include "autogain_functions.h" | 762 | #include "autogain_functions.h" |
736 | 763 | ||
737 | static void do_autogain(struct gspca_dev *gspca_dev) | 764 | static void do_autogain(struct gspca_dev *gspca_dev) |
@@ -792,10 +819,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
792 | if (sof) { | 819 | if (sof) { |
793 | int n, lum_offset, footer_length; | 820 | int n, lum_offset, footer_length; |
794 | 821 | ||
795 | /* 6 bytes after the FF D9 EOF marker a number of lumination | 822 | /* |
796 | bytes are send corresponding to different parts of the | 823 | * 6 bytes after the FF D9 EOF marker a number of lumination |
797 | image, the 14th and 15th byte after the EOF seem to | 824 | * bytes are send corresponding to different parts of the |
798 | correspond to the center of the image */ | 825 | * image, the 14th and 15th byte after the EOF seem to |
826 | * correspond to the center of the image. | ||
827 | */ | ||
799 | lum_offset = 61 + sizeof pac_sof_marker; | 828 | lum_offset = 61 + sizeof pac_sof_marker; |
800 | footer_length = 74; | 829 | footer_length = 74; |
801 | 830 | ||
@@ -839,9 +868,10 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
839 | u8 index; | 868 | u8 index; |
840 | u8 value; | 869 | u8 value; |
841 | 870 | ||
842 | /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit | 871 | /* |
843 | long on the USB bus) | 872 | * reg->reg: bit0..15: reserved for register index (wIndex is 16bit |
844 | */ | 873 | * long on the USB bus) |
874 | */ | ||
845 | if (reg->match.type == V4L2_CHIP_MATCH_HOST && | 875 | if (reg->match.type == V4L2_CHIP_MATCH_HOST && |
846 | reg->match.addr == 0 && | 876 | reg->match.addr == 0 && |
847 | (reg->reg < 0x000000ff) && | 877 | (reg->reg < 0x000000ff) && |
@@ -852,9 +882,11 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
852 | index = reg->reg; | 882 | index = reg->reg; |
853 | value = reg->val; | 883 | value = reg->val; |
854 | 884 | ||
855 | /* Note that there shall be no access to other page | 885 | /* |
856 | by any other function between the page swith and | 886 | * Note that there shall be no access to other page |
857 | the actual register write */ | 887 | * by any other function between the page switch and |
888 | * the actual register write. | ||
889 | */ | ||
858 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 890 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
859 | reg_w(gspca_dev, index, value); | 891 | reg_w(gspca_dev, index, value); |
860 | 892 | ||
@@ -940,6 +972,7 @@ static const struct usb_device_id device_table[] = { | |||
940 | {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, | 972 | {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, |
941 | {USB_DEVICE(0x093a, 0x2625)}, | 973 | {USB_DEVICE(0x093a, 0x2625)}, |
942 | {USB_DEVICE(0x093a, 0x2626)}, | 974 | {USB_DEVICE(0x093a, 0x2626)}, |
975 | {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP}, | ||
943 | {USB_DEVICE(0x093a, 0x2628)}, | 976 | {USB_DEVICE(0x093a, 0x2628)}, |
944 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, | 977 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, |
945 | {USB_DEVICE(0x093a, 0x262a)}, | 978 | {USB_DEVICE(0x093a, 0x262a)}, |