]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/media/video/gspca/t613.c
74ca17845223e297c6087d423dd8745824ef2994
[mirror_ubuntu-bionic-kernel.git] / drivers / media / video / gspca / t613.c
1 /*
2 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
24 * Costantino Leandro
25 */
26
27 #define MODULE_NAME "t613"
28
29 #include "gspca.h"
30
31 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
32
33 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35 MODULE_LICENSE("GPL");
36
37 struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
40 unsigned char brightness;
41 unsigned char contrast;
42 unsigned char colors;
43 unsigned char autogain;
44 unsigned char gamma;
45 unsigned char sharpness;
46 unsigned char freq;
47 unsigned char whitebalance;
48 unsigned char mirror;
49 unsigned char effect;
50
51 __u8 sensor;
52 #define SENSOR_TAS5130A 0
53 #define SENSOR_OM6802 1
54 };
55
56 /* V4L2 controls supported by the driver */
57 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80 static struct ctrl sd_ctrls[] = {
81 #define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 14,
89 .step = 1,
90 .default_value = 8,
91 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95 #define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109 #define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
123 #define GAMMA_MAX 16
124 #define GAMMA_DEF 10
125 {
126 {
127 .id = V4L2_CID_GAMMA, /* (gamma on win) */
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "Gamma",
130 .minimum = 0,
131 .maximum = GAMMA_MAX - 1,
132 .step = 1,
133 .default_value = GAMMA_DEF,
134 },
135 .set = sd_setgamma,
136 .get = sd_getgamma,
137 },
138 #define SD_AUTOGAIN 4
139 {
140 {
141 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
142 * some apps dont bring up the
143 * backligth_compensation control) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Low Light",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149 .default_value = 0x01,
150 },
151 .set = sd_setlowlight,
152 .get = sd_getlowlight,
153 },
154 #define SD_MIRROR 5
155 {
156 {
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
163 .default_value = 0,
164 },
165 .set = sd_setflip,
166 .get = sd_getflip
167 },
168 #define SD_LIGHTFREQ 6
169 {
170 {
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
175 .maximum = 2,
176 .step = 1,
177 .default_value = 1,
178 },
179 .set = sd_setfreq,
180 .get = sd_getfreq},
181
182 #define SD_WHITE_BALANCE 7
183 {
184 {
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
188 .minimum = 0,
189 .maximum = 1,
190 .step = 1,
191 .default_value = 0,
192 },
193 .set = sd_setwhitebalance,
194 .get = sd_getwhitebalance
195 },
196 #define SD_SHARPNESS 8 /* (aka definition on win) */
197 {
198 {
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Sharpness",
202 .minimum = 0,
203 .maximum = 15,
204 .step = 1,
205 .default_value = 0x06,
206 },
207 .set = sd_setsharpness,
208 .get = sd_getsharpness,
209 },
210 #define SD_EFFECTS 9
211 {
212 {
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
216 .minimum = 0,
217 .maximum = 4,
218 .step = 1,
219 .default_value = 0,
220 },
221 .set = sd_seteffect,
222 .get = sd_geteffect
223 },
224 };
225
226 static char *effects_control[] = {
227 "Normal",
228 "Emboss", /* disabled */
229 "Monochrome",
230 "Sepia",
231 "Sketch",
232 "Sun Effect", /* disabled */
233 "Negative",
234 };
235
236 static const struct v4l2_pix_format vga_mode_t16[] = {
237 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
238 .bytesperline = 160,
239 .sizeimage = 160 * 120 * 4 / 8 + 590,
240 .colorspace = V4L2_COLORSPACE_JPEG,
241 .priv = 4},
242 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
243 .bytesperline = 176,
244 .sizeimage = 176 * 144 * 3 / 8 + 590,
245 .colorspace = V4L2_COLORSPACE_JPEG,
246 .priv = 3},
247 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
248 .bytesperline = 320,
249 .sizeimage = 320 * 240 * 3 / 8 + 590,
250 .colorspace = V4L2_COLORSPACE_JPEG,
251 .priv = 2},
252 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .bytesperline = 352,
254 .sizeimage = 352 * 288 * 3 / 8 + 590,
255 .colorspace = V4L2_COLORSPACE_JPEG,
256 .priv = 1},
257 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
258 .bytesperline = 640,
259 .sizeimage = 640 * 480 * 3 / 8 + 590,
260 .colorspace = V4L2_COLORSPACE_JPEG,
261 .priv = 0},
262 };
263
264 /* sensor specific data */
265 struct additional_sensor_data {
266 const __u8 data1[20];
267 const __u8 data2[18];
268 const __u8 data3[18];
269 const __u8 data4[4];
270 const __u8 data5[6];
271 const __u8 stream[4];
272 };
273
274 const static struct additional_sensor_data sensor_data[] = {
275 { /* TAS5130A */
276 .data1 =
277 {0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10,
278 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
279 0xd8, 0xc8, 0xd9, 0xfc},
280 .data2 =
281 {0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60,
282 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
283 0xe8, 0xe0},
284 .data3 =
285 {0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60,
286 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
287 0xcf, 0xe0},
288 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
289 {0x66, 0x00, 0xa8, 0xe8},
290 .data5 =
291 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
292 .stream =
293 {0x0b, 0x04, 0x0a, 0x40},
294 },
295 { /* OM6802 */
296 .data1 =
297 {0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22,
298 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06,
299 0xd8, 0xb3, 0xd9, 0xfc},
300 .data2 =
301 {0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80,
302 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff,
303 0xe8, 0xff},
304 .data3 =
305 {0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80,
306 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff,
307 0xcf, 0xff},
308 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
309 {0x66, 0xca, 0xa8, 0xf0 },
310 .data5 = /* this could be removed later */
311 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
312 .stream =
313 {0x0b, 0x04, 0x0a, 0x78},
314 }
315 };
316
317 #define MAX_EFFECTS 7
318 /* easily done by soft, this table could be removed,
319 * i keep it here just in case */
320 static const __u8 effects_table[MAX_EFFECTS][6] = {
321 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
322 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
323 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
324 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
325 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
326 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
327 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
328 };
329
330 static const __u8 gamma_table[GAMMA_MAX][34] = {
331 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */
332 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
333 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
334 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
335 0xa0, 0xff},
336 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */
337 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
338 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
339 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
340 0xa0, 0xff},
341 {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */
342 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
343 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
344 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
345 0xa0, 0xff},
346 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */
347 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
348 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
349 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
350 0xa0, 0xff},
351 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */
352 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
353 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
354 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
355 0xa0, 0xff},
356 {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */
357 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
358 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
359 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
360 0xa0, 0xff},
361 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */
362 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
363 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
364 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
365 0xa0, 0xff},
366 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */
367 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
368 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
369 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
370 0xa0, 0xff},
371 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */
372 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
373 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
374 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
375 0xa0, 0xff},
376 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */
377 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
378 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
379 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
380 0xa0, 0xff},
381 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */
382 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
383 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
384 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
385 0xa0, 0xff},
386 {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */
387 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
388 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
389 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
390 0xa0, 0xff},
391 {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */
392 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
393 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
394 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
395 0xa0, 0xff},
396 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */
397 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
398 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
399 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
400 0xa0, 0xff},
401 {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */
402 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
403 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
404 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
405 0xa0, 0xff},
406 {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */
407 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
408 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
409 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
410 0xa0, 0xff}
411 };
412
413 static const __u8 tas5130a_sensor_init[][8] = {
414 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
415 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
416 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
417 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
418 {},
419 };
420
421 static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
422
423 /* read 1 byte */
424 static int reg_r(struct gspca_dev *gspca_dev,
425 __u16 index)
426 {
427 usb_control_msg(gspca_dev->dev,
428 usb_rcvctrlpipe(gspca_dev->dev, 0),
429 0, /* request */
430 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
431 0, /* value */
432 index,
433 gspca_dev->usb_buf, 1, 500);
434 return gspca_dev->usb_buf[0];
435 }
436
437 static void reg_w(struct gspca_dev *gspca_dev,
438 __u16 index)
439 {
440 usb_control_msg(gspca_dev->dev,
441 usb_sndctrlpipe(gspca_dev->dev, 0),
442 0,
443 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
444 0, index,
445 NULL, 0, 500);
446 }
447
448 static void reg_w_buf(struct gspca_dev *gspca_dev,
449 const __u8 *buffer, __u16 len)
450 {
451 if (len <= USB_BUF_SZ) {
452 memcpy(gspca_dev->usb_buf, buffer, len);
453 usb_control_msg(gspca_dev->dev,
454 usb_sndctrlpipe(gspca_dev->dev, 0),
455 0,
456 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
457 0x01, 0,
458 gspca_dev->usb_buf, len, 500);
459 } else {
460 __u8 *tmpbuf;
461
462 tmpbuf = kmalloc(len, GFP_KERNEL);
463 memcpy(tmpbuf, buffer, len);
464 usb_control_msg(gspca_dev->dev,
465 usb_sndctrlpipe(gspca_dev->dev, 0),
466 0,
467 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
468 0x01, 0,
469 tmpbuf, len, 500);
470 kfree(tmpbuf);
471 }
472 }
473
474 /* Reported as OM6802*/
475 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
476 {
477 int i;
478 const __u8 *p;
479 __u8 byte;
480 __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
481 static const __u8 sensor_init[] = {
482 0xdf, 0x6d,
483 0xdd, 0x18,
484 0x5a, 0xe0,
485 0x5c, 0x07,
486 0x5d, 0xb0,
487 0x5e, 0x1e,
488 0x60, 0x71,
489 0xef, 0x00,
490 0xe9, 0x00,
491 0xea, 0x00,
492 0x90, 0x24,
493 0x91, 0xb2,
494 0x82, 0x32,
495 0xfd, 0x41,
496 0x00 /* table end */
497 };
498
499 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
500 msleep(5);
501 i = 4;
502 while (--i > 0) {
503 byte = reg_r(gspca_dev, 0x0060);
504 if (!(byte & 0x01))
505 break;
506 msleep(100);
507 }
508 byte = reg_r(gspca_dev, 0x0063);
509 if (byte != 0x17) {
510 err("Bad sensor reset %02x", byte);
511 /* continue? */
512 }
513
514 p = sensor_init;
515 while (*p != 0) {
516 val[1] = *p++;
517 val[3] = *p++;
518 if (*p == 0)
519 reg_w(gspca_dev, 0x3c80);
520 reg_w_buf(gspca_dev, val, sizeof val);
521 i = 4;
522 while (--i >= 0) {
523 msleep(15);
524 byte = reg_r(gspca_dev, 0x60);
525 if (!(byte & 0x01))
526 break;
527 }
528 }
529 msleep(15);
530 reg_w(gspca_dev, 0x3c80);
531 }
532
533 /* this function is called at probe time */
534 static int sd_config(struct gspca_dev *gspca_dev,
535 const struct usb_device_id *id)
536 {
537 struct sd *sd = (struct sd *) gspca_dev;
538 struct cam *cam;
539
540 cam = &gspca_dev->cam;
541
542 cam->cam_mode = vga_mode_t16;
543 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
544
545 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
546 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
547 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
548 sd->gamma = GAMMA_DEF;
549 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
550 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
551 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
552 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
553 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
554 return 0;
555 }
556
557 static void setbrightness(struct gspca_dev *gspca_dev)
558 {
559 struct sd *sd = (struct sd *) gspca_dev;
560 unsigned int brightness;
561 __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
562
563 brightness = sd->brightness;
564 if (brightness < 7) {
565 set6[1] = 0x26;
566 set6[3] = 0x70 - brightness * 0x10;
567 } else {
568 set6[3] = 0x00 + ((brightness - 7) * 0x10);
569 }
570
571 reg_w_buf(gspca_dev, set6, sizeof set6);
572 }
573
574 static void setcontrast(struct gspca_dev *gspca_dev)
575 {
576 struct sd *sd = (struct sd *) gspca_dev;
577 unsigned int contrast = sd->contrast;
578 __u16 reg_to_write;
579
580 if (contrast < 7)
581 reg_to_write = 0x8ea9 - contrast * 0x200;
582 else
583 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
584
585 reg_w(gspca_dev, reg_to_write);
586 }
587
588 static void setcolors(struct gspca_dev *gspca_dev)
589 {
590 struct sd *sd = (struct sd *) gspca_dev;
591 __u16 reg_to_write;
592
593 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
594 reg_w(gspca_dev, reg_to_write);
595 }
596
597 static void setgamma(struct gspca_dev *gspca_dev)
598 {
599 struct sd *sd = (struct sd *) gspca_dev;
600
601 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
602 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
603 }
604
605 static void setwhitebalance(struct gspca_dev *gspca_dev)
606 {
607 struct sd *sd = (struct sd *) gspca_dev;
608
609 __u8 white_balance[8] =
610 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
611
612 if (sd->whitebalance)
613 white_balance[7] = 0x3c;
614
615 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
616 }
617
618 static void setsharpness(struct gspca_dev *gspca_dev)
619 {
620 struct sd *sd = (struct sd *) gspca_dev;
621 __u16 reg_to_write;
622
623 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
624
625 reg_w(gspca_dev, reg_to_write);
626 }
627
628 /* this function is called at probe and resume time */
629 static int sd_init(struct gspca_dev *gspca_dev)
630 {
631 /* some of this registers are not really neded, because
632 * they are overriden by setbrigthness, setcontrast, etc,
633 * but wont hurt anyway, and can help someone with similar webcam
634 * to see the initial parameters.*/
635 struct sd *sd = (struct sd *) gspca_dev;
636 int i;
637 __u8 byte, test_byte;
638
639 static const __u8 read_indexs[] =
640 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
641 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
642 static const __u8 n1[] =
643 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
644 static const __u8 n2[] =
645 {0x08, 0x00};
646 static const __u8 n3[] =
647 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
648 static const __u8 n4[] =
649 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
650 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
651 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
652 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
653 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
654 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
655 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
656 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
657 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
658 static const __u8 nset9[4] =
659 { 0x0b, 0x04, 0x0a, 0x78 };
660 static const __u8 nset8[6] =
661 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
662
663 byte = reg_r(gspca_dev, 0x06);
664 test_byte = reg_r(gspca_dev, 0x07);
665 if (byte == 0x08 && test_byte == 0x07) {
666 PDEBUG(D_CONF, "sensor om6802");
667 sd->sensor = SENSOR_OM6802;
668 } else if (byte == 0x08 && test_byte == 0x01) {
669 PDEBUG(D_CONF, "sensor tas5130a");
670 sd->sensor = SENSOR_TAS5130A;
671 } else {
672 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
673 sd->sensor = SENSOR_TAS5130A;
674 }
675
676 reg_w_buf(gspca_dev, n1, sizeof n1);
677 test_byte = 0;
678 i = 5;
679 while (--i >= 0) {
680 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
681 test_byte = reg_r(gspca_dev, 0x0063);
682 msleep(100);
683 if (test_byte == 0x17)
684 break; /* OK */
685 }
686 if (i < 0) {
687 err("Bad sensor reset %02x", test_byte);
688 /* return -EIO; */
689 /*fixme: test - continue */
690 }
691 reg_w_buf(gspca_dev, n2, sizeof n2);
692
693 i = 0;
694 while (read_indexs[i] != 0x00) {
695 test_byte = reg_r(gspca_dev, read_indexs[i]);
696 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
697 test_byte);
698 i++;
699 }
700
701 reg_w_buf(gspca_dev, n3, sizeof n3);
702 reg_w_buf(gspca_dev, n4, sizeof n4);
703 reg_r(gspca_dev, 0x0080);
704 reg_w(gspca_dev, 0x2c80);
705
706 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
707 sizeof sensor_data[sd->sensor].data1);
708 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
709 sizeof sensor_data[sd->sensor].data3);
710 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
711 sizeof sensor_data[sd->sensor].data2);
712
713 reg_w(gspca_dev, 0x3880);
714 reg_w(gspca_dev, 0x3880);
715 reg_w(gspca_dev, 0x338e);
716
717 setbrightness(gspca_dev);
718 setcontrast(gspca_dev);
719 setgamma(gspca_dev);
720 setcolors(gspca_dev);
721 setsharpness(gspca_dev);
722 setwhitebalance(gspca_dev);
723
724 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
725 reg_w(gspca_dev, 0x2088);
726 reg_w(gspca_dev, 0x2089);
727
728 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
729 sizeof sensor_data[sd->sensor].data4);
730 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
731 sizeof sensor_data[sd->sensor].data5);
732 reg_w_buf(gspca_dev, nset8, sizeof nset8);
733 reg_w_buf(gspca_dev, nset9, sizeof nset9);
734
735 reg_w(gspca_dev, 0x2880);
736
737 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
738 sizeof sensor_data[sd->sensor].data1);
739 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
740 sizeof sensor_data[sd->sensor].data3);
741 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
742 sizeof sensor_data[sd->sensor].data2);
743
744 return 0;
745 }
746
747 static void setflip(struct gspca_dev *gspca_dev)
748 {
749 struct sd *sd = (struct sd *) gspca_dev;
750 __u8 flipcmd[8] =
751 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
752
753 if (sd->mirror)
754 flipcmd[3] = 0x01;
755
756 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
757 }
758
759 static void seteffect(struct gspca_dev *gspca_dev)
760 {
761 struct sd *sd = (struct sd *) gspca_dev;
762
763 reg_w_buf(gspca_dev, effects_table[sd->effect],
764 sizeof effects_table[0]);
765 if (sd->effect == 1 || sd->effect == 5) {
766 PDEBUG(D_CONF,
767 "This effect have been disabled for webcam \"safety\"");
768 return;
769 }
770
771 if (sd->effect == 1 || sd->effect == 4)
772 reg_w(gspca_dev, 0x4aa6);
773 else
774 reg_w(gspca_dev, 0xfaa6);
775 }
776
777 static void setlightfreq(struct gspca_dev *gspca_dev)
778 {
779 struct sd *sd = (struct sd *) gspca_dev;
780 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
781
782 if (sd->freq == 2) /* 60hz */
783 freq[1] = 0x00;
784
785 reg_w_buf(gspca_dev, freq, sizeof freq);
786 }
787
788 /* Is this really needed?
789 * i added some module parameters for test with some users */
790 static void poll_sensor(struct gspca_dev *gspca_dev)
791 {
792 struct sd *sd = (struct sd *) gspca_dev;
793 static const __u8 poll1[] =
794 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
795 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
796 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
797 0x60, 0x14};
798 static const __u8 poll2[] =
799 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
800 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
801 static const __u8 poll3[] =
802 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
803 static const __u8 poll4[] =
804 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
805 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
806 0xc2, 0x80, 0xc3, 0x10};
807
808 if (sd->sensor != SENSOR_TAS5130A) {
809 PDEBUG(D_STREAM, "[Sensor requires polling]");
810 reg_w_buf(gspca_dev, poll1, sizeof poll1);
811 reg_w_buf(gspca_dev, poll2, sizeof poll2);
812 reg_w_buf(gspca_dev, poll3, sizeof poll3);
813 reg_w_buf(gspca_dev, poll4, sizeof poll4);
814 }
815 }
816
817 static int sd_start(struct gspca_dev *gspca_dev)
818 {
819 struct sd *sd = (struct sd *) gspca_dev;
820 int i, mode;
821 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
822 static const __u8 t3[] =
823 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
824 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
825
826 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
827 switch (mode) {
828 case 1: /* 352x288 */
829 t2[1] = 0x40;
830 break;
831 case 2: /* 320x240 */
832 t2[1] = 0x10;
833 break;
834 case 3: /* 176x144 */
835 t2[1] = 0x50;
836 break;
837 case 4: /* 160x120 */
838 t2[1] = 0x20;
839 break;
840 default: /* 640x480 (0x00) */
841 break;
842 }
843
844 if (sd->sensor == SENSOR_TAS5130A) {
845 i = 0;
846 while (tas5130a_sensor_init[i][0] != 0) {
847 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
848 sizeof tas5130a_sensor_init[0]);
849 i++;
850 }
851 reg_w(gspca_dev, 0x3c80);
852 /* just in case and to keep sync with logs (for mine) */
853 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
854 sizeof tas5130a_sensor_init[0]);
855 reg_w(gspca_dev, 0x3c80);
856 } else {
857 om6802_sensor_init(gspca_dev);
858 }
859 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
860 sizeof sensor_data[sd->sensor].data4);
861 reg_r(gspca_dev, 0x0012);
862 reg_w_buf(gspca_dev, t2, sizeof t2);
863 reg_w_buf(gspca_dev, t3, sizeof t3);
864 reg_w(gspca_dev, 0x0013);
865 msleep(15);
866 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
867 sizeof sensor_data[sd->sensor].stream);
868 poll_sensor(gspca_dev);
869
870 /* restart on each start, just in case, sometimes regs goes wrong
871 * when using controls from app */
872 setbrightness(gspca_dev);
873 setcontrast(gspca_dev);
874 setcolors(gspca_dev);
875 return 0;
876 }
877
878 static void sd_stopN(struct gspca_dev *gspca_dev)
879 {
880 struct sd *sd = (struct sd *) gspca_dev;
881
882 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
883 sizeof sensor_data[sd->sensor].stream);
884 msleep(20);
885 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
886 sizeof sensor_data[sd->sensor].stream);
887 msleep(20);
888 reg_w(gspca_dev, 0x0309);
889 }
890
891 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
892 struct gspca_frame *frame, /* target */
893 __u8 *data, /* isoc packet */
894 int len) /* iso packet length */
895 {
896 static __u8 ffd9[] = { 0xff, 0xd9 };
897
898 if (data[0] == 0x5a) {
899 /* Control Packet, after this came the header again,
900 * but extra bytes came in the packet before this,
901 * sometimes an EOF arrives, sometimes not... */
902 return;
903 }
904 data += 2;
905 len -= 2;
906 if (data[0] == 0xff && data[1] == 0xd8) {
907 /* extra bytes....., could be processed too but would be
908 * a waste of time, right now leave the application and
909 * libjpeg do it for ourserlves.. */
910 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
911 ffd9, 2);
912 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
913 return;
914 }
915
916 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
917 /* Just in case, i have seen packets with the marker,
918 * other's do not include it... */
919 len -= 2;
920 }
921 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
922 }
923
924 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
925 {
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 sd->brightness = val;
929 if (gspca_dev->streaming)
930 setbrightness(gspca_dev);
931 return 0;
932 }
933
934 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
935 {
936 struct sd *sd = (struct sd *) gspca_dev;
937
938 *val = sd->brightness;
939 return *val;
940 }
941
942 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
943 {
944 struct sd *sd = (struct sd *) gspca_dev;
945
946 sd->whitebalance = val;
947 if (gspca_dev->streaming)
948 setwhitebalance(gspca_dev);
949 return 0;
950 }
951
952 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
953 {
954 struct sd *sd = (struct sd *) gspca_dev;
955
956 *val = sd->whitebalance;
957 return *val;
958 }
959
960 static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
961 {
962 struct sd *sd = (struct sd *) gspca_dev;
963
964 sd->mirror = val;
965 if (gspca_dev->streaming)
966 setflip(gspca_dev);
967 return 0;
968 }
969
970 static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
971 {
972 struct sd *sd = (struct sd *) gspca_dev;
973
974 *val = sd->mirror;
975 return *val;
976 }
977
978 static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
979 {
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 sd->effect = val;
983 if (gspca_dev->streaming)
984 seteffect(gspca_dev);
985 return 0;
986 }
987
988 static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
989 {
990 struct sd *sd = (struct sd *) gspca_dev;
991
992 *val = sd->effect;
993 return *val;
994 }
995
996 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
997 {
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 sd->contrast = val;
1001 if (gspca_dev->streaming)
1002 setcontrast(gspca_dev);
1003 return 0;
1004 }
1005
1006 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1007 {
1008 struct sd *sd = (struct sd *) gspca_dev;
1009
1010 *val = sd->contrast;
1011 return *val;
1012 }
1013
1014 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1015 {
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 sd->colors = val;
1019 if (gspca_dev->streaming)
1020 setcolors(gspca_dev);
1021 return 0;
1022 }
1023
1024 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1025 {
1026 struct sd *sd = (struct sd *) gspca_dev;
1027
1028 *val = sd->colors;
1029 return 0;
1030 }
1031
1032 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1033 {
1034 struct sd *sd = (struct sd *) gspca_dev;
1035
1036 sd->gamma = val;
1037 if (gspca_dev->streaming)
1038 setgamma(gspca_dev);
1039 return 0;
1040 }
1041
1042 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1043 {
1044 struct sd *sd = (struct sd *) gspca_dev;
1045
1046 *val = sd->gamma;
1047 return 0;
1048 }
1049
1050 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1051 {
1052 struct sd *sd = (struct sd *) gspca_dev;
1053
1054 sd->freq = val;
1055 if (gspca_dev->streaming)
1056 setlightfreq(gspca_dev);
1057 return 0;
1058 }
1059
1060 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1061 {
1062 struct sd *sd = (struct sd *) gspca_dev;
1063
1064 *val = sd->freq;
1065 return 0;
1066 }
1067
1068 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1069 {
1070 struct sd *sd = (struct sd *) gspca_dev;
1071
1072 sd->sharpness = val;
1073 if (gspca_dev->streaming)
1074 setsharpness(gspca_dev);
1075 return 0;
1076 }
1077
1078 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1079 {
1080 struct sd *sd = (struct sd *) gspca_dev;
1081
1082 *val = sd->sharpness;
1083 return 0;
1084 }
1085
1086 /* Low Light set here......*/
1087 static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1088 {
1089 struct sd *sd = (struct sd *) gspca_dev;
1090
1091 sd->autogain = val;
1092 if (val != 0)
1093 reg_w(gspca_dev, 0xf48e);
1094 else
1095 reg_w(gspca_dev, 0xb48e);
1096 return 0;
1097 }
1098
1099 static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1100 {
1101 struct sd *sd = (struct sd *) gspca_dev;
1102
1103 *val = sd->autogain;
1104 return 0;
1105 }
1106
1107 static int sd_querymenu(struct gspca_dev *gspca_dev,
1108 struct v4l2_querymenu *menu)
1109 {
1110 switch (menu->id) {
1111 case V4L2_CID_POWER_LINE_FREQUENCY:
1112 switch (menu->index) {
1113 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1114 strcpy((char *) menu->name, "50 Hz");
1115 return 0;
1116 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1117 strcpy((char *) menu->name, "60 Hz");
1118 return 0;
1119 }
1120 break;
1121 case V4L2_CID_EFFECTS:
1122 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1123 strncpy((char *) menu->name,
1124 effects_control[menu->index], 32);
1125 return 0;
1126 }
1127 break;
1128 }
1129 return -EINVAL;
1130 }
1131
1132 /* sub-driver description */
1133 static const struct sd_desc sd_desc = {
1134 .name = MODULE_NAME,
1135 .ctrls = sd_ctrls,
1136 .nctrls = ARRAY_SIZE(sd_ctrls),
1137 .config = sd_config,
1138 .init = sd_init,
1139 .start = sd_start,
1140 .stopN = sd_stopN,
1141 .pkt_scan = sd_pkt_scan,
1142 .querymenu = sd_querymenu,
1143 };
1144
1145 /* -- module initialisation -- */
1146 static const __devinitdata struct usb_device_id device_table[] = {
1147 {USB_DEVICE(0x17a1, 0x0128)},
1148 {}
1149 };
1150 MODULE_DEVICE_TABLE(usb, device_table);
1151
1152 /* -- device connect -- */
1153 static int sd_probe(struct usb_interface *intf,
1154 const struct usb_device_id *id)
1155 {
1156 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1157 THIS_MODULE);
1158 }
1159
1160 static struct usb_driver sd_driver = {
1161 .name = MODULE_NAME,
1162 .id_table = device_table,
1163 .probe = sd_probe,
1164 .disconnect = gspca_disconnect,
1165 #ifdef CONFIG_PM
1166 .suspend = gspca_suspend,
1167 .resume = gspca_resume,
1168 #endif
1169 };
1170
1171 /* -- module insert / remove -- */
1172 static int __init sd_mod_init(void)
1173 {
1174 if (usb_register(&sd_driver) < 0)
1175 return -1;
1176 PDEBUG(D_PROBE, "registered");
1177 return 0;
1178 }
1179 static void __exit sd_mod_exit(void)
1180 {
1181 usb_deregister(&sd_driver);
1182 PDEBUG(D_PROBE, "deregistered");
1183 }
1184
1185 module_init(sd_mod_init);
1186 module_exit(sd_mod_exit);