diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2009-11-11 05:46:28 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:41:49 -0500 |
commit | 189d92af707ead6aa4a3e14511662462e8e956e2 (patch) | |
tree | 8961adac8c132f12788f023a4a6f54ff889e3969 | |
parent | 4bdf4a8342ca01ff794f5de8f9766cf15947a2ef (diff) |
V4L/DVB (13422): gspca - ov534: ov772x changes from Richard Kaswy.
- 320x240 resolution added
- controls added
- different sd_desc tables
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/ov534.c | 676 |
1 files changed, 591 insertions, 85 deletions
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4b528b372911..fa28316c06ed 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ov534 gspca driver | 2 | * ov534 gspca driver |
3 | * | ||
3 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | 4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> |
4 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | 5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> |
5 | * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr | 6 | * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr |
@@ -8,6 +9,8 @@ | |||
8 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> | 9 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> |
9 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ | 10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ |
10 | * | 11 | * |
12 | * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr | ||
13 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 16 | * the Free Software Foundation; either version 2 of the License, or |
@@ -50,6 +53,14 @@ struct sd { | |||
50 | __u32 last_pts; | 53 | __u32 last_pts; |
51 | u16 last_fid; | 54 | u16 last_fid; |
52 | u8 frame_rate; | 55 | u8 frame_rate; |
56 | u8 gain; | ||
57 | u8 exposure; | ||
58 | u8 redblc; | ||
59 | u8 blueblc; | ||
60 | u8 autogain; | ||
61 | u8 sharpness; | ||
62 | u8 hflip; | ||
63 | u8 vflip; | ||
53 | 64 | ||
54 | u8 sensor; | 65 | u8 sensor; |
55 | #define SENSOR_OV772X 0 | 66 | #define SENSOR_OV772X 0 |
@@ -57,10 +68,146 @@ struct sd { | |||
57 | }; | 68 | }; |
58 | 69 | ||
59 | /* V4L2 controls supported by the driver */ | 70 | /* V4L2 controls supported by the driver */ |
60 | static struct ctrl sd_ctrls[] = { | 71 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
72 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
73 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
74 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
75 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val); | ||
76 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val); | ||
77 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val); | ||
78 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val); | ||
79 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
80 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
81 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
86 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
87 | |||
88 | static struct ctrl sd_ctrls_ov772x[] = { | ||
89 | { | ||
90 | { | ||
91 | .id = V4L2_CID_GAIN, | ||
92 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
93 | .name = "Main Gain", | ||
94 | .minimum = 0, | ||
95 | .maximum = 63, | ||
96 | .step = 1, | ||
97 | #define GAIN_DEF 20 | ||
98 | .default_value = GAIN_DEF, | ||
99 | }, | ||
100 | .set = sd_setgain, | ||
101 | .get = sd_getgain, | ||
102 | }, | ||
103 | { | ||
104 | { | ||
105 | .id = V4L2_CID_EXPOSURE, | ||
106 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
107 | .name = "Exposure", | ||
108 | .minimum = 0, | ||
109 | .maximum = 255, | ||
110 | .step = 1, | ||
111 | #define EXPO_DEF 255 | ||
112 | .default_value = EXPO_DEF, | ||
113 | }, | ||
114 | .set = sd_setexposure, | ||
115 | .get = sd_getexposure, | ||
116 | }, | ||
117 | { | ||
118 | { | ||
119 | .id = V4L2_CID_RED_BALANCE, | ||
120 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
121 | .name = "Red Balance", | ||
122 | .minimum = 0, | ||
123 | .maximum = 255, | ||
124 | .step = 1, | ||
125 | #define RED_BALANCE_DEF 128 | ||
126 | .default_value = RED_BALANCE_DEF, | ||
127 | }, | ||
128 | .set = sd_setredblc, | ||
129 | .get = sd_getredblc, | ||
130 | }, | ||
131 | { | ||
132 | { | ||
133 | .id = V4L2_CID_BLUE_BALANCE, | ||
134 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
135 | .name = "Blue Balance", | ||
136 | .minimum = 0, | ||
137 | .maximum = 255, | ||
138 | .step = 1, | ||
139 | #define BLUE_BALANCE_DEF 128 | ||
140 | .default_value = BLUE_BALANCE_DEF, | ||
141 | }, | ||
142 | .set = sd_setblueblc, | ||
143 | .get = sd_getblueblc, | ||
144 | }, | ||
145 | { | ||
146 | { | ||
147 | .id = V4L2_CID_AUTOGAIN, | ||
148 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
149 | .name = "Autogain", | ||
150 | .minimum = 0, | ||
151 | .maximum = 1, | ||
152 | .step = 1, | ||
153 | #define AUTOGAIN_DEF 1 | ||
154 | .default_value = AUTOGAIN_DEF, | ||
155 | }, | ||
156 | .set = sd_setautogain, | ||
157 | .get = sd_getautogain, | ||
158 | }, | ||
159 | { | ||
160 | { | ||
161 | .id = V4L2_CID_SHARPNESS, | ||
162 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
163 | .name = "Sharpness", | ||
164 | .minimum = 0, | ||
165 | .maximum = 63, | ||
166 | .step = 1, | ||
167 | #define SHARPNESS_DEF 4 | ||
168 | .default_value = SHARPNESS_DEF, | ||
169 | }, | ||
170 | .set = sd_setsharpness, | ||
171 | .get = sd_getsharpness, | ||
172 | }, | ||
173 | { | ||
174 | { | ||
175 | .id = V4L2_CID_HFLIP, | ||
176 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
177 | .name = "HFlip", | ||
178 | .minimum = 0, | ||
179 | .maximum = 1, | ||
180 | .step = 1, | ||
181 | #define HFLIP_DEF 0 | ||
182 | .default_value = HFLIP_DEF, | ||
183 | }, | ||
184 | .set = sd_sethflip, | ||
185 | .get = sd_gethflip, | ||
186 | }, | ||
187 | { | ||
188 | { | ||
189 | .id = V4L2_CID_VFLIP, | ||
190 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
191 | .name = "VFlip", | ||
192 | .minimum = 0, | ||
193 | .maximum = 1, | ||
194 | .step = 1, | ||
195 | #define VFLIP_DEF 0 | ||
196 | .default_value = VFLIP_DEF, | ||
197 | }, | ||
198 | .set = sd_setvflip, | ||
199 | .get = sd_getvflip, | ||
200 | }, | ||
201 | }; | ||
202 | static struct ctrl sd_ctrls_ov965x[] = { | ||
61 | }; | 203 | }; |
62 | 204 | ||
63 | static const struct v4l2_pix_format vga_yuyv_mode[] = { | 205 | static const struct v4l2_pix_format vga_yuyv_mode[] = { |
206 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | ||
207 | .bytesperline = 320 * 2, | ||
208 | .sizeimage = 320 * 240 * 2, | ||
209 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
210 | .priv = 1}, | ||
64 | {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | 211 | {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, |
65 | .bytesperline = 640 * 2, | 212 | .bytesperline = 640 * 2, |
66 | .sizeimage = 640 * 480 * 2, | 213 | .sizeimage = 640 * 480 * 2, |
@@ -80,8 +227,7 @@ static const struct v4l2_pix_format vga_jpeg_mode[] = { | |||
80 | .colorspace = V4L2_COLORSPACE_JPEG, | 227 | .colorspace = V4L2_COLORSPACE_JPEG, |
81 | .priv = 0}, | 228 | .priv = 0}, |
82 | }; | 229 | }; |
83 | 230 | static const u8 bridge_init_ov772x[][2] = { | |
84 | static const u8 bridge_init_ov722x[][2] = { | ||
85 | { 0xc2, 0x0c }, | 231 | { 0xc2, 0x0c }, |
86 | { 0x88, 0xf8 }, | 232 | { 0x88, 0xf8 }, |
87 | { 0xc3, 0x69 }, | 233 | { 0xc3, 0x69 }, |
@@ -122,6 +268,7 @@ static const u8 bridge_init_ov722x[][2] = { | |||
122 | { 0x1d, 0x40 }, | 268 | { 0x1d, 0x40 }, |
123 | { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ | 269 | { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ |
124 | { 0x1d, 0x00 }, /* payload size */ | 270 | { 0x1d, 0x00 }, /* payload size */ |
271 | |||
125 | { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ | 272 | { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ |
126 | { 0x1d, 0x58 }, /* frame size */ | 273 | { 0x1d, 0x58 }, /* frame size */ |
127 | { 0x1d, 0x00 }, /* frame size */ | 274 | { 0x1d, 0x00 }, /* frame size */ |
@@ -138,10 +285,20 @@ static const u8 bridge_init_ov722x[][2] = { | |||
138 | { 0xc1, 0x3c }, | 285 | { 0xc1, 0x3c }, |
139 | { 0xc2, 0x0c }, | 286 | { 0xc2, 0x0c }, |
140 | }; | 287 | }; |
141 | 288 | static const u8 sensor_init_ov772x[][2] = { | |
142 | static const u8 sensor_init_ov722x[][2] = { | ||
143 | { 0x12, 0x80 }, | 289 | { 0x12, 0x80 }, |
144 | { 0x11, 0x01 }, | 290 | { 0x11, 0x01 }, |
291 | /*fixme: better have a delay?*/ | ||
292 | { 0x11, 0x01 }, | ||
293 | { 0x11, 0x01 }, | ||
294 | { 0x11, 0x01 }, | ||
295 | { 0x11, 0x01 }, | ||
296 | { 0x11, 0x01 }, | ||
297 | { 0x11, 0x01 }, | ||
298 | { 0x11, 0x01 }, | ||
299 | { 0x11, 0x01 }, | ||
300 | { 0x11, 0x01 }, | ||
301 | { 0x11, 0x01 }, | ||
145 | 302 | ||
146 | { 0x3d, 0x03 }, | 303 | { 0x3d, 0x03 }, |
147 | { 0x17, 0x26 }, | 304 | { 0x17, 0x26 }, |
@@ -154,7 +311,7 @@ static const u8 sensor_init_ov722x[][2] = { | |||
154 | { 0x65, 0x20 }, | 311 | { 0x65, 0x20 }, |
155 | { 0x11, 0x01 }, | 312 | { 0x11, 0x01 }, |
156 | { 0x42, 0x7f }, | 313 | { 0x42, 0x7f }, |
157 | { 0x63, 0xe0 }, | 314 | { 0x63, 0xaa }, /* was e0 */ |
158 | { 0x64, 0xff }, | 315 | { 0x64, 0xff }, |
159 | { 0x66, 0x00 }, | 316 | { 0x66, 0x00 }, |
160 | { 0x13, 0xf0 }, | 317 | { 0x13, 0xf0 }, |
@@ -221,6 +378,46 @@ static const u8 sensor_init_ov722x[][2] = { | |||
221 | { 0x8e, 0x00 }, | 378 | { 0x8e, 0x00 }, |
222 | { 0x0c, 0xd0 } | 379 | { 0x0c, 0xd0 } |
223 | }; | 380 | }; |
381 | static const u8 bridge_start_ov772x_vga[][2] = { | ||
382 | {0x1c, 0x00}, | ||
383 | {0x1d, 0x40}, | ||
384 | {0x1d, 0x02}, | ||
385 | {0x1d, 0x00}, | ||
386 | {0x1d, 0x02}, | ||
387 | {0x1d, 0x58}, | ||
388 | {0x1d, 0x00}, | ||
389 | {0xc0, 0x50}, | ||
390 | {0xc1, 0x3c}, | ||
391 | }; | ||
392 | static const u8 sensor_start_ov772x_vga[][2] = { | ||
393 | {0x12, 0x00}, | ||
394 | {0x17, 0x26}, | ||
395 | {0x18, 0xa0}, | ||
396 | {0x19, 0x07}, | ||
397 | {0x1a, 0xf0}, | ||
398 | {0x29, 0xa0}, | ||
399 | {0x2c, 0xf0}, | ||
400 | }; | ||
401 | static const u8 bridge_start_ov772x_qvga[][2] = { | ||
402 | {0x1c, 0x00}, | ||
403 | {0x1d, 0x40}, | ||
404 | {0x1d, 0x02}, | ||
405 | {0x1d, 0x00}, | ||
406 | {0x1d, 0x01}, | ||
407 | {0x1d, 0x4b}, | ||
408 | {0x1d, 0x00}, | ||
409 | {0xc0, 0x28}, | ||
410 | {0xc1, 0x1e}, | ||
411 | }; | ||
412 | static const u8 sensor_start_ov772x_qvga[][2] = { | ||
413 | {0x12, 0x40}, | ||
414 | {0x17, 0x3f}, | ||
415 | {0x18, 0x50}, | ||
416 | {0x19, 0x03}, | ||
417 | {0x1a, 0x78}, | ||
418 | {0x29, 0x50}, | ||
419 | {0x2c, 0x78}, | ||
420 | }; | ||
224 | 421 | ||
225 | static const u8 bridge_init_ov965x[][2] = { | 422 | static const u8 bridge_init_ov965x[][2] = { |
226 | {0x88, 0xf8}, | 423 | {0x88, 0xf8}, |
@@ -757,35 +954,150 @@ static void sccb_w_array(struct gspca_dev *gspca_dev, | |||
757 | static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) | 954 | static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) |
758 | { | 955 | { |
759 | struct sd *sd = (struct sd *) gspca_dev; | 956 | struct sd *sd = (struct sd *) gspca_dev; |
760 | int fr = sd->frame_rate; | 957 | int i; |
958 | struct rate_s { | ||
959 | u8 fps; | ||
960 | u8 r11; | ||
961 | u8 r0d; | ||
962 | u8 re5; | ||
963 | }; | ||
964 | const struct rate_s *r; | ||
965 | static const struct rate_s rate_0[] = { /* 640x480 */ | ||
966 | {60, 0x01, 0xc1, 0x04}, | ||
967 | {50, 0x01, 0x41, 0x02}, | ||
968 | {40, 0x02, 0xc1, 0x04}, | ||
969 | {30, 0x04, 0x81, 0x02}, | ||
970 | {15, 0x03, 0x41, 0x04}, | ||
971 | }; | ||
972 | static const struct rate_s rate_1[] = { /* 320x240 */ | ||
973 | {125, 0x02, 0x81, 0x02}, | ||
974 | {100, 0x02, 0xc1, 0x04}, | ||
975 | {75, 0x03, 0xc1, 0x04}, | ||
976 | {60, 0x04, 0xc1, 0x04}, | ||
977 | {50, 0x02, 0x41, 0x04}, | ||
978 | {40, 0x03, 0x41, 0x04}, | ||
979 | {30, 0x04, 0x41, 0x04}, | ||
980 | }; | ||
981 | |||
982 | if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) { | ||
983 | r = rate_0; | ||
984 | i = ARRAY_SIZE(rate_0); | ||
985 | } else { | ||
986 | r = rate_1; | ||
987 | i = ARRAY_SIZE(rate_1); | ||
988 | } | ||
989 | while (--i > 0) { | ||
990 | if (sd->frame_rate >= r->fps) | ||
991 | break; | ||
992 | r++; | ||
993 | } | ||
994 | |||
995 | sccb_reg_write(gspca_dev, 0x11, r->r11); | ||
996 | sccb_reg_write(gspca_dev, 0x0d, r->r0d); | ||
997 | ov534_reg_write(gspca_dev, 0xe5, r->re5); | ||
998 | |||
999 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | ||
1000 | } | ||
1001 | |||
1002 | /* ov772x controls */ | ||
1003 | static void setgain(struct gspca_dev *gspca_dev) | ||
1004 | { | ||
1005 | struct sd *sd = (struct sd *) gspca_dev; | ||
1006 | u8 val; | ||
761 | 1007 | ||
762 | switch (fr) { | 1008 | val = sd->gain; |
763 | case 50: | 1009 | switch (val & 0x30) { |
764 | sccb_reg_write(gspca_dev, 0x11, 0x01); | 1010 | case 0x00: |
765 | sccb_reg_write(gspca_dev, 0x0d, 0x41); | 1011 | val &= 0x0f; |
766 | ov534_reg_write(gspca_dev, 0xe5, 0x02); | ||
767 | break; | 1012 | break; |
768 | case 40: | 1013 | case 0x10: |
769 | sccb_reg_write(gspca_dev, 0x11, 0x02); | 1014 | val &= 0x0f; |
770 | sccb_reg_write(gspca_dev, 0x0d, 0xc1); | 1015 | val |= 0x30; |
771 | ov534_reg_write(gspca_dev, 0xe5, 0x04); | ||
772 | break; | 1016 | break; |
773 | /* case 30: */ | 1017 | case 0x20: |
774 | default: | 1018 | val &= 0x0f; |
775 | fr = 30; | 1019 | val |= 0x70; |
776 | sccb_reg_write(gspca_dev, 0x11, 0x04); | ||
777 | sccb_reg_write(gspca_dev, 0x0d, 0x81); | ||
778 | ov534_reg_write(gspca_dev, 0xe5, 0x02); | ||
779 | break; | 1020 | break; |
780 | case 15: | 1021 | default: |
781 | sccb_reg_write(gspca_dev, 0x11, 0x03); | 1022 | /* case 0x30: */ |
782 | sccb_reg_write(gspca_dev, 0x0d, 0x41); | 1023 | val &= 0x0f; |
783 | ov534_reg_write(gspca_dev, 0xe5, 0x04); | 1024 | val |= 0xf0; |
784 | break; | 1025 | break; |
785 | } | 1026 | } |
1027 | sccb_reg_write(gspca_dev, 0x00, val); | ||
1028 | } | ||
1029 | |||
1030 | static void setexposure(struct gspca_dev *gspca_dev) | ||
1031 | { | ||
1032 | struct sd *sd = (struct sd *) gspca_dev; | ||
1033 | u8 val; | ||
1034 | |||
1035 | val = sd->exposure; | ||
1036 | sccb_reg_write(gspca_dev, 0x08, val >> 7); | ||
1037 | sccb_reg_write(gspca_dev, 0x10, val << 1); | ||
1038 | } | ||
1039 | |||
1040 | static void setredblc(struct gspca_dev *gspca_dev) | ||
1041 | { | ||
1042 | struct sd *sd = (struct sd *) gspca_dev; | ||
786 | 1043 | ||
787 | sd->frame_rate = fr; | 1044 | sccb_reg_write(gspca_dev, 0x43, sd->redblc); |
788 | PDEBUG(D_PROBE, "frame_rate: %d", fr); | 1045 | } |
1046 | |||
1047 | static void setblueblc(struct gspca_dev *gspca_dev) | ||
1048 | { | ||
1049 | struct sd *sd = (struct sd *) gspca_dev; | ||
1050 | |||
1051 | sccb_reg_write(gspca_dev, 0x42, sd->blueblc); | ||
1052 | } | ||
1053 | |||
1054 | static void setautogain(struct gspca_dev *gspca_dev) | ||
1055 | { | ||
1056 | struct sd *sd = (struct sd *) gspca_dev; | ||
1057 | |||
1058 | if (sd->autogain) { | ||
1059 | sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */ | ||
1060 | sccb_reg_write(gspca_dev, 0x64, | ||
1061 | sccb_reg_read(gspca_dev, 0x64) | 0x03); | ||
1062 | } else { | ||
1063 | sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */ | ||
1064 | sccb_reg_write(gspca_dev, 0x64, | ||
1065 | sccb_reg_read(gspca_dev, 0x64) & 0xfc); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | static void setsharpness(struct gspca_dev *gspca_dev) | ||
1070 | { | ||
1071 | struct sd *sd = (struct sd *) gspca_dev; | ||
1072 | u8 val; | ||
1073 | |||
1074 | val = sd->sharpness; | ||
1075 | sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */ | ||
1076 | sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */ | ||
1077 | } | ||
1078 | |||
1079 | static void sethflip(struct gspca_dev *gspca_dev) | ||
1080 | { | ||
1081 | struct sd *sd = (struct sd *) gspca_dev; | ||
1082 | |||
1083 | if (sd->hflip == 0) | ||
1084 | sccb_reg_write(gspca_dev, 0x0c, | ||
1085 | sccb_reg_read(gspca_dev, 0x0c) | 0x40); | ||
1086 | else | ||
1087 | sccb_reg_write(gspca_dev, 0x0c, | ||
1088 | sccb_reg_read(gspca_dev, 0x0c) & 0xbf); | ||
1089 | } | ||
1090 | |||
1091 | static void setvflip(struct gspca_dev *gspca_dev) | ||
1092 | { | ||
1093 | struct sd *sd = (struct sd *) gspca_dev; | ||
1094 | |||
1095 | if (sd->vflip == 0) | ||
1096 | sccb_reg_write(gspca_dev, 0x0c, | ||
1097 | sccb_reg_read(gspca_dev, 0x0c) | 0x80); | ||
1098 | else | ||
1099 | sccb_reg_write(gspca_dev, 0x0c, | ||
1100 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | ||
789 | } | 1101 | } |
790 | 1102 | ||
791 | /* this function is called at probe time */ | 1103 | /* this function is called at probe time */ |
@@ -811,6 +1123,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
811 | cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); | 1123 | cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); |
812 | } | 1124 | } |
813 | 1125 | ||
1126 | sd->frame_rate = 30; | ||
1127 | sd->gain = GAIN_DEF; | ||
1128 | sd->exposure = EXPO_DEF; | ||
1129 | sd->redblc = RED_BALANCE_DEF; | ||
1130 | sd->blueblc = BLUE_BALANCE_DEF; | ||
1131 | sd->autogain = AUTOGAIN_DEF; | ||
1132 | sd->sharpness = SHARPNESS_DEF; | ||
1133 | #if HFLIP_DEF != 0 | ||
1134 | sd->hflip = HFLIP_DEF; | ||
1135 | #endif | ||
1136 | #if VFLIP_DEF != 0 | ||
1137 | sd->vflip = VFLIP_DEF; | ||
1138 | #endif | ||
814 | return 0; | 1139 | return 0; |
815 | } | 1140 | } |
816 | 1141 | ||
@@ -847,11 +1172,11 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
847 | /* initialize */ | 1172 | /* initialize */ |
848 | switch (sd->sensor) { | 1173 | switch (sd->sensor) { |
849 | case SENSOR_OV772X: | 1174 | case SENSOR_OV772X: |
850 | reg_w_array(gspca_dev, bridge_init_ov722x, | 1175 | reg_w_array(gspca_dev, bridge_init_ov772x, |
851 | ARRAY_SIZE(bridge_init_ov722x)); | 1176 | ARRAY_SIZE(bridge_init_ov772x)); |
852 | ov534_set_led(gspca_dev, 1); | 1177 | ov534_set_led(gspca_dev, 1); |
853 | sccb_w_array(gspca_dev, sensor_init_ov722x, | 1178 | sccb_w_array(gspca_dev, sensor_init_ov772x, |
854 | ARRAY_SIZE(sensor_init_ov722x)); | 1179 | ARRAY_SIZE(sensor_init_ov772x)); |
855 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 1180 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
856 | ov534_set_led(gspca_dev, 0); | 1181 | ov534_set_led(gspca_dev, 0); |
857 | ov534_set_frame_rate(gspca_dev); | 1182 | ov534_set_frame_rate(gspca_dev); |
@@ -875,60 +1200,78 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
875 | return 0; | 1200 | return 0; |
876 | } | 1201 | } |
877 | 1202 | ||
878 | static int sd_start(struct gspca_dev *gspca_dev) | 1203 | static int sd_start_ov772x(struct gspca_dev *gspca_dev) |
879 | { | 1204 | { |
880 | struct sd *sd = (struct sd *) gspca_dev; | ||
881 | int mode; | 1205 | int mode; |
882 | 1206 | ||
883 | switch (sd->sensor) { | 1207 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
884 | case SENSOR_OV772X: | 1208 | if (mode != 0) { /* 320x240 */ |
885 | ov534_set_led(gspca_dev, 1); | 1209 | reg_w_array(gspca_dev, bridge_start_ov772x_qvga, |
886 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | 1210 | ARRAY_SIZE(bridge_start_ov772x_qvga)); |
887 | break; | 1211 | sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, |
888 | default: | 1212 | ARRAY_SIZE(sensor_start_ov772x_qvga)); |
889 | /* case SENSOR_OV965X: */ | 1213 | } else { /* 640x480 */ |
890 | 1214 | reg_w_array(gspca_dev, bridge_start_ov772x_vga, | |
891 | sccb_w_array(gspca_dev, sensor_start_ov965x, | 1215 | ARRAY_SIZE(bridge_start_ov772x_vga)); |
892 | ARRAY_SIZE(sensor_start_ov965x)); | 1216 | sccb_w_array(gspca_dev, sensor_start_ov772x_vga, |
893 | reg_w_array(gspca_dev, bridge_start_ov965x, | 1217 | ARRAY_SIZE(sensor_start_ov772x_vga)); |
894 | ARRAY_SIZE(bridge_start_ov965x)); | ||
895 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
896 | if (mode != 0) { /* 320x240 */ | ||
897 | reg_w_array(gspca_dev, bridge_start_ov965x_cif, | ||
898 | ARRAY_SIZE(bridge_start_ov965x_cif)); | ||
899 | sccb_w_array(gspca_dev, sensor_start_ov965x_cif, | ||
900 | ARRAY_SIZE(sensor_start_ov965x_cif)); | ||
901 | } else { /* 640x480 */ | ||
902 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
903 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
904 | sccb_w_array(gspca_dev, sensor_start_ov965x_vga, | ||
905 | ARRAY_SIZE(sensor_start_ov965x_vga)); | ||
906 | } | ||
907 | sccb_w_array(gspca_dev, sensor_start_ov965x_2, | ||
908 | ARRAY_SIZE(sensor_start_ov965x_2)); | ||
909 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
910 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
911 | ov534_set_led(gspca_dev, 1); | ||
912 | } | 1218 | } |
1219 | ov534_set_frame_rate(gspca_dev); | ||
1220 | |||
1221 | setautogain(gspca_dev); | ||
1222 | setgain(gspca_dev); | ||
1223 | setredblc(gspca_dev); | ||
1224 | setblueblc(gspca_dev); | ||
1225 | setexposure(gspca_dev); | ||
1226 | setsharpness(gspca_dev); | ||
1227 | setvflip(gspca_dev); | ||
1228 | sethflip(gspca_dev); | ||
1229 | |||
1230 | ov534_set_led(gspca_dev, 1); | ||
1231 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
913 | return 0; | 1232 | return 0; |
914 | } | 1233 | } |
915 | 1234 | ||
916 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1235 | static int sd_start_ov965x(struct gspca_dev *gspca_dev) |
917 | { | 1236 | { |
918 | struct sd *sd = (struct sd *) gspca_dev; | 1237 | int mode; |
919 | 1238 | ||
920 | switch (sd->sensor) { | 1239 | sccb_w_array(gspca_dev, sensor_start_ov965x, |
921 | case SENSOR_OV772X: | 1240 | ARRAY_SIZE(sensor_start_ov965x)); |
922 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 1241 | reg_w_array(gspca_dev, bridge_start_ov965x, |
923 | ov534_set_led(gspca_dev, 0); | 1242 | ARRAY_SIZE(bridge_start_ov965x)); |
924 | break; | 1243 | |
925 | default: | 1244 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
926 | /* case SENSOR_OV965X: */ | 1245 | if (mode != 0) { /* 320x240 */ |
927 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | 1246 | reg_w_array(gspca_dev, bridge_start_ov965x_cif, |
928 | ov534_set_led(gspca_dev, 0); | 1247 | ARRAY_SIZE(bridge_start_ov965x_cif)); |
929 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | 1248 | sccb_w_array(gspca_dev, sensor_start_ov965x_cif, |
930 | break; | 1249 | ARRAY_SIZE(sensor_start_ov965x_cif)); |
1250 | } else { /* 640x480 */ | ||
1251 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
1252 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
1253 | sccb_w_array(gspca_dev, sensor_start_ov965x_vga, | ||
1254 | ARRAY_SIZE(sensor_start_ov965x_vga)); | ||
931 | } | 1255 | } |
1256 | sccb_w_array(gspca_dev, sensor_start_ov965x_2, | ||
1257 | ARRAY_SIZE(sensor_start_ov965x_2)); | ||
1258 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1259 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1260 | ov534_set_led(gspca_dev, 1); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) | ||
1265 | { | ||
1266 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | ||
1267 | ov534_set_led(gspca_dev, 0); | ||
1268 | } | ||
1269 | |||
1270 | static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) | ||
1271 | { | ||
1272 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1273 | ov534_set_led(gspca_dev, 0); | ||
1274 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
932 | } | 1275 | } |
933 | 1276 | ||
934 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 1277 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ |
@@ -1002,7 +1345,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, | |||
1002 | data + 12, len - 12); | 1345 | data + 12, len - 12); |
1003 | } | 1346 | } |
1004 | 1347 | ||
1005 | |||
1006 | /* Done this payload */ | 1348 | /* Done this payload */ |
1007 | goto scan_next; | 1349 | goto scan_next; |
1008 | 1350 | ||
@@ -1016,6 +1358,151 @@ scan_next: | |||
1016 | } while (remaining_len > 0); | 1358 | } while (remaining_len > 0); |
1017 | } | 1359 | } |
1018 | 1360 | ||
1361 | /* ov772x controls */ | ||
1362 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
1363 | { | ||
1364 | struct sd *sd = (struct sd *) gspca_dev; | ||
1365 | |||
1366 | sd->gain = val; | ||
1367 | if (gspca_dev->streaming) | ||
1368 | setgain(gspca_dev); | ||
1369 | return 0; | ||
1370 | } | ||
1371 | |||
1372 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1373 | { | ||
1374 | struct sd *sd = (struct sd *) gspca_dev; | ||
1375 | |||
1376 | *val = sd->gain; | ||
1377 | return 0; | ||
1378 | } | ||
1379 | |||
1380 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1381 | { | ||
1382 | struct sd *sd = (struct sd *) gspca_dev; | ||
1383 | |||
1384 | sd->exposure = val; | ||
1385 | if (gspca_dev->streaming) | ||
1386 | setexposure(gspca_dev); | ||
1387 | return 0; | ||
1388 | } | ||
1389 | |||
1390 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1391 | { | ||
1392 | struct sd *sd = (struct sd *) gspca_dev; | ||
1393 | |||
1394 | *val = sd->exposure; | ||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | ||
1399 | { | ||
1400 | struct sd *sd = (struct sd *) gspca_dev; | ||
1401 | |||
1402 | sd->redblc = val; | ||
1403 | if (gspca_dev->streaming) | ||
1404 | setredblc(gspca_dev); | ||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
1409 | { | ||
1410 | struct sd *sd = (struct sd *) gspca_dev; | ||
1411 | |||
1412 | *val = sd->redblc; | ||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val) | ||
1417 | { | ||
1418 | struct sd *sd = (struct sd *) gspca_dev; | ||
1419 | |||
1420 | sd->blueblc = val; | ||
1421 | if (gspca_dev->streaming) | ||
1422 | setblueblc(gspca_dev); | ||
1423 | return 0; | ||
1424 | } | ||
1425 | |||
1426 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
1427 | { | ||
1428 | struct sd *sd = (struct sd *) gspca_dev; | ||
1429 | |||
1430 | *val = sd->blueblc; | ||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1435 | { | ||
1436 | struct sd *sd = (struct sd *) gspca_dev; | ||
1437 | |||
1438 | sd->autogain = val; | ||
1439 | if (gspca_dev->streaming) | ||
1440 | setautogain(gspca_dev); | ||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1445 | { | ||
1446 | struct sd *sd = (struct sd *) gspca_dev; | ||
1447 | |||
1448 | *val = sd->autogain; | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
1453 | { | ||
1454 | struct sd *sd = (struct sd *) gspca_dev; | ||
1455 | |||
1456 | sd->sharpness = val; | ||
1457 | if (gspca_dev->streaming) | ||
1458 | setsharpness(gspca_dev); | ||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
1462 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1463 | { | ||
1464 | struct sd *sd = (struct sd *) gspca_dev; | ||
1465 | |||
1466 | *val = sd->sharpness; | ||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1471 | { | ||
1472 | struct sd *sd = (struct sd *) gspca_dev; | ||
1473 | |||
1474 | sd->hflip = val; | ||
1475 | if (gspca_dev->streaming) | ||
1476 | sethflip(gspca_dev); | ||
1477 | return 0; | ||
1478 | } | ||
1479 | |||
1480 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1481 | { | ||
1482 | struct sd *sd = (struct sd *) gspca_dev; | ||
1483 | |||
1484 | *val = sd->hflip; | ||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1489 | { | ||
1490 | struct sd *sd = (struct sd *) gspca_dev; | ||
1491 | |||
1492 | sd->vflip = val; | ||
1493 | if (gspca_dev->streaming) | ||
1494 | setvflip(gspca_dev); | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1499 | { | ||
1500 | struct sd *sd = (struct sd *) gspca_dev; | ||
1501 | |||
1502 | *val = sd->vflip; | ||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1019 | /* get stream parameters (framerate) */ | 1506 | /* get stream parameters (framerate) */ |
1020 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, | 1507 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, |
1021 | struct v4l2_streamparm *parm) | 1508 | struct v4l2_streamparm *parm) |
@@ -1047,7 +1534,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
1047 | 1534 | ||
1048 | /* Set requested framerate */ | 1535 | /* Set requested framerate */ |
1049 | sd->frame_rate = tpf->denominator / tpf->numerator; | 1536 | sd->frame_rate = tpf->denominator / tpf->numerator; |
1050 | ov534_set_frame_rate(gspca_dev); | 1537 | if (gspca_dev->streaming) |
1538 | ov534_set_frame_rate(gspca_dev); | ||
1051 | 1539 | ||
1052 | /* Return the actual framerate */ | 1540 | /* Return the actual framerate */ |
1053 | tpf->numerator = 1; | 1541 | tpf->numerator = 1; |
@@ -1057,14 +1545,27 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
1057 | } | 1545 | } |
1058 | 1546 | ||
1059 | /* sub-driver description */ | 1547 | /* sub-driver description */ |
1060 | static const struct sd_desc sd_desc = { | 1548 | static const struct sd_desc sd_desc_ov772x = { |
1061 | .name = MODULE_NAME, | 1549 | .name = MODULE_NAME, |
1062 | .ctrls = sd_ctrls, | 1550 | .ctrls = sd_ctrls_ov772x, |
1063 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1551 | .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), |
1064 | .config = sd_config, | 1552 | .config = sd_config, |
1065 | .init = sd_init, | 1553 | .init = sd_init, |
1066 | .start = sd_start, | 1554 | .start = sd_start_ov772x, |
1067 | .stopN = sd_stopN, | 1555 | .stopN = sd_stopN_ov772x, |
1556 | .pkt_scan = sd_pkt_scan, | ||
1557 | .get_streamparm = sd_get_streamparm, | ||
1558 | .set_streamparm = sd_set_streamparm, | ||
1559 | }; | ||
1560 | |||
1561 | static const struct sd_desc sd_desc_ov965x = { | ||
1562 | .name = MODULE_NAME, | ||
1563 | .ctrls = sd_ctrls_ov965x, | ||
1564 | .nctrls = ARRAY_SIZE(sd_ctrls_ov965x), | ||
1565 | .config = sd_config, | ||
1566 | .init = sd_init, | ||
1567 | .start = sd_start_ov965x, | ||
1568 | .stopN = sd_stopN_ov965x, | ||
1068 | .pkt_scan = sd_pkt_scan, | 1569 | .pkt_scan = sd_pkt_scan, |
1069 | .get_streamparm = sd_get_streamparm, | 1570 | .get_streamparm = sd_get_streamparm, |
1070 | .set_streamparm = sd_set_streamparm, | 1571 | .set_streamparm = sd_set_streamparm, |
@@ -1082,8 +1583,12 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
1082 | /* -- device connect -- */ | 1583 | /* -- device connect -- */ |
1083 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1584 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
1084 | { | 1585 | { |
1085 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 1586 | return gspca_dev_probe(intf, id, |
1086 | THIS_MODULE); | 1587 | id->driver_info == SENSOR_OV772X |
1588 | ? &sd_desc_ov772x | ||
1589 | : &sd_desc_ov965x, | ||
1590 | sizeof(struct sd), | ||
1591 | THIS_MODULE); | ||
1087 | } | 1592 | } |
1088 | 1593 | ||
1089 | static struct usb_driver sd_driver = { | 1594 | static struct usb_driver sd_driver = { |
@@ -1101,6 +1606,7 @@ static struct usb_driver sd_driver = { | |||
1101 | static int __init sd_mod_init(void) | 1606 | static int __init sd_mod_init(void) |
1102 | { | 1607 | { |
1103 | int ret; | 1608 | int ret; |
1609 | |||
1104 | ret = usb_register(&sd_driver); | 1610 | ret = usb_register(&sd_driver); |
1105 | if (ret < 0) | 1611 | if (ret < 0) |
1106 | return ret; | 1612 | return ret; |