1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#define MODULE_NAME "t613"
28
29#include <linux/input.h>
30#include <linux/slab.h>
31#include "gspca.h"
32
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev;
39 struct v4l2_ctrl *freq;
40 struct {
41 struct v4l2_ctrl *awb;
42 struct v4l2_ctrl *gain;
43 struct v4l2_ctrl *red_balance;
44 struct v4l2_ctrl *blue_balance;
45 };
46
47 u8 sensor;
48 u8 button_pressed;
49};
50enum sensors {
51 SENSOR_OM6802,
52 SENSOR_OTHER,
53 SENSOR_TAS5130A,
54 SENSOR_LT168G,
55};
56
57static const struct v4l2_pix_format vga_mode_t16[] = {
58 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
59 .bytesperline = 160,
60 .sizeimage = 160 * 120 * 4 / 8 + 590,
61 .colorspace = V4L2_COLORSPACE_JPEG,
62 .priv = 4},
63#if 0
64 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
65 .bytesperline = 176,
66 .sizeimage = 176 * 144 * 3 / 8 + 590,
67 .colorspace = V4L2_COLORSPACE_JPEG,
68 .priv = 3},
69#endif
70 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
71 .bytesperline = 320,
72 .sizeimage = 320 * 240 * 3 / 8 + 590,
73 .colorspace = V4L2_COLORSPACE_JPEG,
74 .priv = 2},
75#if 0
76 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
77 .bytesperline = 352,
78 .sizeimage = 352 * 288 * 3 / 8 + 590,
79 .colorspace = V4L2_COLORSPACE_JPEG,
80 .priv = 1},
81#endif
82 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
83 .bytesperline = 640,
84 .sizeimage = 640 * 480 * 3 / 8 + 590,
85 .colorspace = V4L2_COLORSPACE_JPEG,
86 .priv = 0},
87};
88
89
90struct additional_sensor_data {
91 const u8 n3[6];
92 const u8 *n4, n4sz;
93 const u8 reg80, reg8e;
94 const u8 nset8[6];
95 const u8 data1[10];
96 const u8 data2[9];
97 const u8 data3[9];
98 const u8 data5[6];
99 const u8 stream[4];
100};
101
102static const u8 n4_om6802[] = {
103 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
104 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
105 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
106 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
107 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
108 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
109 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
110 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
111 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
112};
113static const u8 n4_other[] = {
114 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
115 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
116 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
117 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
118 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
119 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
120 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
121 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
122};
123static const u8 n4_tas5130a[] = {
124 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
125 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
126 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
127 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
128 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
129 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
130 0xc6, 0xda
131};
132static const u8 n4_lt168g[] = {
133 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
134 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
135 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
136 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
137 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
138 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
139 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
140 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
141 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
142};
143
144static const struct additional_sensor_data sensor_data[] = {
145[SENSOR_OM6802] = {
146 .n3 =
147 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
148 .n4 = n4_om6802,
149 .n4sz = sizeof n4_om6802,
150 .reg80 = 0x3c,
151 .reg8e = 0x33,
152 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
153 .data1 =
154 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
155 0xb3, 0xfc},
156 .data2 =
157 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
158 0xff},
159 .data3 =
160 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
161 0xff},
162 .data5 =
163 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
164 .stream =
165 {0x0b, 0x04, 0x0a, 0x78},
166 },
167[SENSOR_OTHER] = {
168 .n3 =
169 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
170 .n4 = n4_other,
171 .n4sz = sizeof n4_other,
172 .reg80 = 0xac,
173 .reg8e = 0xb8,
174 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
175 .data1 =
176 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
177 0xe8, 0xfc},
178 .data2 =
179 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
180 0xd9},
181 .data3 =
182 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
183 0xd9},
184 .data5 =
185 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
186 .stream =
187 {0x0b, 0x04, 0x0a, 0x00},
188 },
189[SENSOR_TAS5130A] = {
190 .n3 =
191 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
192 .n4 = n4_tas5130a,
193 .n4sz = sizeof n4_tas5130a,
194 .reg80 = 0x3c,
195 .reg8e = 0xb4,
196 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
197 .data1 =
198 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
199 0xc8, 0xfc},
200 .data2 =
201 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
202 0xe0},
203 .data3 =
204 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
205 0xe0},
206 .data5 =
207 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
208 .stream =
209 {0x0b, 0x04, 0x0a, 0x40},
210 },
211[SENSOR_LT168G] = {
212 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
213 .n4 = n4_lt168g,
214 .n4sz = sizeof n4_lt168g,
215 .reg80 = 0x7c,
216 .reg8e = 0xb3,
217 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
218 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
219 0xb0, 0xf4},
220 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
221 0xff},
222 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
223 0xff},
224 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
225 .stream = {0x0b, 0x04, 0x0a, 0x28},
226 },
227};
228
229#define MAX_EFFECTS 7
230static const u8 effects_table[MAX_EFFECTS][6] = {
231 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},
232 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},
233 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},
234 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},
235 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},
236 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},
237 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},
238};
239
240#define GAMMA_MAX (15)
241static const u8 gamma_table[GAMMA_MAX+1][17] = {
242
243 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,
244 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
245 0xff},
246 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,
247 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
248 0xff},
249 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,
250 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
251 0xff},
252 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,
253 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
254 0xff},
255 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,
256 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
257 0xff},
258 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,
259 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
260 0xff},
261 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,
262 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
263 0xff},
264 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
265 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
266 0xff},
267 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,
268 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
269 0xff},
270 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,
271 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
272 0xff},
273 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,
274 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
275 0xff},
276 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,
277 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
278 0xff},
279 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,
280 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
281 0xff},
282 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,
283 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
284 0xff},
285 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,
286 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
287 0xff},
288 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,
289 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
290 0xff}
291};
292
293static const u8 tas5130a_sensor_init[][8] = {
294 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
295 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
296 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
297};
298
299static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
300
301
302static u8 reg_r(struct gspca_dev *gspca_dev,
303 u16 index)
304{
305 usb_control_msg(gspca_dev->dev,
306 usb_rcvctrlpipe(gspca_dev->dev, 0),
307 0,
308 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
309 0,
310 index,
311 gspca_dev->usb_buf, 1, 500);
312 return gspca_dev->usb_buf[0];
313}
314
315static void reg_w(struct gspca_dev *gspca_dev,
316 u16 index)
317{
318 usb_control_msg(gspca_dev->dev,
319 usb_sndctrlpipe(gspca_dev->dev, 0),
320 0,
321 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
322 0, index,
323 NULL, 0, 500);
324}
325
326static void reg_w_buf(struct gspca_dev *gspca_dev,
327 const u8 *buffer, u16 len)
328{
329 if (len <= USB_BUF_SZ) {
330 memcpy(gspca_dev->usb_buf, buffer, len);
331 usb_control_msg(gspca_dev->dev,
332 usb_sndctrlpipe(gspca_dev->dev, 0),
333 0,
334 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
335 0x01, 0,
336 gspca_dev->usb_buf, len, 500);
337 } else {
338 u8 *tmpbuf;
339
340 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
341 if (!tmpbuf) {
342 pr_err("Out of memory\n");
343 return;
344 }
345 usb_control_msg(gspca_dev->dev,
346 usb_sndctrlpipe(gspca_dev->dev, 0),
347 0,
348 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
349 0x01, 0,
350 tmpbuf, len, 500);
351 kfree(tmpbuf);
352 }
353}
354
355
356static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
357 u8 reg,
358 const u8 *buffer, u16 len)
359{
360 int i;
361 u8 *p, *tmpbuf;
362
363 if (len * 2 <= USB_BUF_SZ) {
364 p = tmpbuf = gspca_dev->usb_buf;
365 } else {
366 p = tmpbuf = kmalloc_array(len, 2, GFP_KERNEL);
367 if (!tmpbuf) {
368 pr_err("Out of memory\n");
369 return;
370 }
371 }
372 i = len;
373 while (--i >= 0) {
374 *p++ = reg++;
375 *p++ = *buffer++;
376 }
377 usb_control_msg(gspca_dev->dev,
378 usb_sndctrlpipe(gspca_dev->dev, 0),
379 0,
380 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
381 0x01, 0,
382 tmpbuf, len * 2, 500);
383 if (len * 2 > USB_BUF_SZ)
384 kfree(tmpbuf);
385}
386
387static void om6802_sensor_init(struct gspca_dev *gspca_dev)
388{
389 int i;
390 const u8 *p;
391 u8 byte;
392 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
393 static const u8 sensor_init[] = {
394 0xdf, 0x6d,
395 0xdd, 0x18,
396 0x5a, 0xe0,
397 0x5c, 0x07,
398 0x5d, 0xb0,
399 0x5e, 0x1e,
400 0x60, 0x71,
401 0xef, 0x00,
402 0xe9, 0x00,
403 0xea, 0x00,
404 0x90, 0x24,
405 0x91, 0xb2,
406 0x82, 0x32,
407 0xfd, 0x41,
408 0x00
409 };
410
411 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
412 msleep(100);
413 i = 4;
414 while (--i > 0) {
415 byte = reg_r(gspca_dev, 0x0060);
416 if (!(byte & 0x01))
417 break;
418 msleep(100);
419 }
420 byte = reg_r(gspca_dev, 0x0063);
421 if (byte != 0x17) {
422 pr_err("Bad sensor reset %02x\n", byte);
423
424 }
425
426 p = sensor_init;
427 while (*p != 0) {
428 val[1] = *p++;
429 val[3] = *p++;
430 if (*p == 0)
431 reg_w(gspca_dev, 0x3c80);
432 reg_w_buf(gspca_dev, val, sizeof val);
433 i = 4;
434 while (--i >= 0) {
435 msleep(15);
436 byte = reg_r(gspca_dev, 0x60);
437 if (!(byte & 0x01))
438 break;
439 }
440 }
441 msleep(15);
442 reg_w(gspca_dev, 0x3c80);
443}
444
445
446static int sd_config(struct gspca_dev *gspca_dev,
447 const struct usb_device_id *id)
448{
449 struct cam *cam = &gspca_dev->cam;
450
451 cam->cam_mode = vga_mode_t16;
452 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
453
454 return 0;
455}
456
457static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
458{
459 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
460
461 if (brightness < 7) {
462 set6[1] = 0x26;
463 set6[3] = 0x70 - brightness * 0x10;
464 } else {
465 set6[3] = 0x00 + ((brightness - 7) * 0x10);
466 }
467
468 reg_w_buf(gspca_dev, set6, sizeof set6);
469}
470
471static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
472{
473 u16 reg_to_write;
474
475 if (contrast < 7)
476 reg_to_write = 0x8ea9 - contrast * 0x200;
477 else
478 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
479
480 reg_w(gspca_dev, reg_to_write);
481}
482
483static void setcolors(struct gspca_dev *gspca_dev, s32 val)
484{
485 u16 reg_to_write;
486
487 reg_to_write = 0x80bb + val * 0x100;
488 reg_w(gspca_dev, reg_to_write);
489}
490
491static void setgamma(struct gspca_dev *gspca_dev, s32 val)
492{
493 gspca_dbg(gspca_dev, D_CONF, "Gamma: %d\n", val);
494 reg_w_ixbuf(gspca_dev, 0x90,
495 gamma_table[val], sizeof gamma_table[0]);
496}
497
498static void setawb_n_RGB(struct gspca_dev *gspca_dev)
499{
500 struct sd *sd = (struct sd *) gspca_dev;
501 u8 all_gain_reg[8] = {
502 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
503 s32 red_gain, blue_gain, green_gain;
504
505 green_gain = sd->gain->val;
506
507 red_gain = green_gain + sd->red_balance->val;
508 if (red_gain > 0x40)
509 red_gain = 0x40;
510 else if (red_gain < 0x10)
511 red_gain = 0x10;
512
513 blue_gain = green_gain + sd->blue_balance->val;
514 if (blue_gain > 0x40)
515 blue_gain = 0x40;
516 else if (blue_gain < 0x10)
517 blue_gain = 0x10;
518
519 all_gain_reg[1] = red_gain;
520 all_gain_reg[3] = blue_gain;
521 all_gain_reg[5] = green_gain;
522 all_gain_reg[7] = sensor_data[sd->sensor].reg80;
523 if (!sd->awb->val)
524 all_gain_reg[7] &= ~0x04;
525
526 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
527}
528
529static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
530{
531 u16 reg_to_write;
532
533 reg_to_write = 0x0aa6 + 0x1000 * val;
534
535 reg_w(gspca_dev, reg_to_write);
536}
537
538static void setfreq(struct gspca_dev *gspca_dev, s32 val)
539{
540 struct sd *sd = (struct sd *) gspca_dev;
541 u8 reg66;
542 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
543
544 switch (sd->sensor) {
545 case SENSOR_LT168G:
546 if (val != 0)
547 freq[3] = 0xa8;
548 reg66 = 0x41;
549 break;
550 case SENSOR_OM6802:
551 reg66 = 0xca;
552 break;
553 default:
554 reg66 = 0x40;
555 break;
556 }
557 switch (val) {
558 case 0:
559 freq[3] = 0xf0;
560 break;
561 case 2:
562 reg66 &= ~0x40;
563 break;
564 }
565 freq[1] = reg66;
566
567 reg_w_buf(gspca_dev, freq, sizeof freq);
568}
569
570
571static int sd_init(struct gspca_dev *gspca_dev)
572{
573
574
575
576
577 struct sd *sd = (struct sd *) gspca_dev;
578 const struct additional_sensor_data *sensor;
579 int i;
580 u16 sensor_id;
581 u8 test_byte = 0;
582
583 static const u8 read_indexs[] =
584 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
585 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
586 static const u8 n1[] =
587 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
588 static const u8 n2[] =
589 {0x08, 0x00};
590
591 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
592 | reg_r(gspca_dev, 0x07);
593 switch (sensor_id & 0xff0f) {
594 case 0x0801:
595 gspca_dbg(gspca_dev, D_PROBE, "sensor tas5130a\n");
596 sd->sensor = SENSOR_TAS5130A;
597 break;
598 case 0x0802:
599 gspca_dbg(gspca_dev, D_PROBE, "sensor lt168g\n");
600 sd->sensor = SENSOR_LT168G;
601 break;
602 case 0x0803:
603 gspca_dbg(gspca_dev, D_PROBE, "sensor 'other'\n");
604 sd->sensor = SENSOR_OTHER;
605 break;
606 case 0x0807:
607 gspca_dbg(gspca_dev, D_PROBE, "sensor om6802\n");
608 sd->sensor = SENSOR_OM6802;
609 break;
610 default:
611 pr_err("unknown sensor %04x\n", sensor_id);
612 return -EINVAL;
613 }
614
615 if (sd->sensor == SENSOR_OM6802) {
616 reg_w_buf(gspca_dev, n1, sizeof n1);
617 i = 5;
618 while (--i >= 0) {
619 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
620 test_byte = reg_r(gspca_dev, 0x0063);
621 msleep(100);
622 if (test_byte == 0x17)
623 break;
624 }
625 if (i < 0) {
626 pr_err("Bad sensor reset %02x\n", test_byte);
627 return -EIO;
628 }
629 reg_w_buf(gspca_dev, n2, sizeof n2);
630 }
631
632 i = 0;
633 while (read_indexs[i] != 0x00) {
634 test_byte = reg_r(gspca_dev, read_indexs[i]);
635 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n",
636 read_indexs[i], test_byte);
637 i++;
638 }
639
640 sensor = &sensor_data[sd->sensor];
641 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
642 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
643
644 if (sd->sensor == SENSOR_LT168G) {
645 test_byte = reg_r(gspca_dev, 0x80);
646 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
647 test_byte);
648 reg_w(gspca_dev, 0x6c80);
649 }
650
651 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
652 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
653 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
654
655 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
656 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
657 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
658 reg_w(gspca_dev, (0x20 << 8) + 0x87);
659 reg_w(gspca_dev, (0x20 << 8) + 0x88);
660 reg_w(gspca_dev, (0x20 << 8) + 0x89);
661
662 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
663 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
664 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
665
666 if (sd->sensor == SENSOR_LT168G) {
667 test_byte = reg_r(gspca_dev, 0x80);
668 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
669 test_byte);
670 reg_w(gspca_dev, 0x6c80);
671 }
672
673 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
674 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
675 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
676
677 return 0;
678}
679
680static void setmirror(struct gspca_dev *gspca_dev, s32 val)
681{
682 u8 hflipcmd[8] =
683 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
684
685 if (val)
686 hflipcmd[3] = 0x01;
687
688 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
689}
690
691static void seteffect(struct gspca_dev *gspca_dev, s32 val)
692{
693 int idx = 0;
694
695 switch (val) {
696 case V4L2_COLORFX_NONE:
697 break;
698 case V4L2_COLORFX_BW:
699 idx = 2;
700 break;
701 case V4L2_COLORFX_SEPIA:
702 idx = 3;
703 break;
704 case V4L2_COLORFX_SKETCH:
705 idx = 4;
706 break;
707 case V4L2_COLORFX_NEGATIVE:
708 idx = 6;
709 break;
710 default:
711 break;
712 }
713
714 reg_w_buf(gspca_dev, effects_table[idx],
715 sizeof effects_table[0]);
716
717 if (val == V4L2_COLORFX_SKETCH)
718 reg_w(gspca_dev, 0x4aa6);
719 else
720 reg_w(gspca_dev, 0xfaa6);
721}
722
723
724
725static void poll_sensor(struct gspca_dev *gspca_dev)
726{
727 static const u8 poll1[] =
728 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
729 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
730 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
731 0x60, 0x14};
732 static const u8 poll2[] =
733 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
734 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
735 static const u8 noise03[] =
736 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
737 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
738 0xc2, 0x80, 0xc3, 0x10};
739
740 gspca_dbg(gspca_dev, D_STREAM, "[Sensor requires polling]\n");
741 reg_w_buf(gspca_dev, poll1, sizeof poll1);
742 reg_w_buf(gspca_dev, poll2, sizeof poll2);
743 reg_w_buf(gspca_dev, noise03, sizeof noise03);
744}
745
746static int sd_start(struct gspca_dev *gspca_dev)
747{
748 struct sd *sd = (struct sd *) gspca_dev;
749 const struct additional_sensor_data *sensor;
750 int i, mode;
751 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
752 static const u8 t3[] =
753 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
754
755 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
756 switch (mode) {
757 case 0:
758 break;
759 case 1:
760 t2[1] = 0x40;
761 break;
762 case 2:
763 t2[1] = 0x10;
764 break;
765 case 3:
766 t2[1] = 0x50;
767 break;
768 default:
769
770 t2[1] = 0x20;
771 break;
772 }
773
774 switch (sd->sensor) {
775 case SENSOR_OM6802:
776 om6802_sensor_init(gspca_dev);
777 break;
778 case SENSOR_TAS5130A:
779 i = 0;
780 for (;;) {
781 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
782 sizeof tas5130a_sensor_init[0]);
783 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
784 break;
785 i++;
786 }
787 reg_w(gspca_dev, 0x3c80);
788
789 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
790 sizeof tas5130a_sensor_init[0]);
791 reg_w(gspca_dev, 0x3c80);
792 break;
793 }
794 sensor = &sensor_data[sd->sensor];
795 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
796 reg_r(gspca_dev, 0x0012);
797 reg_w_buf(gspca_dev, t2, sizeof t2);
798 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
799 reg_w(gspca_dev, 0x0013);
800 msleep(15);
801 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
802 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
803
804 if (sd->sensor == SENSOR_OM6802)
805 poll_sensor(gspca_dev);
806
807 return 0;
808}
809
810static void sd_stopN(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813
814 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
815 sizeof sensor_data[sd->sensor].stream);
816 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
817 sizeof sensor_data[sd->sensor].stream);
818 if (sd->sensor == SENSOR_OM6802) {
819 msleep(20);
820 reg_w(gspca_dev, 0x0309);
821 }
822#if IS_ENABLED(CONFIG_INPUT)
823
824 if (sd->button_pressed) {
825 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
826 input_sync(gspca_dev->input_dev);
827 sd->button_pressed = 0;
828 }
829#endif
830}
831
832static void sd_pkt_scan(struct gspca_dev *gspca_dev,
833 u8 *data,
834 int len)
835{
836 struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
837 int pkt_type;
838
839 if (data[0] == 0x5a) {
840#if IS_ENABLED(CONFIG_INPUT)
841 if (len > 20) {
842 u8 state = (data[20] & 0x80) ? 1 : 0;
843 if (sd->button_pressed != state) {
844 input_report_key(gspca_dev->input_dev,
845 KEY_CAMERA, state);
846 input_sync(gspca_dev->input_dev);
847 sd->button_pressed = state;
848 }
849 }
850#endif
851
852
853
854 return;
855 }
856 data += 2;
857 len -= 2;
858 if (data[0] == 0xff && data[1] == 0xd8)
859 pkt_type = FIRST_PACKET;
860 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
861 pkt_type = LAST_PACKET;
862 else
863 pkt_type = INTER_PACKET;
864 gspca_frame_add(gspca_dev, pkt_type, data, len);
865}
866
867static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
868{
869 struct gspca_dev *gspca_dev =
870 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
871 struct sd *sd = (struct sd *)gspca_dev;
872 s32 red_gain, blue_gain, green_gain;
873
874 gspca_dev->usb_err = 0;
875
876 switch (ctrl->id) {
877 case V4L2_CID_AUTO_WHITE_BALANCE:
878 red_gain = reg_r(gspca_dev, 0x0087);
879 if (red_gain > 0x40)
880 red_gain = 0x40;
881 else if (red_gain < 0x10)
882 red_gain = 0x10;
883
884 blue_gain = reg_r(gspca_dev, 0x0088);
885 if (blue_gain > 0x40)
886 blue_gain = 0x40;
887 else if (blue_gain < 0x10)
888 blue_gain = 0x10;
889
890 green_gain = reg_r(gspca_dev, 0x0089);
891 if (green_gain > 0x40)
892 green_gain = 0x40;
893 else if (green_gain < 0x10)
894 green_gain = 0x10;
895
896 sd->gain->val = green_gain;
897 sd->red_balance->val = red_gain - green_gain;
898 sd->blue_balance->val = blue_gain - green_gain;
899 break;
900 }
901 return 0;
902}
903
904static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
905{
906 struct gspca_dev *gspca_dev =
907 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
908
909 gspca_dev->usb_err = 0;
910
911 if (!gspca_dev->streaming)
912 return 0;
913
914 switch (ctrl->id) {
915 case V4L2_CID_BRIGHTNESS:
916 setbrightness(gspca_dev, ctrl->val);
917 break;
918 case V4L2_CID_CONTRAST:
919 setcontrast(gspca_dev, ctrl->val);
920 break;
921 case V4L2_CID_SATURATION:
922 setcolors(gspca_dev, ctrl->val);
923 break;
924 case V4L2_CID_GAMMA:
925 setgamma(gspca_dev, ctrl->val);
926 break;
927 case V4L2_CID_HFLIP:
928 setmirror(gspca_dev, ctrl->val);
929 break;
930 case V4L2_CID_SHARPNESS:
931 setsharpness(gspca_dev, ctrl->val);
932 break;
933 case V4L2_CID_POWER_LINE_FREQUENCY:
934 setfreq(gspca_dev, ctrl->val);
935 break;
936 case V4L2_CID_BACKLIGHT_COMPENSATION:
937 reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
938 break;
939 case V4L2_CID_AUTO_WHITE_BALANCE:
940 setawb_n_RGB(gspca_dev);
941 break;
942 case V4L2_CID_COLORFX:
943 seteffect(gspca_dev, ctrl->val);
944 break;
945 }
946 return gspca_dev->usb_err;
947}
948
949static const struct v4l2_ctrl_ops sd_ctrl_ops = {
950 .g_volatile_ctrl = sd_g_volatile_ctrl,
951 .s_ctrl = sd_s_ctrl,
952};
953
954static int sd_init_controls(struct gspca_dev *gspca_dev)
955{
956 struct sd *sd = (struct sd *)gspca_dev;
957 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
958
959 gspca_dev->vdev.ctrl_handler = hdl;
960 v4l2_ctrl_handler_init(hdl, 12);
961 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
962 V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
963 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
964 V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
965 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
966 V4L2_CID_SATURATION, 0, 0xf, 1, 5);
967 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
968 V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
969
970
971 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
972 V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
973 if (sd->sensor == SENSOR_TAS5130A)
974 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
975 V4L2_CID_HFLIP, 0, 1, 1, 0);
976 sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
977 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
978 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
979 V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
980 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
981 V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
982 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
983 V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
984 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
985 V4L2_CID_SHARPNESS, 0, 15, 1, 6);
986 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
987 V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
988 ~((1 << V4L2_COLORFX_NONE) |
989 (1 << V4L2_COLORFX_BW) |
990 (1 << V4L2_COLORFX_SEPIA) |
991 (1 << V4L2_COLORFX_SKETCH) |
992 (1 << V4L2_COLORFX_NEGATIVE)),
993 V4L2_COLORFX_NONE);
994 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
995 V4L2_CID_POWER_LINE_FREQUENCY,
996 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
997 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
998
999 if (hdl->error) {
1000 pr_err("Could not initialize controls\n");
1001 return hdl->error;
1002 }
1003
1004 v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
1005
1006 return 0;
1007}
1008
1009
1010static const struct sd_desc sd_desc = {
1011 .name = MODULE_NAME,
1012 .config = sd_config,
1013 .init = sd_init,
1014 .init_controls = sd_init_controls,
1015 .start = sd_start,
1016 .stopN = sd_stopN,
1017 .pkt_scan = sd_pkt_scan,
1018#if IS_ENABLED(CONFIG_INPUT)
1019 .other_input = 1,
1020#endif
1021};
1022
1023
1024static const struct usb_device_id device_table[] = {
1025 {USB_DEVICE(0x17a1, 0x0128)},
1026 {}
1027};
1028MODULE_DEVICE_TABLE(usb, device_table);
1029
1030
1031static int sd_probe(struct usb_interface *intf,
1032 const struct usb_device_id *id)
1033{
1034 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1035 THIS_MODULE);
1036}
1037
1038static struct usb_driver sd_driver = {
1039 .name = MODULE_NAME,
1040 .id_table = device_table,
1041 .probe = sd_probe,
1042 .disconnect = gspca_disconnect,
1043#ifdef CONFIG_PM
1044 .suspend = gspca_suspend,
1045 .resume = gspca_resume,
1046 .reset_resume = gspca_resume,
1047#endif
1048};
1049
1050module_usb_driver(sd_driver);
1051