1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * T613 subdriver
4 *
5 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
6 *
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
14 */
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#define MODULE_NAME "t613"
19
20#include <linux/input.h>
21#include <linux/slab.h>
22#include "gspca.h"
23
24MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
25MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
26MODULE_LICENSE("GPL");
27
28struct 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;
36 };
37
38 u8 sensor;
39 u8 button_pressed;
40};
41enum sensors {
42 SENSOR_OM6802,
43 SENSOR_OTHER,
44 SENSOR_TAS5130A,
45 SENSOR_LT168G, /* must verify if this is the actual model */
46};
47
48static 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},
78};
79
80/* sensor specific data */
81struct 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];
91};
92
93static 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
103};
104static 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
113};
114static 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
122};
123static 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
133};
134
135static 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},
157 },
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},
179 },
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},
201 },
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},
217 },
218};
219
220#define MAX_EFFECTS 7
221static 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 */
229};
230
231#define GAMMA_MAX (15)
232static 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}
282};
283
284static 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},
288};
289
290static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
291
292/* read 1 byte */
293static u8 reg_r(struct gspca_dev *gspca_dev,
294 u16 index)
295{
296 usb_control_msg(dev: gspca_dev->dev,
297 usb_rcvctrlpipe(gspca_dev->dev, 0),
298 request: 0, /* request */
299 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
300 value: 0, /* value */
301 index,
302 data: gspca_dev->usb_buf, size: 1, timeout: 500);
303 return gspca_dev->usb_buf[0];
304}
305
306static void reg_w(struct gspca_dev *gspca_dev,
307 u16 index)
308{
309 usb_control_msg(dev: gspca_dev->dev,
310 usb_sndctrlpipe(gspca_dev->dev, 0),
311 request: 0,
312 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 value: 0, index,
314 NULL, size: 0, timeout: 500);
315}
316
317static void reg_w_buf(struct gspca_dev *gspca_dev,
318 const u8 *buffer, u16 len)
319{
320 if (len <= USB_BUF_SZ) {
321 memcpy(gspca_dev->usb_buf, buffer, len);
322 usb_control_msg(dev: gspca_dev->dev,
323 usb_sndctrlpipe(gspca_dev->dev, 0),
324 request: 0,
325 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 value: 0x01, index: 0,
327 data: gspca_dev->usb_buf, size: len, timeout: 500);
328 } else {
329 u8 *tmpbuf;
330
331 tmpbuf = kmemdup(p: buffer, size: len, GFP_KERNEL);
332 if (!tmpbuf) {
333 pr_err("Out of memory\n");
334 return;
335 }
336 usb_control_msg(dev: gspca_dev->dev,
337 usb_sndctrlpipe(gspca_dev->dev, 0),
338 request: 0,
339 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
340 value: 0x01, index: 0,
341 data: tmpbuf, size: len, timeout: 500);
342 kfree(objp: tmpbuf);
343 }
344}
345
346/* write values to consecutive registers */
347static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
348 u8 reg,
349 const u8 *buffer, u16 len)
350{
351 int i;
352 u8 *p, *tmpbuf;
353
354 if (len * 2 <= USB_BUF_SZ) {
355 p = tmpbuf = gspca_dev->usb_buf;
356 } else {
357 p = tmpbuf = kmalloc_array(n: len, size: 2, GFP_KERNEL);
358 if (!tmpbuf) {
359 pr_err("Out of memory\n");
360 return;
361 }
362 }
363 i = len;
364 while (--i >= 0) {
365 *p++ = reg++;
366 *p++ = *buffer++;
367 }
368 usb_control_msg(dev: gspca_dev->dev,
369 usb_sndctrlpipe(gspca_dev->dev, 0),
370 request: 0,
371 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
372 value: 0x01, index: 0,
373 data: tmpbuf, size: len * 2, timeout: 500);
374 if (len * 2 > USB_BUF_SZ)
375 kfree(objp: tmpbuf);
376}
377
378static void om6802_sensor_init(struct gspca_dev *gspca_dev)
379{
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 */
400 };
401
402 reg_w_buf(gspca_dev, buffer: sensor_reset, len: sizeof sensor_reset);
403 msleep(msecs: 100);
404 i = 4;
405 while (--i > 0) {
406 byte = reg_r(gspca_dev, index: 0x0060);
407 if (!(byte & 0x01))
408 break;
409 msleep(msecs: 100);
410 }
411 byte = reg_r(gspca_dev, index: 0x0063);
412 if (byte != 0x17) {
413 pr_err("Bad sensor reset %02x\n", byte);
414 /* continue? */
415 }
416
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, index: 0x3c80);
423 reg_w_buf(gspca_dev, buffer: val, len: sizeof val);
424 i = 4;
425 while (--i >= 0) {
426 msleep(msecs: 15);
427 byte = reg_r(gspca_dev, index: 0x60);
428 if (!(byte & 0x01))
429 break;
430 }
431 }
432 msleep(msecs: 15);
433 reg_w(gspca_dev, index: 0x3c80);
434}
435
436/* this function is called at probe time */
437static int sd_config(struct gspca_dev *gspca_dev,
438 const struct usb_device_id *id)
439{
440 struct cam *cam = &gspca_dev->cam;
441
442 cam->cam_mode = vga_mode_t16;
443 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
444
445 return 0;
446}
447
448static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
449{
450 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
451
452 if (brightness < 7) {
453 set6[1] = 0x26;
454 set6[3] = 0x70 - brightness * 0x10;
455 } else {
456 set6[3] = 0x00 + ((brightness - 7) * 0x10);
457 }
458
459 reg_w_buf(gspca_dev, buffer: set6, len: sizeof set6);
460}
461
462static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
463{
464 u16 reg_to_write;
465
466 if (contrast < 7)
467 reg_to_write = 0x8ea9 - contrast * 0x200;
468 else
469 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
470
471 reg_w(gspca_dev, index: reg_to_write);
472}
473
474static void setcolors(struct gspca_dev *gspca_dev, s32 val)
475{
476 u16 reg_to_write;
477
478 reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */
479 reg_w(gspca_dev, index: reg_to_write);
480}
481
482static void setgamma(struct gspca_dev *gspca_dev, s32 val)
483{
484 gspca_dbg(gspca_dev, D_CONF, "Gamma: %d\n", val);
485 reg_w_ixbuf(gspca_dev, reg: 0x90,
486 buffer: gamma_table[val], len: sizeof gamma_table[0]);
487}
488
489static void setawb_n_RGB(struct gspca_dev *gspca_dev)
490{
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;
495
496 green_gain = sd->gain->val;
497
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;
503
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;
509
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 */
516
517 reg_w_buf(gspca_dev, buffer: all_gain_reg, len: sizeof all_gain_reg);
518}
519
520static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
521{
522 u16 reg_to_write;
523
524 reg_to_write = 0x0aa6 + 0x1000 * val;
525
526 reg_w(gspca_dev, index: reg_to_write);
527}
528
529static void setfreq(struct gspca_dev *gspca_dev, s32 val)
530{
531 struct sd *sd = (struct sd *) gspca_dev;
532 u8 reg66;
533 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
534
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;
547 }
548 switch (val) {
549 case 0: /* no flicker */
550 freq[3] = 0xf0;
551 break;
552 case 2: /* 60Hz */
553 reg66 &= ~0x40;
554 break;
555 }
556 freq[1] = reg66;
557
558 reg_w_buf(gspca_dev, buffer: freq, len: sizeof freq);
559}
560
561/* this function is called at probe and resume time */
562static int sd_init(struct gspca_dev *gspca_dev)
563{
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;
573
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};
581
582 sensor_id = (reg_r(gspca_dev, index: 0x06) << 8)
583 | reg_r(gspca_dev, index: 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;
604 }
605
606 if (sd->sensor == SENSOR_OM6802) {
607 reg_w_buf(gspca_dev, buffer: n1, len: sizeof n1);
608 i = 5;
609 while (--i >= 0) {
610 reg_w_buf(gspca_dev, buffer: sensor_reset, len: sizeof sensor_reset);
611 test_byte = reg_r(gspca_dev, index: 0x0063);
612 msleep(msecs: 100);
613 if (test_byte == 0x17)
614 break; /* OK */
615 }
616 if (i < 0) {
617 pr_err("Bad sensor reset %02x\n", test_byte);
618 return -EIO;
619 }
620 reg_w_buf(gspca_dev, buffer: n2, len: sizeof n2);
621 }
622
623 i = 0;
624 while (read_indexs[i] != 0x00) {
625 test_byte = reg_r(gspca_dev, index: read_indexs[i]);
626 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n",
627 read_indexs[i], test_byte);
628 i++;
629 }
630
631 sensor = &sensor_data[sd->sensor];
632 reg_w_buf(gspca_dev, buffer: sensor->n3, len: sizeof sensor->n3);
633 reg_w_buf(gspca_dev, buffer: sensor->n4, len: sensor->n4sz);
634
635 if (sd->sensor == SENSOR_LT168G) {
636 test_byte = reg_r(gspca_dev, index: 0x80);
637 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
638 test_byte);
639 reg_w(gspca_dev, index: 0x6c80);
640 }
641
642 reg_w_ixbuf(gspca_dev, reg: 0xd0, buffer: sensor->data1, len: sizeof sensor->data1);
643 reg_w_ixbuf(gspca_dev, reg: 0xc7, buffer: sensor->data2, len: sizeof sensor->data2);
644 reg_w_ixbuf(gspca_dev, reg: 0xe0, buffer: sensor->data3, len: sizeof sensor->data3);
645
646 reg_w(gspca_dev, index: (sensor->reg80 << 8) + 0x80);
647 reg_w(gspca_dev, index: (sensor->reg80 << 8) + 0x80);
648 reg_w(gspca_dev, index: (sensor->reg8e << 8) + 0x8e);
649 reg_w(gspca_dev, index: (0x20 << 8) + 0x87);
650 reg_w(gspca_dev, index: (0x20 << 8) + 0x88);
651 reg_w(gspca_dev, index: (0x20 << 8) + 0x89);
652
653 reg_w_buf(gspca_dev, buffer: sensor->data5, len: sizeof sensor->data5);
654 reg_w_buf(gspca_dev, buffer: sensor->nset8, len: sizeof sensor->nset8);
655 reg_w_buf(gspca_dev, buffer: sensor->stream, len: sizeof sensor->stream);
656
657 if (sd->sensor == SENSOR_LT168G) {
658 test_byte = reg_r(gspca_dev, index: 0x80);
659 gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80,
660 test_byte);
661 reg_w(gspca_dev, index: 0x6c80);
662 }
663
664 reg_w_ixbuf(gspca_dev, reg: 0xd0, buffer: sensor->data1, len: sizeof sensor->data1);
665 reg_w_ixbuf(gspca_dev, reg: 0xc7, buffer: sensor->data2, len: sizeof sensor->data2);
666 reg_w_ixbuf(gspca_dev, reg: 0xe0, buffer: sensor->data3, len: sizeof sensor->data3);
667
668 return 0;
669}
670
671static void setmirror(struct gspca_dev *gspca_dev, s32 val)
672{
673 u8 hflipcmd[8] =
674 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
675
676 if (val)
677 hflipcmd[3] = 0x01;
678
679 reg_w_buf(gspca_dev, buffer: hflipcmd, len: sizeof hflipcmd);
680}
681
682static void seteffect(struct gspca_dev *gspca_dev, s32 val)
683{
684 int idx = 0;
685
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;
703 }
704
705 reg_w_buf(gspca_dev, buffer: effects_table[idx],
706 len: sizeof effects_table[0]);
707
708 if (val == V4L2_COLORFX_SKETCH)
709 reg_w(gspca_dev, index: 0x4aa6);
710 else
711 reg_w(gspca_dev, index: 0xfaa6);
712}
713
714/* Is this really needed?
715 * i added some module parameters for test with some users */
716static void poll_sensor(struct gspca_dev *gspca_dev)
717{
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};
730
731 gspca_dbg(gspca_dev, D_STREAM, "[Sensor requires polling]\n");
732 reg_w_buf(gspca_dev, buffer: poll1, len: sizeof poll1);
733 reg_w_buf(gspca_dev, buffer: poll2, len: sizeof poll2);
734 reg_w_buf(gspca_dev, buffer: noise03, len: sizeof noise03);
735}
736
737static int sd_start(struct gspca_dev *gspca_dev)
738{
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 };
745
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;
763 }
764
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, buffer: tas5130a_sensor_init[i],
773 len: sizeof tas5130a_sensor_init[0]);
774 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
775 break;
776 i++;
777 }
778 reg_w(gspca_dev, index: 0x3c80);
779 /* just in case and to keep sync with logs (for mine) */
780 reg_w_buf(gspca_dev, buffer: tas5130a_sensor_init[i],
781 len: sizeof tas5130a_sensor_init[0]);
782 reg_w(gspca_dev, index: 0x3c80);
783 break;
784 }
785 sensor = &sensor_data[sd->sensor];
786 setfreq(gspca_dev, val: v4l2_ctrl_g_ctrl(ctrl: sd->freq));
787 reg_r(gspca_dev, index: 0x0012);
788 reg_w_buf(gspca_dev, buffer: t2, len: sizeof t2);
789 reg_w_ixbuf(gspca_dev, reg: 0xb3, buffer: t3, len: sizeof t3);
790 reg_w(gspca_dev, index: 0x0013);
791 msleep(msecs: 15);
792 reg_w_buf(gspca_dev, buffer: sensor->stream, len: sizeof sensor->stream);
793 reg_w_buf(gspca_dev, buffer: sensor->stream, len: sizeof sensor->stream);
794
795 if (sd->sensor == SENSOR_OM6802)
796 poll_sensor(gspca_dev);
797
798 return 0;
799}
800
801static void sd_stopN(struct gspca_dev *gspca_dev)
802{
803 struct sd *sd = (struct sd *) gspca_dev;
804
805 reg_w_buf(gspca_dev, buffer: sensor_data[sd->sensor].stream,
806 len: sizeof sensor_data[sd->sensor].stream);
807 reg_w_buf(gspca_dev, buffer: sensor_data[sd->sensor].stream,
808 len: sizeof sensor_data[sd->sensor].stream);
809 if (sd->sensor == SENSOR_OM6802) {
810 msleep(msecs: 20);
811 reg_w(gspca_dev, index: 0x0309);
812 }
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(dev: gspca_dev->input_dev, KEY_CAMERA, value: 0);
817 input_sync(dev: gspca_dev->input_dev);
818 sd->button_pressed = 0;
819 }
820#endif
821}
822
823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
824 u8 *data, /* isoc packet */
825 int len) /* iso packet length */
826{
827 struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
828 int pkt_type;
829
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(dev: gspca_dev->input_dev,
836 KEY_CAMERA, value: state);
837 input_sync(dev: gspca_dev->input_dev);
838 sd->button_pressed = state;
839 }
840 }
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;
846 }
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, packet_type: pkt_type, data, len);
856}
857
858static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
859{
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;
864
865 gspca_dev->usb_err = 0;
866
867 switch (ctrl->id) {
868 case V4L2_CID_AUTO_WHITE_BALANCE:
869 red_gain = reg_r(gspca_dev, index: 0x0087);
870 if (red_gain > 0x40)
871 red_gain = 0x40;
872 else if (red_gain < 0x10)
873 red_gain = 0x10;
874
875 blue_gain = reg_r(gspca_dev, index: 0x0088);
876 if (blue_gain > 0x40)
877 blue_gain = 0x40;
878 else if (blue_gain < 0x10)
879 blue_gain = 0x10;
880
881 green_gain = reg_r(gspca_dev, index: 0x0089);
882 if (green_gain > 0x40)
883 green_gain = 0x40;
884 else if (green_gain < 0x10)
885 green_gain = 0x10;
886
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;
891 }
892 return 0;
893}
894
895static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
896{
897 struct gspca_dev *gspca_dev =
898 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
899
900 gspca_dev->usb_err = 0;
901
902 if (!gspca_dev->streaming)
903 return 0;
904
905 switch (ctrl->id) {
906 case V4L2_CID_BRIGHTNESS:
907 setbrightness(gspca_dev, brightness: ctrl->val);
908 break;
909 case V4L2_CID_CONTRAST:
910 setcontrast(gspca_dev, contrast: ctrl->val);
911 break;
912 case V4L2_CID_SATURATION:
913 setcolors(gspca_dev, val: ctrl->val);
914 break;
915 case V4L2_CID_GAMMA:
916 setgamma(gspca_dev, val: ctrl->val);
917 break;
918 case V4L2_CID_HFLIP:
919 setmirror(gspca_dev, val: ctrl->val);
920 break;
921 case V4L2_CID_SHARPNESS:
922 setsharpness(gspca_dev, val: ctrl->val);
923 break;
924 case V4L2_CID_POWER_LINE_FREQUENCY:
925 setfreq(gspca_dev, val: ctrl->val);
926 break;
927 case V4L2_CID_BACKLIGHT_COMPENSATION:
928 reg_w(gspca_dev, index: 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, val: ctrl->val);
935 break;
936 }
937 return gspca_dev->usb_err;
938}
939
940static const struct v4l2_ctrl_ops sd_ctrl_ops = {
941 .g_volatile_ctrl = sd_g_volatile_ctrl,
942 .s_ctrl = sd_s_ctrl,
943};
944
945static int sd_init_controls(struct gspca_dev *gspca_dev)
946{
947 struct sd *sd = (struct sd *)gspca_dev;
948 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
949
950 gspca_dev->vdev.ctrl_handler = hdl;
951 v4l2_ctrl_handler_init(hdl, 12);
952 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
953 V4L2_CID_BRIGHTNESS, min: 0, max: 14, step: 1, def: 8);
954 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
955 V4L2_CID_CONTRAST, min: 0, max: 0x0d, step: 1, def: 7);
956 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
957 V4L2_CID_SATURATION, min: 0, max: 0xf, step: 1, def: 5);
958 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
959 V4L2_CID_GAMMA, min: 0, GAMMA_MAX, step: 1, def: 10);
960 /* Activate lowlight, some apps don't bring up the
961 backlight_compensation control) */
962 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
963 V4L2_CID_BACKLIGHT_COMPENSATION, min: 0, max: 1, step: 1, def: 1);
964 if (sd->sensor == SENSOR_TAS5130A)
965 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
966 V4L2_CID_HFLIP, min: 0, max: 1, step: 1, def: 0);
967 sd->awb = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
968 V4L2_CID_AUTO_WHITE_BALANCE, min: 0, max: 1, step: 1, def: 1);
969 sd->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
970 V4L2_CID_GAIN, min: 0x10, max: 0x40, step: 1, def: 0x20);
971 sd->blue_balance = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
972 V4L2_CID_BLUE_BALANCE, min: -0x30, max: 0x30, step: 1, def: 0);
973 sd->red_balance = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
974 V4L2_CID_RED_BALANCE, min: -0x30, max: 0x30, step: 1, def: 0);
975 v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
976 V4L2_CID_SHARPNESS, min: 0, max: 15, step: 1, def: 6);
977 v4l2_ctrl_new_std_menu(hdl, ops: &sd_ctrl_ops,
978 V4L2_CID_COLORFX, max: V4L2_COLORFX_SKETCH,
979 mask: ~((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 def: V4L2_COLORFX_NONE);
985 sd->freq = v4l2_ctrl_new_std_menu(hdl, ops: &sd_ctrl_ops,
986 V4L2_CID_POWER_LINE_FREQUENCY,
987 max: V4L2_CID_POWER_LINE_FREQUENCY_60HZ, mask: 1,
988 def: V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
989
990 if (hdl->error) {
991 pr_err("Could not initialize controls\n");
992 return hdl->error;
993 }
994
995 v4l2_ctrl_auto_cluster(ncontrols: 4, controls: &sd->awb, manual_val: 0, set_volatile: true);
996
997 return 0;
998}
999
1000/* sub-driver description */
1001static 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
1012};
1013
1014/* -- module initialisation -- */
1015static const struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x17a1, 0x0128)},
1017 {}
1018};
1019MODULE_DEVICE_TABLE(usb, device_table);
1020
1021/* -- device connect -- */
1022static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1024{
1025 return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd),
1026 THIS_MODULE);
1027}
1028
1029static 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
1039};
1040
1041module_usb_driver(sd_driver);
1042

source code of linux/drivers/media/usb/gspca/t613.c