WIP FPC-III support
[linux/fpc-iii.git] / drivers / media / usb / gspca / t613.c
blob33b37ccf109055cbcb1573e568808fbc6266463b
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * T613 subdriver
5 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
7 *Notes: * t613 + tas5130A
8 * * Focus to light do not balance well as in win.
9 * Quality in win is not good, but its kinda better.
10 * * Fix some "extraneous bytes", most of apps will show the image anyway
11 * * Gamma table, is there, but its really doing something?
12 * * 7~8 Fps, its ok, max on win its 10.
13 * Costantino Leandro
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #define MODULE_NAME "t613"
20 #include <linux/input.h>
21 #include <linux/slab.h>
22 #include "gspca.h"
24 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
25 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
26 MODULE_LICENSE("GPL");
28 struct sd {
29 struct gspca_dev gspca_dev; /* !! must be the first item */
30 struct v4l2_ctrl *freq;
31 struct { /* awb / color gains control cluster */
32 struct v4l2_ctrl *awb;
33 struct v4l2_ctrl *gain;
34 struct v4l2_ctrl *red_balance;
35 struct v4l2_ctrl *blue_balance;
38 u8 sensor;
39 u8 button_pressed;
41 enum sensors {
42 SENSOR_OM6802,
43 SENSOR_OTHER,
44 SENSOR_TAS5130A,
45 SENSOR_LT168G, /* must verify if this is the actual model */
48 static const struct v4l2_pix_format vga_mode_t16[] = {
49 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
50 .bytesperline = 160,
51 .sizeimage = 160 * 120 * 4 / 8 + 590,
52 .colorspace = V4L2_COLORSPACE_JPEG,
53 .priv = 4},
54 #if 0 /* HDG: broken with my test cam, so lets disable it */
55 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
56 .bytesperline = 176,
57 .sizeimage = 176 * 144 * 3 / 8 + 590,
58 .colorspace = V4L2_COLORSPACE_JPEG,
59 .priv = 3},
60 #endif
61 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
62 .bytesperline = 320,
63 .sizeimage = 320 * 240 * 3 / 8 + 590,
64 .colorspace = V4L2_COLORSPACE_JPEG,
65 .priv = 2},
66 #if 0 /* HDG: broken with my test cam, so lets disable it */
67 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
68 .bytesperline = 352,
69 .sizeimage = 352 * 288 * 3 / 8 + 590,
70 .colorspace = V4L2_COLORSPACE_JPEG,
71 .priv = 1},
72 #endif
73 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
74 .bytesperline = 640,
75 .sizeimage = 640 * 480 * 3 / 8 + 590,
76 .colorspace = V4L2_COLORSPACE_JPEG,
77 .priv = 0},
80 /* sensor specific data */
81 struct additional_sensor_data {
82 const u8 n3[6];
83 const u8 *n4, n4sz;
84 const u8 reg80, reg8e;
85 const u8 nset8[6];
86 const u8 data1[10];
87 const u8 data2[9];
88 const u8 data3[9];
89 const u8 data5[6];
90 const u8 stream[4];
93 static const u8 n4_om6802[] = {
94 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
95 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
96 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
97 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
98 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
99 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
100 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
101 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
102 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
104 static const u8 n4_other[] = {
105 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
106 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
107 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
108 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
109 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
110 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
111 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
112 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
114 static const u8 n4_tas5130a[] = {
115 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
116 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
117 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
118 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
119 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
120 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
121 0xc6, 0xda
123 static const u8 n4_lt168g[] = {
124 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
125 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
126 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
127 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
128 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
129 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
130 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
131 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
132 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
135 static const struct additional_sensor_data sensor_data[] = {
136 [SENSOR_OM6802] = {
137 .n3 =
138 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
139 .n4 = n4_om6802,
140 .n4sz = sizeof n4_om6802,
141 .reg80 = 0x3c,
142 .reg8e = 0x33,
143 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
144 .data1 =
145 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
146 0xb3, 0xfc},
147 .data2 =
148 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
149 0xff},
150 .data3 =
151 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
152 0xff},
153 .data5 = /* this could be removed later */
154 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
155 .stream =
156 {0x0b, 0x04, 0x0a, 0x78},
158 [SENSOR_OTHER] = {
159 .n3 =
160 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
161 .n4 = n4_other,
162 .n4sz = sizeof n4_other,
163 .reg80 = 0xac,
164 .reg8e = 0xb8,
165 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
166 .data1 =
167 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
168 0xe8, 0xfc},
169 .data2 =
170 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
171 0xd9},
172 .data3 =
173 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
174 0xd9},
175 .data5 =
176 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
177 .stream =
178 {0x0b, 0x04, 0x0a, 0x00},
180 [SENSOR_TAS5130A] = {
181 .n3 =
182 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
183 .n4 = n4_tas5130a,
184 .n4sz = sizeof n4_tas5130a,
185 .reg80 = 0x3c,
186 .reg8e = 0xb4,
187 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
188 .data1 =
189 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
190 0xc8, 0xfc},
191 .data2 =
192 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
193 0xe0},
194 .data3 =
195 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
196 0xe0},
197 .data5 =
198 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
199 .stream =
200 {0x0b, 0x04, 0x0a, 0x40},
202 [SENSOR_LT168G] = {
203 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
204 .n4 = n4_lt168g,
205 .n4sz = sizeof n4_lt168g,
206 .reg80 = 0x7c,
207 .reg8e = 0xb3,
208 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
209 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
210 0xb0, 0xf4},
211 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
212 0xff},
213 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
214 0xff},
215 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
216 .stream = {0x0b, 0x04, 0x0a, 0x28},
220 #define MAX_EFFECTS 7
221 static const u8 effects_table[MAX_EFFECTS][6] = {
222 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
223 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
224 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
225 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
226 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
227 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
228 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
231 #define GAMMA_MAX (15)
232 static const u8 gamma_table[GAMMA_MAX+1][17] = {
233 /* gamma table from cam1690.ini */
234 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
235 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
236 0xff},
237 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
238 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
239 0xff},
240 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
241 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
242 0xff},
243 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
244 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
245 0xff},
246 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
247 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
248 0xff},
249 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
250 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
251 0xff},
252 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
253 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
254 0xff},
255 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
256 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
257 0xff},
258 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
259 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
260 0xff},
261 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
262 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
263 0xff},
264 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
265 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
266 0xff},
267 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
268 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
269 0xff},
270 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
271 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
272 0xff},
273 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
274 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
275 0xff},
276 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
277 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
278 0xff},
279 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
280 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
281 0xff}
284 static const u8 tas5130a_sensor_init[][8] = {
285 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
286 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
287 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
290 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
292 /* read 1 byte */
293 static u8 reg_r(struct gspca_dev *gspca_dev,
294 u16 index)
296 usb_control_msg(gspca_dev->dev,
297 usb_rcvctrlpipe(gspca_dev->dev, 0),
298 0, /* request */
299 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
300 0, /* value */
301 index,
302 gspca_dev->usb_buf, 1, 500);
303 return gspca_dev->usb_buf[0];
306 static void reg_w(struct gspca_dev *gspca_dev,
307 u16 index)
309 usb_control_msg(gspca_dev->dev,
310 usb_sndctrlpipe(gspca_dev->dev, 0),
312 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 0, index,
314 NULL, 0, 500);
317 static void reg_w_buf(struct gspca_dev *gspca_dev,
318 const u8 *buffer, u16 len)
320 if (len <= USB_BUF_SZ) {
321 memcpy(gspca_dev->usb_buf, buffer, len);
322 usb_control_msg(gspca_dev->dev,
323 usb_sndctrlpipe(gspca_dev->dev, 0),
325 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 0x01, 0,
327 gspca_dev->usb_buf, len, 500);
328 } else {
329 u8 *tmpbuf;
331 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
332 if (!tmpbuf) {
333 pr_err("Out of memory\n");
334 return;
336 usb_control_msg(gspca_dev->dev,
337 usb_sndctrlpipe(gspca_dev->dev, 0),
339 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
340 0x01, 0,
341 tmpbuf, len, 500);
342 kfree(tmpbuf);
346 /* write values to consecutive registers */
347 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
348 u8 reg,
349 const u8 *buffer, u16 len)
351 int i;
352 u8 *p, *tmpbuf;
354 if (len * 2 <= USB_BUF_SZ) {
355 p = tmpbuf = gspca_dev->usb_buf;
356 } else {
357 p = tmpbuf = kmalloc_array(len, 2, GFP_KERNEL);
358 if (!tmpbuf) {
359 pr_err("Out of memory\n");
360 return;
363 i = len;
364 while (--i >= 0) {
365 *p++ = reg++;
366 *p++ = *buffer++;
368 usb_control_msg(gspca_dev->dev,
369 usb_sndctrlpipe(gspca_dev->dev, 0),
371 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
372 0x01, 0,
373 tmpbuf, len * 2, 500);
374 if (len * 2 > USB_BUF_SZ)
375 kfree(tmpbuf);
378 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
380 int i;
381 const u8 *p;
382 u8 byte;
383 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
384 static const u8 sensor_init[] = {
385 0xdf, 0x6d,
386 0xdd, 0x18,
387 0x5a, 0xe0,
388 0x5c, 0x07,
389 0x5d, 0xb0,
390 0x5e, 0x1e,
391 0x60, 0x71,
392 0xef, 0x00,
393 0xe9, 0x00,
394 0xea, 0x00,
395 0x90, 0x24,
396 0x91, 0xb2,
397 0x82, 0x32,
398 0xfd, 0x41,
399 0x00 /* table end */
402 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
403 msleep(100);
404 i = 4;
405 while (--i > 0) {
406 byte = reg_r(gspca_dev, 0x0060);
407 if (!(byte & 0x01))
408 break;
409 msleep(100);
411 byte = reg_r(gspca_dev, 0x0063);
412 if (byte != 0x17) {
413 pr_err("Bad sensor reset %02x\n", byte);
414 /* continue? */
417 p = sensor_init;
418 while (*p != 0) {
419 val[1] = *p++;
420 val[3] = *p++;
421 if (*p == 0)
422 reg_w(gspca_dev, 0x3c80);
423 reg_w_buf(gspca_dev, val, sizeof val);
424 i = 4;
425 while (--i >= 0) {
426 msleep(15);
427 byte = reg_r(gspca_dev, 0x60);
428 if (!(byte & 0x01))
429 break;
432 msleep(15);
433 reg_w(gspca_dev, 0x3c80);
436 /* this function is called at probe time */
437 static int sd_config(struct gspca_dev *gspca_dev,
438 const struct usb_device_id *id)
440 struct cam *cam = &gspca_dev->cam;
442 cam->cam_mode = vga_mode_t16;
443 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
445 return 0;
448 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
450 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
452 if (brightness < 7) {
453 set6[1] = 0x26;
454 set6[3] = 0x70 - brightness * 0x10;
455 } else {
456 set6[3] = 0x00 + ((brightness - 7) * 0x10);
459 reg_w_buf(gspca_dev, set6, sizeof set6);
462 static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
464 u16 reg_to_write;
466 if (contrast < 7)
467 reg_to_write = 0x8ea9 - contrast * 0x200;
468 else
469 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
471 reg_w(gspca_dev, reg_to_write);
474 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
476 u16 reg_to_write;
478 reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */
479 reg_w(gspca_dev, reg_to_write);
482 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
484 gspca_dbg(gspca_dev, D_CONF, "Gamma: %d\n", val);
485 reg_w_ixbuf(gspca_dev, 0x90,
486 gamma_table[val], sizeof gamma_table[0]);
489 static void setawb_n_RGB(struct gspca_dev *gspca_dev)
491 struct sd *sd = (struct sd *) gspca_dev;
492 u8 all_gain_reg[8] = {
493 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
494 s32 red_gain, blue_gain, green_gain;
496 green_gain = sd->gain->val;
498 red_gain = green_gain + sd->red_balance->val;
499 if (red_gain > 0x40)
500 red_gain = 0x40;
501 else if (red_gain < 0x10)
502 red_gain = 0x10;
504 blue_gain = green_gain + sd->blue_balance->val;
505 if (blue_gain > 0x40)
506 blue_gain = 0x40;
507 else if (blue_gain < 0x10)
508 blue_gain = 0x10;
510 all_gain_reg[1] = red_gain;
511 all_gain_reg[3] = blue_gain;
512 all_gain_reg[5] = green_gain;
513 all_gain_reg[7] = sensor_data[sd->sensor].reg80;
514 if (!sd->awb->val)
515 all_gain_reg[7] &= ~0x04; /* AWB off */
517 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
520 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
522 u16 reg_to_write;
524 reg_to_write = 0x0aa6 + 0x1000 * val;
526 reg_w(gspca_dev, reg_to_write);
529 static void setfreq(struct gspca_dev *gspca_dev, s32 val)
531 struct sd *sd = (struct sd *) gspca_dev;
532 u8 reg66;
533 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
535 switch (sd->sensor) {
536 case SENSOR_LT168G:
537 if (val != 0)
538 freq[3] = 0xa8;
539 reg66 = 0x41;
540 break;
541 case SENSOR_OM6802:
542 reg66 = 0xca;
543 break;
544 default:
545 reg66 = 0x40;
546 break;
548 switch (val) {
549 case 0: /* no flicker */
550 freq[3] = 0xf0;
551 break;
552 case 2: /* 60Hz */
553 reg66 &= ~0x40;
554 break;
556 freq[1] = reg66;
558 reg_w_buf(gspca_dev, freq, sizeof freq);
561 /* this function is called at probe and resume time */
562 static int sd_init(struct gspca_dev *gspca_dev)
564 /* some of this registers are not really needed, because
565 * they are overridden by setbrigthness, setcontrast, etc.,
566 * but won't hurt anyway, and can help someone with similar webcam
567 * to see the initial parameters.*/
568 struct sd *sd = (struct sd *) gspca_dev;
569 const struct additional_sensor_data *sensor;
570 int i;
571 u16 sensor_id;
572 u8 test_byte = 0;
574 static const u8 read_indexs[] =
575 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
576 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
577 static const u8 n1[] =
578 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
579 static const u8 n2[] =
580 {0x08, 0x00};
582 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
583 | reg_r(gspca_dev, 0x07);
584 switch (sensor_id & 0xff0f) {
585 case 0x0801:
586 gspca_dbg(gspca_dev, D_PROBE, "sensor tas5130a\n");
587 sd->sensor = SENSOR_TAS5130A;
588 break;
589 case 0x0802:
590 gspca_dbg(gspca_dev, D_PROBE, "sensor lt168g\n");
591 sd->sensor = SENSOR_LT168G;
592 break;
593 case 0x0803:
594 gspca_dbg(gspca_dev, D_PROBE, "sensor 'other'\n");
595 sd->sensor = SENSOR_OTHER;
596 break;
597 case 0x0807:
598 gspca_dbg(gspca_dev, D_PROBE, "sensor om6802\n");
599 sd->sensor = SENSOR_OM6802;
600 break;
601 default:
602 pr_err("unknown sensor %04x\n", sensor_id);
603 return -EINVAL;
606 if (sd->sensor == SENSOR_OM6802) {
607 reg_w_buf(gspca_dev, n1, sizeof n1);
608 i = 5;
609 while (--i >= 0) {
610 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
611 test_byte = reg_r(gspca_dev, 0x0063);
612 msleep(100);
613 if (test_byte == 0x17)
614 break; /* OK */
616 if (i < 0) {
617 pr_err("Bad sensor reset %02x\n", test_byte);
618 return -EIO;
620 reg_w_buf(gspca_dev, n2, sizeof n2);
623 i = 0;
624 while (read_indexs[i] != 0x00) {
625 test_byte = reg_r(gspca_dev, read_indexs[i]);
626 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n",
627 read_indexs[i], test_byte);
628 i++;
631 sensor = &sensor_data[sd->sensor];
632 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
633 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
635 if (sd->sensor == SENSOR_LT168G) {
636 test_byte = reg_r(gspca_dev, 0x80);
637 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
638 test_byte);
639 reg_w(gspca_dev, 0x6c80);
642 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
643 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
644 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
646 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
647 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
648 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
649 reg_w(gspca_dev, (0x20 << 8) + 0x87);
650 reg_w(gspca_dev, (0x20 << 8) + 0x88);
651 reg_w(gspca_dev, (0x20 << 8) + 0x89);
653 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
654 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
655 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
657 if (sd->sensor == SENSOR_LT168G) {
658 test_byte = reg_r(gspca_dev, 0x80);
659 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
660 test_byte);
661 reg_w(gspca_dev, 0x6c80);
664 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
665 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
666 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
668 return 0;
671 static void setmirror(struct gspca_dev *gspca_dev, s32 val)
673 u8 hflipcmd[8] =
674 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
676 if (val)
677 hflipcmd[3] = 0x01;
679 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
682 static void seteffect(struct gspca_dev *gspca_dev, s32 val)
684 int idx = 0;
686 switch (val) {
687 case V4L2_COLORFX_NONE:
688 break;
689 case V4L2_COLORFX_BW:
690 idx = 2;
691 break;
692 case V4L2_COLORFX_SEPIA:
693 idx = 3;
694 break;
695 case V4L2_COLORFX_SKETCH:
696 idx = 4;
697 break;
698 case V4L2_COLORFX_NEGATIVE:
699 idx = 6;
700 break;
701 default:
702 break;
705 reg_w_buf(gspca_dev, effects_table[idx],
706 sizeof effects_table[0]);
708 if (val == V4L2_COLORFX_SKETCH)
709 reg_w(gspca_dev, 0x4aa6);
710 else
711 reg_w(gspca_dev, 0xfaa6);
714 /* Is this really needed?
715 * i added some module parameters for test with some users */
716 static void poll_sensor(struct gspca_dev *gspca_dev)
718 static const u8 poll1[] =
719 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
720 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
721 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
722 0x60, 0x14};
723 static const u8 poll2[] =
724 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
725 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
726 static const u8 noise03[] = /* (some differences / ms-drv) */
727 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
728 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
729 0xc2, 0x80, 0xc3, 0x10};
731 gspca_dbg(gspca_dev, D_STREAM, "[Sensor requires polling]\n");
732 reg_w_buf(gspca_dev, poll1, sizeof poll1);
733 reg_w_buf(gspca_dev, poll2, sizeof poll2);
734 reg_w_buf(gspca_dev, noise03, sizeof noise03);
737 static int sd_start(struct gspca_dev *gspca_dev)
739 struct sd *sd = (struct sd *) gspca_dev;
740 const struct additional_sensor_data *sensor;
741 int i, mode;
742 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
743 static const u8 t3[] =
744 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
746 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
747 switch (mode) {
748 case 0: /* 640x480 (0x00) */
749 break;
750 case 1: /* 352x288 */
751 t2[1] = 0x40;
752 break;
753 case 2: /* 320x240 */
754 t2[1] = 0x10;
755 break;
756 case 3: /* 176x144 */
757 t2[1] = 0x50;
758 break;
759 default:
760 /* case 4: * 160x120 */
761 t2[1] = 0x20;
762 break;
765 switch (sd->sensor) {
766 case SENSOR_OM6802:
767 om6802_sensor_init(gspca_dev);
768 break;
769 case SENSOR_TAS5130A:
770 i = 0;
771 for (;;) {
772 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
773 sizeof tas5130a_sensor_init[0]);
774 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
775 break;
776 i++;
778 reg_w(gspca_dev, 0x3c80);
779 /* just in case and to keep sync with logs (for mine) */
780 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
781 sizeof tas5130a_sensor_init[0]);
782 reg_w(gspca_dev, 0x3c80);
783 break;
785 sensor = &sensor_data[sd->sensor];
786 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
787 reg_r(gspca_dev, 0x0012);
788 reg_w_buf(gspca_dev, t2, sizeof t2);
789 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
790 reg_w(gspca_dev, 0x0013);
791 msleep(15);
792 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
793 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
795 if (sd->sensor == SENSOR_OM6802)
796 poll_sensor(gspca_dev);
798 return 0;
801 static void sd_stopN(struct gspca_dev *gspca_dev)
803 struct sd *sd = (struct sd *) gspca_dev;
805 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
806 sizeof sensor_data[sd->sensor].stream);
807 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
808 sizeof sensor_data[sd->sensor].stream);
809 if (sd->sensor == SENSOR_OM6802) {
810 msleep(20);
811 reg_w(gspca_dev, 0x0309);
813 #if IS_ENABLED(CONFIG_INPUT)
814 /* If the last button state is pressed, release it now! */
815 if (sd->button_pressed) {
816 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
817 input_sync(gspca_dev->input_dev);
818 sd->button_pressed = 0;
820 #endif
823 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
824 u8 *data, /* isoc packet */
825 int len) /* iso packet length */
827 struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
828 int pkt_type;
830 if (data[0] == 0x5a) {
831 #if IS_ENABLED(CONFIG_INPUT)
832 if (len > 20) {
833 u8 state = (data[20] & 0x80) ? 1 : 0;
834 if (sd->button_pressed != state) {
835 input_report_key(gspca_dev->input_dev,
836 KEY_CAMERA, state);
837 input_sync(gspca_dev->input_dev);
838 sd->button_pressed = state;
841 #endif
842 /* Control Packet, after this came the header again,
843 * but extra bytes came in the packet before this,
844 * sometimes an EOF arrives, sometimes not... */
845 return;
847 data += 2;
848 len -= 2;
849 if (data[0] == 0xff && data[1] == 0xd8)
850 pkt_type = FIRST_PACKET;
851 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
852 pkt_type = LAST_PACKET;
853 else
854 pkt_type = INTER_PACKET;
855 gspca_frame_add(gspca_dev, pkt_type, data, len);
858 static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
860 struct gspca_dev *gspca_dev =
861 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
862 struct sd *sd = (struct sd *)gspca_dev;
863 s32 red_gain, blue_gain, green_gain;
865 gspca_dev->usb_err = 0;
867 switch (ctrl->id) {
868 case V4L2_CID_AUTO_WHITE_BALANCE:
869 red_gain = reg_r(gspca_dev, 0x0087);
870 if (red_gain > 0x40)
871 red_gain = 0x40;
872 else if (red_gain < 0x10)
873 red_gain = 0x10;
875 blue_gain = reg_r(gspca_dev, 0x0088);
876 if (blue_gain > 0x40)
877 blue_gain = 0x40;
878 else if (blue_gain < 0x10)
879 blue_gain = 0x10;
881 green_gain = reg_r(gspca_dev, 0x0089);
882 if (green_gain > 0x40)
883 green_gain = 0x40;
884 else if (green_gain < 0x10)
885 green_gain = 0x10;
887 sd->gain->val = green_gain;
888 sd->red_balance->val = red_gain - green_gain;
889 sd->blue_balance->val = blue_gain - green_gain;
890 break;
892 return 0;
895 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
897 struct gspca_dev *gspca_dev =
898 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
900 gspca_dev->usb_err = 0;
902 if (!gspca_dev->streaming)
903 return 0;
905 switch (ctrl->id) {
906 case V4L2_CID_BRIGHTNESS:
907 setbrightness(gspca_dev, ctrl->val);
908 break;
909 case V4L2_CID_CONTRAST:
910 setcontrast(gspca_dev, ctrl->val);
911 break;
912 case V4L2_CID_SATURATION:
913 setcolors(gspca_dev, ctrl->val);
914 break;
915 case V4L2_CID_GAMMA:
916 setgamma(gspca_dev, ctrl->val);
917 break;
918 case V4L2_CID_HFLIP:
919 setmirror(gspca_dev, ctrl->val);
920 break;
921 case V4L2_CID_SHARPNESS:
922 setsharpness(gspca_dev, ctrl->val);
923 break;
924 case V4L2_CID_POWER_LINE_FREQUENCY:
925 setfreq(gspca_dev, ctrl->val);
926 break;
927 case V4L2_CID_BACKLIGHT_COMPENSATION:
928 reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
929 break;
930 case V4L2_CID_AUTO_WHITE_BALANCE:
931 setawb_n_RGB(gspca_dev);
932 break;
933 case V4L2_CID_COLORFX:
934 seteffect(gspca_dev, ctrl->val);
935 break;
937 return gspca_dev->usb_err;
940 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
941 .g_volatile_ctrl = sd_g_volatile_ctrl,
942 .s_ctrl = sd_s_ctrl,
945 static int sd_init_controls(struct gspca_dev *gspca_dev)
947 struct sd *sd = (struct sd *)gspca_dev;
948 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
950 gspca_dev->vdev.ctrl_handler = hdl;
951 v4l2_ctrl_handler_init(hdl, 12);
952 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
953 V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
954 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
955 V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
956 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
957 V4L2_CID_SATURATION, 0, 0xf, 1, 5);
958 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
959 V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
960 /* Activate lowlight, some apps don't bring up the
961 backlight_compensation control) */
962 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
963 V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
964 if (sd->sensor == SENSOR_TAS5130A)
965 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
966 V4L2_CID_HFLIP, 0, 1, 1, 0);
967 sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
968 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
969 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
970 V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
971 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
972 V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
973 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
974 V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
975 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
976 V4L2_CID_SHARPNESS, 0, 15, 1, 6);
977 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
978 V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
979 ~((1 << V4L2_COLORFX_NONE) |
980 (1 << V4L2_COLORFX_BW) |
981 (1 << V4L2_COLORFX_SEPIA) |
982 (1 << V4L2_COLORFX_SKETCH) |
983 (1 << V4L2_COLORFX_NEGATIVE)),
984 V4L2_COLORFX_NONE);
985 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
986 V4L2_CID_POWER_LINE_FREQUENCY,
987 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
988 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
990 if (hdl->error) {
991 pr_err("Could not initialize controls\n");
992 return hdl->error;
995 v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
997 return 0;
1000 /* sub-driver description */
1001 static const struct sd_desc sd_desc = {
1002 .name = MODULE_NAME,
1003 .config = sd_config,
1004 .init = sd_init,
1005 .init_controls = sd_init_controls,
1006 .start = sd_start,
1007 .stopN = sd_stopN,
1008 .pkt_scan = sd_pkt_scan,
1009 #if IS_ENABLED(CONFIG_INPUT)
1010 .other_input = 1,
1011 #endif
1014 /* -- module initialisation -- */
1015 static const struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x17a1, 0x0128)},
1019 MODULE_DEVICE_TABLE(usb, device_table);
1021 /* -- device connect -- */
1022 static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1025 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1026 THIS_MODULE);
1029 static struct usb_driver sd_driver = {
1030 .name = MODULE_NAME,
1031 .id_table = device_table,
1032 .probe = sd_probe,
1033 .disconnect = gspca_disconnect,
1034 #ifdef CONFIG_PM
1035 .suspend = gspca_suspend,
1036 .resume = gspca_resume,
1037 .reset_resume = gspca_resume,
1038 #endif
1041 module_usb_driver(sd_driver);