]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/usb/gspca/t613.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / media / usb / gspca / t613.c
CommitLineData
6a7eba24 1/*
cd8955b8
JFM
2 * T613 subdriver
3 *
4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
6a7eba24
JFM
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
10b0e96e
JFM
16 *Notes: * t613 + tas5130A
17 * * Focus to light do not balance well as in win.
18 * Quality in win is not good, but its kinda better.
19 * * Fix some "extraneous bytes", most of apps will show the image anyway
20 * * Gamma table, is there, but its really doing something?
21 * * 7~8 Fps, its ok, max on win its 10.
22 * Costantino Leandro
6a7eba24
JFM
23 */
24
1b19e429
JP
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
6a7eba24 27#define MODULE_NAME "t613"
10b0e96e 28
ee186fd9 29#include <linux/input.h>
be2a9fae 30#include <linux/slab.h>
6a7eba24 31#include "gspca.h"
6a7eba24 32
6a7eba24
JFM
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; /* !! must be the first item */
9bf81642
HV
39 struct v4l2_ctrl *freq;
40 struct { /* awb / color gains control cluster */
41 struct v4l2_ctrl *awb;
42 struct v4l2_ctrl *gain;
43 struct v4l2_ctrl *red_balance;
44 struct v4l2_ctrl *blue_balance;
45 };
82e25491
JFM
46
47 u8 sensor;
ee186fd9 48 u8 button_pressed;
11ce884a
JFM
49};
50enum sensors {
cd8955b8
JFM
51 SENSOR_OM6802,
52 SENSOR_OTHER,
53 SENSOR_TAS5130A,
54 SENSOR_LT168G, /* must verify if this is the actual model */
6a7eba24
JFM
55};
56
cc611b8a 57static const struct v4l2_pix_format vga_mode_t16[] = {
c2446b3e
JFM
58 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
59 .bytesperline = 160,
5d05294a 60 .sizeimage = 160 * 120 * 4 / 8 + 590,
c2446b3e
JFM
61 .colorspace = V4L2_COLORSPACE_JPEG,
62 .priv = 4},
1ea172d2 63#if 0 /* HDG: broken with my test cam, so lets disable it */
c2446b3e
JFM
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},
1ea172d2 69#endif
c2446b3e
JFM
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},
1ea172d2 75#if 0 /* HDG: broken with my test cam, so lets disable it */
c2446b3e
JFM
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},
1ea172d2 81#endif
c2446b3e
JFM
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},
6a7eba24
JFM
87};
88
ad62fb08
LC
89/* sensor specific data */
90struct additional_sensor_data {
78a6d74e
JFM
91 const u8 n3[6];
92 const u8 *n4, n4sz;
93 const u8 reg80, reg8e;
94 const u8 nset8[6];
82e25491
JFM
95 const u8 data1[10];
96 const u8 data2[9];
97 const u8 data3[9];
82e25491
JFM
98 const u8 data5[6];
99 const u8 stream[4];
ad62fb08
LC
100};
101
78a6d74e
JFM
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};
00e8006d
NW
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};
78a6d74e 143
e23b2907 144static const struct additional_sensor_data sensor_data[] = {
cd8955b8 145[SENSOR_OM6802] = {
78a6d74e
JFM
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},
2d56f3bb
JFM
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},
78a6d74e
JFM
159 .data3 =
160 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
161 0xff},
2d56f3bb
JFM
162 .data5 = /* this could be removed later */
163 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
164 .stream =
165 {0x0b, 0x04, 0x0a, 0x78},
166 },
cd8955b8 167[SENSOR_OTHER] = {
78a6d74e
JFM
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},
2d56f3bb
JFM
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},
78a6d74e
JFM
181 .data3 =
182 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
183 0xd9},
2d56f3bb
JFM
184 .data5 =
185 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
186 .stream =
187 {0x0b, 0x04, 0x0a, 0x00},
188 },
cd8955b8 189[SENSOR_TAS5130A] = {
78a6d74e
JFM
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},
ad62fb08 197 .data1 =
82e25491
JFM
198 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
199 0xc8, 0xfc},
ad62fb08 200 .data2 =
82e25491
JFM
201 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
202 0xe0},
78a6d74e
JFM
203 .data3 =
204 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
205 0xe0},
ad62fb08
LC
206 .data5 =
207 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
208 .stream =
209 {0x0b, 0x04, 0x0a, 0x40},
210 },
cd8955b8 211[SENSOR_LT168G] = {
00e8006d
NW
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},
00e8006d
NW
224 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
225 .stream = {0x0b, 0x04, 0x0a, 0x28},
226 },
ad62fb08
LC
227};
228
6a7eba24 229#define MAX_EFFECTS 7
82e25491 230static const u8 effects_table[MAX_EFFECTS][6] = {
6a7eba24
JFM
231 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
232 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
233 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
234 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
235 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
236 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
237 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
238};
239
9bf81642
HV
240#define GAMMA_MAX (15)
241static const u8 gamma_table[GAMMA_MAX+1][17] = {
79960d39
JFM
242/* gamma table from cam1690.ini */
243 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
244 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
82e25491 245 0xff},
79960d39
JFM
246 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
247 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
82e25491 248 0xff},
79960d39
JFM
249 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
250 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
82e25491 251 0xff},
79960d39
JFM
252 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
253 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
82e25491 254 0xff},
1d00d6c1 255 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
79960d39 256 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
82e25491 257 0xff},
79960d39
JFM
258 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
259 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
82e25491 260 0xff},
79960d39 261 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
82e25491
JFM
262 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
263 0xff},
79960d39 264 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
82e25491
JFM
265 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
266 0xff},
79960d39
JFM
267 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
268 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
82e25491 269 0xff},
79960d39
JFM
270 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
271 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
82e25491 272 0xff},
79960d39
JFM
273 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
274 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
82e25491 275 0xff},
79960d39 276 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
82e25491
JFM
277 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
278 0xff},
279 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
280 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
281 0xff},
282 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
283 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
284 0xff},
285 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
286 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
287 0xff},
288 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
289 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
290 0xff}
6a7eba24
JFM
291};
292
82e25491 293static const u8 tas5130a_sensor_init[][8] = {
6a7eba24
JFM
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},
6a7eba24
JFM
297};
298
82e25491 299static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
392ee5a5 300
739570bb 301/* read 1 byte */
82e25491
JFM
302static u8 reg_r(struct gspca_dev *gspca_dev,
303 u16 index)
6a7eba24 304{
739570bb
JFM
305 usb_control_msg(gspca_dev->dev,
306 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
307 0, /* request */
308 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
309 0, /* value */
739570bb
JFM
310 index,
311 gspca_dev->usb_buf, 1, 500);
312 return gspca_dev->usb_buf[0];
6a7eba24
JFM
313}
314
739570bb 315static void reg_w(struct gspca_dev *gspca_dev,
82e25491 316 u16 index)
fadc7993
JFM
317{
318 usb_control_msg(gspca_dev->dev,
319 usb_sndctrlpipe(gspca_dev->dev, 0),
320 0,
0bc99b5c 321 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993
JFM
322 0, index,
323 NULL, 0, 500);
324}
325
f89be036 326static void reg_w_buf(struct gspca_dev *gspca_dev,
82e25491 327 const u8 *buffer, u16 len)
6a7eba24 328{
8295d99e 329 if (len <= USB_BUF_SZ) {
739570bb
JFM
330 memcpy(gspca_dev->usb_buf, buffer, len);
331 usb_control_msg(gspca_dev->dev,
332 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062 333 0,
0bc99b5c 334 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993 335 0x01, 0,
739570bb 336 gspca_dev->usb_buf, len, 500);
a5ae2062 337 } else {
82e25491 338 u8 *tmpbuf;
a5ae2062 339
feda79bf 340 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
24f222e7 341 if (!tmpbuf) {
1b19e429 342 pr_err("Out of memory\n");
24f222e7
JFM
343 return;
344 }
739570bb
JFM
345 usb_control_msg(gspca_dev->dev,
346 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062 347 0,
0bc99b5c 348 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
fadc7993 349 0x01, 0,
a5ae2062
JFM
350 tmpbuf, len, 500);
351 kfree(tmpbuf);
352 }
6a7eba24
JFM
353}
354
82e25491
JFM
355/* write values to consecutive registers */
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
24f222e7 363 if (len * 2 <= USB_BUF_SZ) {
82e25491 364 p = tmpbuf = gspca_dev->usb_buf;
24f222e7 365 } else {
82e25491 366 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
24f222e7 367 if (!tmpbuf) {
1b19e429 368 pr_err("Out of memory\n");
24f222e7
JFM
369 return;
370 }
371 }
82e25491
JFM
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
236088d2 387static void om6802_sensor_init(struct gspca_dev *gspca_dev)
fadc7993
JFM
388{
389 int i;
82e25491
JFM
390 const u8 *p;
391 u8 byte;
392 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
393 static const u8 sensor_init[] = {
fadc7993
JFM
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,
fadc7993
JFM
407 0xfd, 0x41,
408 0x00 /* table end */
409 };
410
392ee5a5 411 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
e30bdc66 412 msleep(100);
392ee5a5 413 i = 4;
97a53a0f 414 while (--i > 0) {
392ee5a5
JFM
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) {
1b19e429 422 pr_err("Bad sensor reset %02x\n", byte);
392ee5a5
JFM
423 /* continue? */
424 }
425
fadc7993
JFM
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);
f89be036 432 reg_w_buf(gspca_dev, val, sizeof val);
fadc7993
JFM
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 }
392ee5a5
JFM
441 msleep(15);
442 reg_w(gspca_dev, 0x3c80);
fadc7993
JFM
443}
444
6a7eba24
JFM
445/* this function is called at probe time */
446static int sd_config(struct gspca_dev *gspca_dev,
447 const struct usb_device_id *id)
448{
9bf81642 449 struct cam *cam = &gspca_dev->cam;
6a7eba24
JFM
450
451 cam->cam_mode = vga_mode_t16;
452 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
453
6a7eba24
JFM
454 return 0;
455}
456
9bf81642 457static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
35480b6b 458{
82e25491 459 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
35480b6b 460
35480b6b
JFM
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
9bf81642 471static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
35480b6b 472{
82e25491 473 u16 reg_to_write;
35480b6b
JFM
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
9bf81642 483static void setcolors(struct gspca_dev *gspca_dev, s32 val)
35480b6b 484{
82e25491 485 u16 reg_to_write;
35480b6b 486
9bf81642 487 reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */
35480b6b
JFM
488 reg_w(gspca_dev, reg_to_write);
489}
490
9bf81642 491static void setgamma(struct gspca_dev *gspca_dev, s32 val)
fadc7993 492{
8547fd18 493 PDEBUG(D_CONF, "Gamma: %d", val);
82e25491 494 reg_w_ixbuf(gspca_dev, 0x90,
9bf81642 495 gamma_table[val], sizeof gamma_table[0]);
fadc7993
JFM
496}
497
9bf81642 498static void setawb_n_RGB(struct gspca_dev *gspca_dev)
e9b15653 499{
be1da9ee 500 struct sd *sd = (struct sd *) gspca_dev;
9bf81642
HV
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; /* AWB off */
e9b15653 525
e9b15653 526 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
be1da9ee
CL
527}
528
9bf81642 529static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
35480b6b 530{
82e25491 531 u16 reg_to_write;
35480b6b 532
9bf81642 533 reg_to_write = 0x0aa6 + 0x1000 * val;
35480b6b
JFM
534
535 reg_w(gspca_dev, reg_to_write);
536}
537
9bf81642 538static void setfreq(struct gspca_dev *gspca_dev, s32 val)
78b98cb9
JFM
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:
9bf81642 546 if (val != 0)
78b98cb9
JFM
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 }
9bf81642 557 switch (val) {
78b98cb9
JFM
558 case 0: /* no flicker */
559 freq[3] = 0xf0;
560 break;
561 case 2: /* 60Hz */
562 reg66 &= ~0x40;
563 break;
564 }
565 freq[1] = reg66;
566
567 reg_w_buf(gspca_dev, freq, sizeof freq);
568}
569
fadc7993
JFM
570/* this function is called at probe and resume time */
571static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24 572{
6a7eba24
JFM
573 /* some of this registers are not really neded, because
574 * they are overriden by setbrigthness, setcontrast, etc,
575 * but wont hurt anyway, and can help someone with similar webcam
576 * to see the initial parameters.*/
fadc7993 577 struct sd *sd = (struct sd *) gspca_dev;
78a6d74e 578 const struct additional_sensor_data *sensor;
fadc7993 579 int i;
2d56f3bb 580 u16 sensor_id;
d9ddd3b0 581 u8 test_byte = 0;
6a7eba24 582
82e25491 583 static const u8 read_indexs[] =
249fe889 584 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
82e25491
JFM
585 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
586 static const u8 n1[] =
6a7eba24 587 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
82e25491 588 static const u8 n2[] =
6a7eba24 589 {0x08, 0x00};
6a7eba24 590
2d56f3bb
JFM
591 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
592 | reg_r(gspca_dev, 0x07);
3da37e42 593 switch (sensor_id & 0xff0f) {
2d56f3bb 594 case 0x0801:
748c0148 595 PDEBUG(D_PROBE, "sensor tas5130a");
236088d2 596 sd->sensor = SENSOR_TAS5130A;
2d56f3bb 597 break;
00e8006d
NW
598 case 0x0802:
599 PDEBUG(D_PROBE, "sensor lt168g");
600 sd->sensor = SENSOR_LT168G;
601 break;
2d56f3bb 602 case 0x0803:
748c0148 603 PDEBUG(D_PROBE, "sensor 'other'");
2d56f3bb
JFM
604 sd->sensor = SENSOR_OTHER;
605 break;
606 case 0x0807:
748c0148 607 PDEBUG(D_PROBE, "sensor om6802");
2d56f3bb
JFM
608 sd->sensor = SENSOR_OM6802;
609 break;
610 default:
1b19e429 611 pr_err("unknown sensor %04x\n", sensor_id);
409b11dd 612 return -EINVAL;
fadc7993
JFM
613 }
614
dd72cb3e 615 if (sd->sensor == SENSOR_OM6802) {
2d56f3bb
JFM
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; /* OK */
624 }
625 if (i < 0) {
1b19e429 626 pr_err("Bad sensor reset %02x\n", test_byte);
78a6d74e 627 return -EIO;
2d56f3bb
JFM
628 }
629 reg_w_buf(gspca_dev, n2, sizeof n2);
fadc7993 630 }
6a7eba24 631
fadc7993 632 i = 0;
6a7eba24 633 while (read_indexs[i] != 0x00) {
fadc7993
JFM
634 test_byte = reg_r(gspca_dev, read_indexs[i]);
635 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
6a7eba24
JFM
636 test_byte);
637 i++;
638 }
639
78a6d74e
JFM
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);
ad62fb08 643
00e8006d
NW
644 if (sd->sensor == SENSOR_LT168G) {
645 test_byte = reg_r(gspca_dev, 0x80);
646 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
647 test_byte);
648 reg_w(gspca_dev, 0x6c80);
649 }
650
78a6d74e
JFM
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);
ad62fb08 654
78a6d74e
JFM
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);
9bf81642
HV
658 reg_w(gspca_dev, (0x20 << 8) + 0x87);
659 reg_w(gspca_dev, (0x20 << 8) + 0x88);
660 reg_w(gspca_dev, (0x20 << 8) + 0x89);
fadc7993 661
78a6d74e
JFM
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);
ad62fb08 665
00e8006d
NW
666 if (sd->sensor == SENSOR_LT168G) {
667 test_byte = reg_r(gspca_dev, 0x80);
668 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
669 test_byte);
670 reg_w(gspca_dev, 0x6c80);
671 }
672
78a6d74e
JFM
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);
6a7eba24 676
012d6b02
JFM
677 return 0;
678}
679
9bf81642 680static void setmirror(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 681{
cd8955b8 682 u8 hflipcmd[8] =
fadc7993 683 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
6a7eba24 684
9bf81642 685 if (val)
cd8955b8 686 hflipcmd[3] = 0x01;
6a7eba24 687
cd8955b8 688 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
6a7eba24
JFM
689}
690
9bf81642 691static void seteffect(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 692{
9bf81642 693 int idx = 0;
6a7eba24 694
9bf81642
HV
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;
6a7eba24
JFM
712 }
713
9bf81642
HV
714 reg_w_buf(gspca_dev, effects_table[idx],
715 sizeof effects_table[0]);
716
717 if (val == V4L2_COLORFX_SKETCH)
fadc7993 718 reg_w(gspca_dev, 0x4aa6);
6a7eba24 719 else
fadc7993 720 reg_w(gspca_dev, 0xfaa6);
6a7eba24
JFM
721}
722
ad62fb08
LC
723/* Is this really needed?
724 * i added some module parameters for test with some users */
725static void poll_sensor(struct gspca_dev *gspca_dev)
726{
82e25491 727 static const u8 poll1[] =
ad62fb08
LC
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};
82e25491 732 static const u8 poll2[] =
ad62fb08
LC
733 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
734 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
98388241 735 static const u8 noise03[] = /* (some differences / ms-drv) */
ad62fb08
LC
736 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
737 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
738 0xc2, 0x80, 0xc3, 0x10};
739
78a6d74e
JFM
740 PDEBUG(D_STREAM, "[Sensor requires polling]");
741 reg_w_buf(gspca_dev, poll1, sizeof poll1);
742 reg_w_buf(gspca_dev, poll2, sizeof poll2);
98388241 743 reg_w_buf(gspca_dev, noise03, sizeof noise03);
ad62fb08
LC
744}
745
fadc7993
JFM
746static int sd_start(struct gspca_dev *gspca_dev)
747{
748 struct sd *sd = (struct sd *) gspca_dev;
78a6d74e 749 const struct additional_sensor_data *sensor;
fadc7993 750 int i, mode;
82e25491
JFM
751 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
752 static const u8 t3[] =
753 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
fadc7993 754
78a6d74e 755 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
fadc7993 756 switch (mode) {
82e25491
JFM
757 case 0: /* 640x480 (0x00) */
758 break;
fadc7993
JFM
759 case 1: /* 352x288 */
760 t2[1] = 0x40;
761 break;
762 case 2: /* 320x240 */
763 t2[1] = 0x10;
764 break;
765 case 3: /* 176x144 */
766 t2[1] = 0x50;
767 break;
82e25491
JFM
768 default:
769/* case 4: * 160x120 */
fadc7993
JFM
770 t2[1] = 0x20;
771 break;
fadc7993
JFM
772 }
773
2d56f3bb
JFM
774 switch (sd->sensor) {
775 case SENSOR_OM6802:
776 om6802_sensor_init(gspca_dev);
777 break;
cd8955b8 778 case SENSOR_TAS5130A:
fadc7993 779 i = 0;
78a6d74e 780 for (;;) {
f89be036 781 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
fadc7993 782 sizeof tas5130a_sensor_init[0]);
78a6d74e
JFM
783 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
784 break;
fadc7993
JFM
785 i++;
786 }
787 reg_w(gspca_dev, 0x3c80);
788 /* just in case and to keep sync with logs (for mine) */
78a6d74e 789 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
fadc7993
JFM
790 sizeof tas5130a_sensor_init[0]);
791 reg_w(gspca_dev, 0x3c80);
2d56f3bb 792 break;
fadc7993 793 }
78a6d74e 794 sensor = &sensor_data[sd->sensor];
9bf81642 795 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
fadc7993 796 reg_r(gspca_dev, 0x0012);
ad62fb08 797 reg_w_buf(gspca_dev, t2, sizeof t2);
82e25491 798 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
fadc7993 799 reg_w(gspca_dev, 0x0013);
ad62fb08 800 msleep(15);
78a6d74e
JFM
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);
ad62fb08 806
fadc7993
JFM
807 return 0;
808}
809
eb229b22
JFM
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);
eb229b22
JFM
816 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
817 sizeof sensor_data[sd->sensor].stream);
78a6d74e 818 if (sd->sensor == SENSOR_OM6802) {
2d56f3bb
JFM
819 msleep(20);
820 reg_w(gspca_dev, 0x0309);
821 }
f8d26879 822#if IS_ENABLED(CONFIG_INPUT)
ee186fd9
HG
823 /* If the last button state is pressed, release it now! */
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
eb229b22
JFM
830}
831
fadc7993 832static void sd_pkt_scan(struct gspca_dev *gspca_dev,
82e25491 833 u8 *data, /* isoc packet */
fadc7993
JFM
834 int len) /* iso packet length */
835{
d7e92e15 836 struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
ebb78c5a 837 int pkt_type;
fadc7993
JFM
838
839 if (data[0] == 0x5a) {
f8d26879 840#if IS_ENABLED(CONFIG_INPUT)
ee186fd9
HG
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
fadc7993
JFM
851 /* Control Packet, after this came the header again,
852 * but extra bytes came in the packet before this,
853 * sometimes an EOF arrives, sometimes not... */
854 return;
855 }
856 data += 2;
857 len -= 2;
ebb78c5a
JFM
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);
6a7eba24
JFM
865}
866
9bf81642 867static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
6a7eba24 868{
9bf81642
HV
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 }
6a7eba24
JFM
901 return 0;
902}
903
9bf81642 904static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
6a7eba24 905{
9bf81642
HV
906 struct gspca_dev *gspca_dev =
907 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
6a7eba24 908
9bf81642 909 gspca_dev->usb_err = 0;
6a7eba24 910
9bf81642
HV
911 if (!gspca_dev->streaming)
912 return 0;
6a7eba24 913
9bf81642
HV
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;
6a7eba24
JFM
947}
948
9bf81642
HV
949static const struct v4l2_ctrl_ops sd_ctrl_ops = {
950 .g_volatile_ctrl = sd_g_volatile_ctrl,
951 .s_ctrl = sd_s_ctrl,
952};
6a7eba24 953
9bf81642 954static int sd_init_controls(struct gspca_dev *gspca_dev)
6a7eba24 955{
9bf81642
HV
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 /* Activate lowlight, some apps dont bring up the
970 backlight_compensation control) */
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 }
6a7eba24 1003
9bf81642 1004 v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
6a7eba24 1005
6a7eba24
JFM
1006 return 0;
1007}
1008
6a7eba24 1009/* sub-driver description */
a5ae2062 1010static const struct sd_desc sd_desc = {
6a7eba24 1011 .name = MODULE_NAME,
6a7eba24 1012 .config = sd_config,
012d6b02 1013 .init = sd_init,
9bf81642 1014 .init_controls = sd_init_controls,
6a7eba24 1015 .start = sd_start,
eb229b22 1016 .stopN = sd_stopN,
6a7eba24 1017 .pkt_scan = sd_pkt_scan,
f8d26879 1018#if IS_ENABLED(CONFIG_INPUT)
ee186fd9
HG
1019 .other_input = 1,
1020#endif
6a7eba24
JFM
1021};
1022
1023/* -- module initialisation -- */
95c967c1 1024static const struct usb_device_id device_table[] = {
9d64fdb1 1025 {USB_DEVICE(0x17a1, 0x0128)},
6a7eba24
JFM
1026 {}
1027};
6a7eba24
JFM
1028MODULE_DEVICE_TABLE(usb, device_table);
1029
1030/* -- device connect -- */
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,
6a709749
JFM
1043#ifdef CONFIG_PM
1044 .suspend = gspca_suspend,
1045 .resume = gspca_resume,
8bb58964 1046 .reset_resume = gspca_resume,
6a709749 1047#endif
6a7eba24
JFM
1048};
1049
ecb3b2b3 1050module_usb_driver(sd_driver);