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