blob: 668a7536af90707686b3c12f761af86657b41507 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030017 *
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
24 * Costantino Leandro
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030025 */
26
27#define MODULE_NAME "t613"
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030028
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030031#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
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 */
39
Jean-Francois Moine82e25492009-01-22 07:18:48 -030040 u8 brightness;
41 u8 contrast;
42 u8 colors;
43 u8 autogain;
44 u8 gamma;
45 u8 sharpness;
46 u8 freq;
47 u8 whitebalance;
48 u8 mirror;
49 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030050
Jean-Francois Moine82e25492009-01-22 07:18:48 -030051 u8 sensor;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -030052#define SENSOR_OM6802 0
53#define SENSOR_OTHER 1
54#define SENSOR_TAS5130A 2
Nicolau Werneck00e80062010-01-30 16:00:15 -030055#define SENSOR_LT168G 3 /* must verify if this is the actual model */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056};
57
58/* V4L2 controls supported by the driver */
59static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_querymenu(struct gspca_dev *gspca_dev,
80 struct v4l2_querymenu *menu);
81
Marton Nemeth7e64dc42009-12-30 09:12:41 -030082static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 {
84 {
85 .id = V4L2_CID_BRIGHTNESS,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Brightness",
88 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030089 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030090 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -030091#define BRIGHTNESS_DEF 8
92 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093 },
94 .set = sd_setbrightness,
95 .get = sd_getbrightness,
96 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 {
98 {
99 .id = V4L2_CID_CONTRAST,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Contrast",
102 .minimum = 0,
103 .maximum = 0x0d,
104 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300105#define CONTRAST_DEF 0x07
106 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300107 },
108 .set = sd_setcontrast,
109 .get = sd_getcontrast,
110 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 {
112 {
113 .id = V4L2_CID_SATURATION,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Color",
116 .minimum = 0,
117 .maximum = 0x0f,
118 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300119#define COLORS_DEF 0x05
120 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121 },
122 .set = sd_setcolors,
123 .get = sd_getcolors,
124 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300125#define GAMMA_MAX 16
126#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127 {
128 {
129 .id = V4L2_CID_GAMMA, /* (gamma on win) */
130 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300131 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300132 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300133 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300135 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300136 },
137 .set = sd_setgamma,
138 .get = sd_getgamma,
139 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140 {
141 {
142 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
143 * some apps dont bring up the
144 * backligth_compensation control) */
145 .type = V4L2_CTRL_TYPE_INTEGER,
146 .name = "Low Light",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300150#define AUTOGAIN_DEF 0x01
151 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152 },
153 .set = sd_setlowlight,
154 .get = sd_getlowlight,
155 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156 {
157 {
158 .id = V4L2_CID_HFLIP,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Mirror Image",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300164#define MIRROR_DEF 0
165 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166 },
167 .set = sd_setflip,
168 .get = sd_getflip
169 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170 {
171 {
172 .id = V4L2_CID_POWER_LINE_FREQUENCY,
173 .type = V4L2_CTRL_TYPE_MENU,
174 .name = "Light Frequency Filter",
175 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
176 .maximum = 2,
177 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300178#define FREQ_DEF 1
179 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180 },
181 .set = sd_setfreq,
182 .get = sd_getfreq},
183
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 {
185 {
186 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "White Balance",
189 .minimum = 0,
190 .maximum = 1,
191 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300192#define WHITE_BALANCE_DEF 0
193 .default_value = WHITE_BALANCE_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300194 },
195 .set = sd_setwhitebalance,
196 .get = sd_getwhitebalance
197 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300198 {
199 {
200 .id = V4L2_CID_SHARPNESS,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 .name = "Sharpness",
203 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300204 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300205 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300206#define SHARPNESS_DEF 0x06
207 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300208 },
209 .set = sd_setsharpness,
210 .get = sd_getsharpness,
211 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 {
213 {
214 .id = V4L2_CID_EFFECTS,
215 .type = V4L2_CTRL_TYPE_MENU,
216 .name = "Webcam Effects",
217 .minimum = 0,
218 .maximum = 4,
219 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300220#define EFFECTS_DEF 0
221 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300222 },
223 .set = sd_seteffect,
224 .get = sd_geteffect
225 },
226};
227
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300228static char *effects_control[] = {
229 "Normal",
230 "Emboss", /* disabled */
231 "Monochrome",
232 "Sepia",
233 "Sketch",
234 "Sun Effect", /* disabled */
235 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236};
237
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300238static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300239 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
240 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300241 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300242 .colorspace = V4L2_COLORSPACE_JPEG,
243 .priv = 4},
244 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
245 .bytesperline = 176,
246 .sizeimage = 176 * 144 * 3 / 8 + 590,
247 .colorspace = V4L2_COLORSPACE_JPEG,
248 .priv = 3},
249 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
250 .bytesperline = 320,
251 .sizeimage = 320 * 240 * 3 / 8 + 590,
252 .colorspace = V4L2_COLORSPACE_JPEG,
253 .priv = 2},
254 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
255 .bytesperline = 352,
256 .sizeimage = 352 * 288 * 3 / 8 + 590,
257 .colorspace = V4L2_COLORSPACE_JPEG,
258 .priv = 1},
259 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
260 .bytesperline = 640,
261 .sizeimage = 640 * 480 * 3 / 8 + 590,
262 .colorspace = V4L2_COLORSPACE_JPEG,
263 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300264};
265
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300266/* sensor specific data */
267struct additional_sensor_data {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300268 const u8 n3[6];
269 const u8 *n4, n4sz;
270 const u8 reg80, reg8e;
271 const u8 nset8[6];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300272 const u8 data1[10];
273 const u8 data2[9];
274 const u8 data3[9];
275 const u8 data4[4];
276 const u8 data5[6];
277 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300278};
279
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300280static const u8 n4_om6802[] = {
281 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
282 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
283 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
284 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
285 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
286 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
287 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
288 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
289 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
290};
291static const u8 n4_other[] = {
292 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
293 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
294 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
295 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
296 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
297 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
298 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
299 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
300};
301static const u8 n4_tas5130a[] = {
302 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
303 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
304 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
305 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
306 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
307 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
308 0xc6, 0xda
309};
Nicolau Werneck00e80062010-01-30 16:00:15 -0300310static const u8 n4_lt168g[] = {
311 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
312 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
313 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
314 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
315 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
316 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
317 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
318 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
319 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
320};
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300321
Tobias Klausere23b2902009-02-09 18:06:49 -0300322static const struct additional_sensor_data sensor_data[] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300323 { /* 0: OM6802 */
324 .n3 =
325 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
326 .n4 = n4_om6802,
327 .n4sz = sizeof n4_om6802,
328 .reg80 = 0x3c,
329 .reg8e = 0x33,
330 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300331 .data1 =
332 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
333 0xb3, 0xfc},
334 .data2 =
335 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
336 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300337 .data3 =
338 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
339 0xff},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300340 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
341 {0x66, 0xca, 0xa8, 0xf0},
342 .data5 = /* this could be removed later */
343 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
344 .stream =
345 {0x0b, 0x04, 0x0a, 0x78},
346 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300347 { /* 1: OTHER */
348 .n3 =
349 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
350 .n4 = n4_other,
351 .n4sz = sizeof n4_other,
352 .reg80 = 0xac,
353 .reg8e = 0xb8,
354 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300355 .data1 =
356 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
357 0xe8, 0xfc},
358 .data2 =
359 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
360 0xd9},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300361 .data3 =
362 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
363 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300364 .data4 =
365 {0x66, 0x00, 0xa8, 0xa8},
366 .data5 =
367 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
368 .stream =
369 {0x0b, 0x04, 0x0a, 0x00},
370 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300371 { /* 2: TAS5130A */
372 .n3 =
373 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
374 .n4 = n4_tas5130a,
375 .n4sz = sizeof n4_tas5130a,
376 .reg80 = 0x3c,
377 .reg8e = 0xb4,
378 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300379 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300380 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
381 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300382 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300383 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
384 0xe0},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300385 .data3 =
386 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
387 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300388 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
389 {0x66, 0x00, 0xa8, 0xe8},
390 .data5 =
391 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
392 .stream =
393 {0x0b, 0x04, 0x0a, 0x40},
394 },
Nicolau Werneck00e80062010-01-30 16:00:15 -0300395 { /* 3: LT168G */
396 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
397 .n4 = n4_lt168g,
398 .n4sz = sizeof n4_lt168g,
399 .reg80 = 0x7c,
400 .reg8e = 0xb3,
401 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
402 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
403 0xb0, 0xf4},
404 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
405 0xff},
406 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
407 0xff},
408 .data4 = {0x66, 0x41, 0xa8, 0xf0},
409 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
410 .stream = {0x0b, 0x04, 0x0a, 0x28},
411 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300412};
413
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300414#define MAX_EFFECTS 7
415/* easily done by soft, this table could be removed,
416 * i keep it here just in case */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300417static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300418 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
419 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
420 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
421 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
422 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
423 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
424 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
425};
426
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300427static const u8 gamma_table[GAMMA_MAX][17] = {
428 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
429 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
430 0xff},
431 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
432 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
433 0xff},
434 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
435 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
436 0xff},
437 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
438 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
439 0xff},
440 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
441 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
442 0xff},
443 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
444 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
445 0xff},
446 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
447 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
448 0xff},
449 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
450 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
451 0xff},
452 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
453 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
454 0xff},
455 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
456 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
457 0xff},
458 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
459 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
460 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300461 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300462 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
463 0xff},
464 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
465 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
466 0xff},
467 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
468 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
469 0xff},
470 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
471 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
472 0xff},
473 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
474 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
475 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300476};
477
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300478static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300479 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
480 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
481 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300482};
483
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300484static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300485
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300486/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300487static u8 reg_r(struct gspca_dev *gspca_dev,
488 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300490 usb_control_msg(gspca_dev->dev,
491 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492 0, /* request */
493 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
494 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300495 index,
496 gspca_dev->usb_buf, 1, 500);
497 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300498}
499
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300500static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300501 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300502{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300503 usb_control_msg(gspca_dev->dev,
504 usb_sndctrlpipe(gspca_dev->dev, 0),
505 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300506 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300507 0, index,
508 NULL, 0, 500);
509}
510
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300511static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300512 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300513{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300514 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300515 memcpy(gspca_dev->usb_buf, buffer, len);
516 usb_control_msg(gspca_dev->dev,
517 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300518 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300519 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300520 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300521 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300522 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300523 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300524
525 tmpbuf = kmalloc(len, GFP_KERNEL);
526 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 usb_control_msg(gspca_dev->dev,
528 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300529 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300530 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300531 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300532 tmpbuf, len, 500);
533 kfree(tmpbuf);
534 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535}
536
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300537/* write values to consecutive registers */
538static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
539 u8 reg,
540 const u8 *buffer, u16 len)
541{
542 int i;
543 u8 *p, *tmpbuf;
544
545 if (len * 2 <= USB_BUF_SZ)
546 p = tmpbuf = gspca_dev->usb_buf;
547 else
548 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
549 i = len;
550 while (--i >= 0) {
551 *p++ = reg++;
552 *p++ = *buffer++;
553 }
554 usb_control_msg(gspca_dev->dev,
555 usb_sndctrlpipe(gspca_dev->dev, 0),
556 0,
557 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
558 0x01, 0,
559 tmpbuf, len * 2, 500);
560 if (len * 2 > USB_BUF_SZ)
561 kfree(tmpbuf);
562}
563
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300564/* Reported as OM6802*/
565static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300566{
567 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300568 const u8 *p;
569 u8 byte;
570 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
571 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300572 0xdf, 0x6d,
573 0xdd, 0x18,
574 0x5a, 0xe0,
575 0x5c, 0x07,
576 0x5d, 0xb0,
577 0x5e, 0x1e,
578 0x60, 0x71,
579 0xef, 0x00,
580 0xe9, 0x00,
581 0xea, 0x00,
582 0x90, 0x24,
583 0x91, 0xb2,
584 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300585 0xfd, 0x41,
586 0x00 /* table end */
587 };
588
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300589 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300590 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300591 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300592 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300593 byte = reg_r(gspca_dev, 0x0060);
594 if (!(byte & 0x01))
595 break;
596 msleep(100);
597 }
598 byte = reg_r(gspca_dev, 0x0063);
599 if (byte != 0x17) {
600 err("Bad sensor reset %02x", byte);
601 /* continue? */
602 }
603
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300604 p = sensor_init;
605 while (*p != 0) {
606 val[1] = *p++;
607 val[3] = *p++;
608 if (*p == 0)
609 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300610 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300611 i = 4;
612 while (--i >= 0) {
613 msleep(15);
614 byte = reg_r(gspca_dev, 0x60);
615 if (!(byte & 0x01))
616 break;
617 }
618 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300619 msleep(15);
620 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300621}
622
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623/* this function is called at probe time */
624static int sd_config(struct gspca_dev *gspca_dev,
625 const struct usb_device_id *id)
626{
627 struct sd *sd = (struct sd *) gspca_dev;
628 struct cam *cam;
629
630 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631
632 cam->cam_mode = vga_mode_t16;
633 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
634
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300635 sd->brightness = BRIGHTNESS_DEF;
636 sd->contrast = CONTRAST_DEF;
637 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300638 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300639 sd->autogain = AUTOGAIN_DEF;
640 sd->mirror = MIRROR_DEF;
641 sd->freq = FREQ_DEF;
642 sd->whitebalance = WHITE_BALANCE_DEF;
643 sd->sharpness = SHARPNESS_DEF;
644 sd->effect = EFFECTS_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 return 0;
646}
647
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300648static void setbrightness(struct gspca_dev *gspca_dev)
649{
650 struct sd *sd = (struct sd *) gspca_dev;
651 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300652 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300653
654 brightness = sd->brightness;
655 if (brightness < 7) {
656 set6[1] = 0x26;
657 set6[3] = 0x70 - brightness * 0x10;
658 } else {
659 set6[3] = 0x00 + ((brightness - 7) * 0x10);
660 }
661
662 reg_w_buf(gspca_dev, set6, sizeof set6);
663}
664
665static void setcontrast(struct gspca_dev *gspca_dev)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
668 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300669 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300670
671 if (contrast < 7)
672 reg_to_write = 0x8ea9 - contrast * 0x200;
673 else
674 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
675
676 reg_w(gspca_dev, reg_to_write);
677}
678
679static void setcolors(struct gspca_dev *gspca_dev)
680{
681 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300682 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300683
684 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
685 reg_w(gspca_dev, reg_to_write);
686}
687
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300688static void setgamma(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300693 reg_w_ixbuf(gspca_dev, 0x90,
694 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300695}
696
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300697static void setwhitebalance(struct gspca_dev *gspca_dev)
698{
699 struct sd *sd = (struct sd *) gspca_dev;
700
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300701 u8 white_balance[8] =
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300702 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
703
704 if (sd->whitebalance)
705 white_balance[7] = 0x3c;
706
707 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
708}
709
710static void setsharpness(struct gspca_dev *gspca_dev)
711{
712 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300713 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300714
715 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
716
717 reg_w(gspca_dev, reg_to_write);
718}
719
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300720/* this function is called at probe and resume time */
721static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723 /* some of this registers are not really neded, because
724 * they are overriden by setbrigthness, setcontrast, etc,
725 * but wont hurt anyway, and can help someone with similar webcam
726 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300727 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300728 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300729 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300730 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300731 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300733 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300734 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300735 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
736 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300738 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300741 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
742 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300743 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300744 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300745 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300746 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300747 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300748 case 0x0802:
749 PDEBUG(D_PROBE, "sensor lt168g");
750 sd->sensor = SENSOR_LT168G;
751 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300752 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300753 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300754 sd->sensor = SENSOR_OTHER;
755 break;
756 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300757 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300758 sd->sensor = SENSOR_OM6802;
759 break;
760 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300761 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300762 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300763 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300765 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300766 reg_w_buf(gspca_dev, n1, sizeof n1);
767 i = 5;
768 while (--i >= 0) {
769 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
770 test_byte = reg_r(gspca_dev, 0x0063);
771 msleep(100);
772 if (test_byte == 0x17)
773 break; /* OK */
774 }
775 if (i < 0) {
776 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300777 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300778 }
779 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300780 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300781
782 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300784 test_byte = reg_r(gspca_dev, read_indexs[i]);
785 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786 test_byte);
787 i++;
788 }
789
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300790 sensor = &sensor_data[sd->sensor];
791 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
792 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300793
Nicolau Werneck00e80062010-01-30 16:00:15 -0300794 if (sd->sensor == SENSOR_LT168G) {
795 test_byte = reg_r(gspca_dev, 0x80);
796 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
797 test_byte);
798 reg_w(gspca_dev, 0x6c80);
799 }
800
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300801 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
802 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
803 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300804
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300805 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
806 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
807 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300808
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300809 setbrightness(gspca_dev);
810 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300811 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300812 setcolors(gspca_dev);
813 setsharpness(gspca_dev);
814 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300815
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300816 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300817 reg_w(gspca_dev, 0x2088);
818 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300819
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300820 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
821 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
822 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
823 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300824
Nicolau Werneck00e80062010-01-30 16:00:15 -0300825 if (sd->sensor == SENSOR_LT168G) {
826 test_byte = reg_r(gspca_dev, 0x80);
827 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
828 test_byte);
829 reg_w(gspca_dev, 0x6c80);
830 }
831
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300832 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
833 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
834 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
836 return 0;
837}
838
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839static void setflip(struct gspca_dev *gspca_dev)
840{
841 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300842 u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300843 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300845 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846 flipcmd[3] = 0x01;
847
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300848 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849}
850
851static void seteffect(struct gspca_dev *gspca_dev)
852{
853 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300855 reg_w_buf(gspca_dev, effects_table[sd->effect],
856 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857 if (sd->effect == 1 || sd->effect == 5) {
858 PDEBUG(D_CONF,
859 "This effect have been disabled for webcam \"safety\"");
860 return;
861 }
862
863 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300864 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300866 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867}
868
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869static void setlightfreq(struct gspca_dev *gspca_dev)
870{
871 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300872 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873
874 if (sd->freq == 2) /* 60hz */
875 freq[1] = 0x00;
876
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300877 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878}
879
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300880/* Is this really needed?
881 * i added some module parameters for test with some users */
882static void poll_sensor(struct gspca_dev *gspca_dev)
883{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300884 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300885 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
886 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
887 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
888 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300889 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300890 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
891 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300892 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300893 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300894 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300895 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
896 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
897 0xc2, 0x80, 0xc3, 0x10};
898
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300899 PDEBUG(D_STREAM, "[Sensor requires polling]");
900 reg_w_buf(gspca_dev, poll1, sizeof poll1);
901 reg_w_buf(gspca_dev, poll2, sizeof poll2);
902 reg_w_buf(gspca_dev, poll3, sizeof poll3);
903 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300904}
905
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300906static int sd_start(struct gspca_dev *gspca_dev)
907{
908 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300909 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300910 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300911 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
912 static const u8 t3[] =
913 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300914
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300915 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300916 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300917 case 0: /* 640x480 (0x00) */
918 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300919 case 1: /* 352x288 */
920 t2[1] = 0x40;
921 break;
922 case 2: /* 320x240 */
923 t2[1] = 0x10;
924 break;
925 case 3: /* 176x144 */
926 t2[1] = 0x50;
927 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300928 default:
929/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300930 t2[1] = 0x20;
931 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300932 }
933
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300934 switch (sd->sensor) {
935 case SENSOR_OM6802:
936 om6802_sensor_init(gspca_dev);
937 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300938 case SENSOR_LT168G:
939 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300940 case SENSOR_OTHER:
941 break;
942 default:
943/* case SENSOR_TAS5130A: */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300944 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300945 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300946 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300947 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300948 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
949 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300950 i++;
951 }
952 reg_w(gspca_dev, 0x3c80);
953 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300954 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300955 sizeof tas5130a_sensor_init[0]);
956 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300957 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300958 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300959 sensor = &sensor_data[sd->sensor];
960 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300961 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300962 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300963 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300964 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300965 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300966 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
967 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300968
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300969 if (sd->sensor == SENSOR_OM6802)
970 poll_sensor(gspca_dev);
971
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300972 return 0;
973}
974
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300975static void sd_stopN(struct gspca_dev *gspca_dev)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
980 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300981 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
982 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300983 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300984 msleep(20);
985 reg_w(gspca_dev, 0x0309);
986 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300987}
988
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300989static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300990 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300991 int len) /* iso packet length */
992{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300993 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300994
995 if (data[0] == 0x5a) {
996 /* Control Packet, after this came the header again,
997 * but extra bytes came in the packet before this,
998 * sometimes an EOF arrives, sometimes not... */
999 return;
1000 }
1001 data += 2;
1002 len -= 2;
1003 if (data[0] == 0xff && data[1] == 0xd8) {
1004 /* extra bytes....., could be processed too but would be
1005 * a waste of time, right now leave the application and
1006 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001007 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001008 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001009 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001010 return;
1011 }
1012
1013 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1014 /* Just in case, i have seen packets with the marker,
1015 * other's do not include it... */
1016 len -= 2;
1017 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001018 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019}
1020
1021static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1022{
1023 struct sd *sd = (struct sd *) gspca_dev;
1024
1025 sd->brightness = val;
1026 if (gspca_dev->streaming)
1027 setbrightness(gspca_dev);
1028 return 0;
1029}
1030
1031static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1032{
1033 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001034
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001035 *val = sd->brightness;
1036 return *val;
1037}
1038
1039static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
1040{
1041 struct sd *sd = (struct sd *) gspca_dev;
1042
1043 sd->whitebalance = val;
1044 if (gspca_dev->streaming)
1045 setwhitebalance(gspca_dev);
1046 return 0;
1047}
1048
1049static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052
1053 *val = sd->whitebalance;
1054 return *val;
1055}
1056
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1058{
1059 struct sd *sd = (struct sd *) gspca_dev;
1060
1061 sd->mirror = val;
1062 if (gspca_dev->streaming)
1063 setflip(gspca_dev);
1064 return 0;
1065}
1066
1067static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1068{
1069 struct sd *sd = (struct sd *) gspca_dev;
1070
1071 *val = sd->mirror;
1072 return *val;
1073}
1074
1075static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1076{
1077 struct sd *sd = (struct sd *) gspca_dev;
1078
1079 sd->effect = val;
1080 if (gspca_dev->streaming)
1081 seteffect(gspca_dev);
1082 return 0;
1083}
1084
1085static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1086{
1087 struct sd *sd = (struct sd *) gspca_dev;
1088
1089 *val = sd->effect;
1090 return *val;
1091}
1092
1093static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1094{
1095 struct sd *sd = (struct sd *) gspca_dev;
1096
1097 sd->contrast = val;
1098 if (gspca_dev->streaming)
1099 setcontrast(gspca_dev);
1100 return 0;
1101}
1102
1103static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106
1107 *val = sd->contrast;
1108 return *val;
1109}
1110
1111static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1112{
1113 struct sd *sd = (struct sd *) gspca_dev;
1114
1115 sd->colors = val;
1116 if (gspca_dev->streaming)
1117 setcolors(gspca_dev);
1118 return 0;
1119}
1120
1121static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1122{
1123 struct sd *sd = (struct sd *) gspca_dev;
1124
1125 *val = sd->colors;
1126 return 0;
1127}
1128
1129static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132
1133 sd->gamma = val;
1134 if (gspca_dev->streaming)
1135 setgamma(gspca_dev);
1136 return 0;
1137}
1138
1139static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001142
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143 *val = sd->gamma;
1144 return 0;
1145}
1146
1147static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1148{
1149 struct sd *sd = (struct sd *) gspca_dev;
1150
1151 sd->freq = val;
1152 if (gspca_dev->streaming)
1153 setlightfreq(gspca_dev);
1154 return 0;
1155}
1156
1157static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1158{
1159 struct sd *sd = (struct sd *) gspca_dev;
1160
1161 *val = sd->freq;
1162 return 0;
1163}
1164
1165static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1166{
1167 struct sd *sd = (struct sd *) gspca_dev;
1168
1169 sd->sharpness = val;
1170 if (gspca_dev->streaming)
1171 setsharpness(gspca_dev);
1172 return 0;
1173}
1174
1175static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1176{
1177 struct sd *sd = (struct sd *) gspca_dev;
1178
1179 *val = sd->sharpness;
1180 return 0;
1181}
1182
1183/* Low Light set here......*/
1184static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1185{
1186 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001187
1188 sd->autogain = val;
1189 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001190 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001192 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001193 return 0;
1194}
1195
1196static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1197{
1198 struct sd *sd = (struct sd *) gspca_dev;
1199
1200 *val = sd->autogain;
1201 return 0;
1202}
1203
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001204static int sd_querymenu(struct gspca_dev *gspca_dev,
1205 struct v4l2_querymenu *menu)
1206{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001207 switch (menu->id) {
1208 case V4L2_CID_POWER_LINE_FREQUENCY:
1209 switch (menu->index) {
1210 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001211 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212 return 0;
1213 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001214 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001215 return 0;
1216 }
1217 break;
1218 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001219 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1220 strncpy((char *) menu->name,
1221 effects_control[menu->index], 32);
1222 return 0;
1223 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001224 break;
1225 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001226 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227}
1228
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001230static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231 .name = MODULE_NAME,
1232 .ctrls = sd_ctrls,
1233 .nctrls = ARRAY_SIZE(sd_ctrls),
1234 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001235 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001236 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001237 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238 .pkt_scan = sd_pkt_scan,
1239 .querymenu = sd_querymenu,
1240};
1241
1242/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001243static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001244 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001245 {}
1246};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001247MODULE_DEVICE_TABLE(usb, device_table);
1248
1249/* -- device connect -- */
1250static int sd_probe(struct usb_interface *intf,
1251 const struct usb_device_id *id)
1252{
1253 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1254 THIS_MODULE);
1255}
1256
1257static struct usb_driver sd_driver = {
1258 .name = MODULE_NAME,
1259 .id_table = device_table,
1260 .probe = sd_probe,
1261 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001262#ifdef CONFIG_PM
1263 .suspend = gspca_suspend,
1264 .resume = gspca_resume,
1265#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001266};
1267
1268/* -- module insert / remove -- */
1269static int __init sd_mod_init(void)
1270{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001271 int ret;
1272 ret = usb_register(&sd_driver);
1273 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001274 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001275 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001276 return 0;
1277}
1278static void __exit sd_mod_exit(void)
1279{
1280 usb_deregister(&sd_driver);
1281 PDEBUG(D_PROBE, "deregistered");
1282}
1283
1284module_init(sd_mod_init);
1285module_exit(sd_mod_exit);