diff options
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r-- | drivers/media/video/gspca/spca561.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index b9c80e2103b9..7bb2355005dc 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #define MODULE_NAME "spca561" | 23 | #define MODULE_NAME "spca561" |
24 | 24 | ||
25 | #include <linux/input.h> | ||
25 | #include "gspca.h" | 26 | #include "gspca.h" |
26 | 27 | ||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
@@ -249,9 +250,9 @@ static const __u16 Pb100_2map8300[][2] = { | |||
249 | }; | 250 | }; |
250 | 251 | ||
251 | static const __u16 spca561_161rev12A_data1[][2] = { | 252 | static const __u16 spca561_161rev12A_data1[][2] = { |
252 | {0x29, 0x8118}, /* white balance - was 21 */ | 253 | {0x29, 0x8118}, /* Control register (various enable bits) */ |
253 | {0x08, 0x8114}, /* white balance - was 01 */ | 254 | {0x08, 0x8114}, /* GPIO: Led off */ |
254 | {0x0e, 0x8112}, /* white balance - was 00 */ | 255 | {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */ |
255 | {0x00, 0x8102}, /* white balance - new */ | 256 | {0x00, 0x8102}, /* white balance - new */ |
256 | {0x92, 0x8804}, | 257 | {0x92, 0x8804}, |
257 | {0x04, 0x8802}, /* windows uses 08 */ | 258 | {0x04, 0x8802}, /* windows uses 08 */ |
@@ -263,15 +264,11 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
263 | {0x07, 0x8601}, | 264 | {0x07, 0x8601}, |
264 | {0x07, 0x8602}, | 265 | {0x07, 0x8602}, |
265 | {0x04, 0x8501}, | 266 | {0x04, 0x8501}, |
266 | {0x21, 0x8118}, | ||
267 | 267 | ||
268 | {0x07, 0x8201}, /* windows uses 02 */ | 268 | {0x07, 0x8201}, /* windows uses 02 */ |
269 | {0x08, 0x8200}, | 269 | {0x08, 0x8200}, |
270 | {0x01, 0x8200}, | 270 | {0x01, 0x8200}, |
271 | 271 | ||
272 | {0x00, 0x8114}, | ||
273 | {0x01, 0x8114}, /* windows uses 00 */ | ||
274 | |||
275 | {0x90, 0x8604}, | 272 | {0x90, 0x8604}, |
276 | {0x00, 0x8605}, | 273 | {0x00, 0x8605}, |
277 | {0xb0, 0x8603}, | 274 | {0xb0, 0x8603}, |
@@ -302,6 +299,9 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
302 | {0xf0, 0x8505}, | 299 | {0xf0, 0x8505}, |
303 | {0x32, 0x850a}, | 300 | {0x32, 0x850a}, |
304 | /* {0x99, 0x8700}, * - white balance - new (removed) */ | 301 | /* {0x99, 0x8700}, * - white balance - new (removed) */ |
302 | /* HDG we used to do this in stop0, making the init state and the state | ||
303 | after a start / stop different, so do this here instead. */ | ||
304 | {0x29, 0x8118}, | ||
305 | {} | 305 | {} |
306 | }; | 306 | }; |
307 | 307 | ||
@@ -645,6 +645,9 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) | |||
645 | setwhite(gspca_dev); | 645 | setwhite(gspca_dev); |
646 | setgain(gspca_dev); | 646 | setgain(gspca_dev); |
647 | setexposure(gspca_dev); | 647 | setexposure(gspca_dev); |
648 | |||
649 | /* Led ON (bit 3 -> 0 */ | ||
650 | reg_w_val(gspca_dev->dev, 0x8114, 0x00); | ||
648 | return 0; | 651 | return 0; |
649 | } | 652 | } |
650 | static int sd_start_72a(struct gspca_dev *gspca_dev) | 653 | static int sd_start_72a(struct gspca_dev *gspca_dev) |
@@ -691,26 +694,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
691 | 694 | ||
692 | if (sd->chip_revision == Rev012A) { | 695 | if (sd->chip_revision == Rev012A) { |
693 | reg_w_val(gspca_dev->dev, 0x8112, 0x0e); | 696 | reg_w_val(gspca_dev->dev, 0x8112, 0x0e); |
697 | /* Led Off (bit 3 -> 1 */ | ||
698 | reg_w_val(gspca_dev->dev, 0x8114, 0x08); | ||
694 | } else { | 699 | } else { |
695 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); | 700 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); |
696 | /* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ | 701 | /* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ |
697 | } | 702 | } |
698 | } | 703 | } |
699 | 704 | ||
700 | /* called on streamoff with alt 0 and on disconnect */ | ||
701 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
702 | { | ||
703 | struct sd *sd = (struct sd *) gspca_dev; | ||
704 | |||
705 | if (!gspca_dev->present) | ||
706 | return; | ||
707 | if (sd->chip_revision == Rev012A) { | ||
708 | reg_w_val(gspca_dev->dev, 0x8118, 0x29); | ||
709 | reg_w_val(gspca_dev->dev, 0x8114, 0x08); | ||
710 | } | ||
711 | /* reg_w_val(gspca_dev->dev, 0x8114, 0); */ | ||
712 | } | ||
713 | |||
714 | static void do_autogain(struct gspca_dev *gspca_dev) | 705 | static void do_autogain(struct gspca_dev *gspca_dev) |
715 | { | 706 | { |
716 | struct sd *sd = (struct sd *) gspca_dev; | 707 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -788,6 +779,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
788 | switch (*data++) { /* sequence number */ | 779 | switch (*data++) { /* sequence number */ |
789 | case 0: /* start of frame */ | 780 | case 0: /* start of frame */ |
790 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | 781 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
782 | |||
783 | /* This should never happen */ | ||
784 | if (len < 2) { | ||
785 | PDEBUG(D_ERR, "Short SOF packet, ignoring"); | ||
786 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
787 | return; | ||
788 | } | ||
789 | |||
790 | #ifdef CONFIG_INPUT | ||
791 | if (data[0] & 0x20) { | ||
792 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
793 | input_sync(gspca_dev->input_dev); | ||
794 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
795 | input_sync(gspca_dev->input_dev); | ||
796 | } | ||
797 | #endif | ||
798 | |||
791 | if (data[1] & 0x10) { | 799 | if (data[1] & 0x10) { |
792 | /* compressed bayer */ | 800 | /* compressed bayer */ |
793 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | 801 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
@@ -1028,8 +1036,10 @@ static const struct sd_desc sd_desc_12a = { | |||
1028 | .init = sd_init_12a, | 1036 | .init = sd_init_12a, |
1029 | .start = sd_start_12a, | 1037 | .start = sd_start_12a, |
1030 | .stopN = sd_stopN, | 1038 | .stopN = sd_stopN, |
1031 | .stop0 = sd_stop0, | ||
1032 | .pkt_scan = sd_pkt_scan, | 1039 | .pkt_scan = sd_pkt_scan, |
1040 | #ifdef CONFIG_INPUT | ||
1041 | .other_input = 1, | ||
1042 | #endif | ||
1033 | }; | 1043 | }; |
1034 | static const struct sd_desc sd_desc_72a = { | 1044 | static const struct sd_desc sd_desc_72a = { |
1035 | .name = MODULE_NAME, | 1045 | .name = MODULE_NAME, |
@@ -1039,9 +1049,11 @@ static const struct sd_desc sd_desc_72a = { | |||
1039 | .init = sd_init_72a, | 1049 | .init = sd_init_72a, |
1040 | .start = sd_start_72a, | 1050 | .start = sd_start_72a, |
1041 | .stopN = sd_stopN, | 1051 | .stopN = sd_stopN, |
1042 | .stop0 = sd_stop0, | ||
1043 | .pkt_scan = sd_pkt_scan, | 1052 | .pkt_scan = sd_pkt_scan, |
1044 | .dq_callback = do_autogain, | 1053 | .dq_callback = do_autogain, |
1054 | #ifdef CONFIG_INPUT | ||
1055 | .other_input = 1, | ||
1056 | #endif | ||
1045 | }; | 1057 | }; |
1046 | static const struct sd_desc *sd_desc[2] = { | 1058 | static const struct sd_desc *sd_desc[2] = { |
1047 | &sd_desc_12a, | 1059 | &sd_desc_12a, |