blob: 8c7dadef8211f5c72c18e8aa953801fe8a276431 [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);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300526 if (!tmpbuf) {
527 err("Out of memory");
528 return;
529 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300530 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531 usb_control_msg(gspca_dev->dev,
532 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300533 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300534 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300535 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300536 tmpbuf, len, 500);
537 kfree(tmpbuf);
538 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539}
540
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300541/* write values to consecutive registers */
542static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
543 u8 reg,
544 const u8 *buffer, u16 len)
545{
546 int i;
547 u8 *p, *tmpbuf;
548
Jean-François Moine24f222e2010-03-07 05:58:55 -0300549 if (len * 2 <= USB_BUF_SZ) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300550 p = tmpbuf = gspca_dev->usb_buf;
Jean-François Moine24f222e2010-03-07 05:58:55 -0300551 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300552 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300553 if (!tmpbuf) {
554 err("Out of memory");
555 return;
556 }
557 }
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300558 i = len;
559 while (--i >= 0) {
560 *p++ = reg++;
561 *p++ = *buffer++;
562 }
563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
565 0,
566 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
567 0x01, 0,
568 tmpbuf, len * 2, 500);
569 if (len * 2 > USB_BUF_SZ)
570 kfree(tmpbuf);
571}
572
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300573/* Reported as OM6802*/
574static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300575{
576 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300577 const u8 *p;
578 u8 byte;
579 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
580 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300581 0xdf, 0x6d,
582 0xdd, 0x18,
583 0x5a, 0xe0,
584 0x5c, 0x07,
585 0x5d, 0xb0,
586 0x5e, 0x1e,
587 0x60, 0x71,
588 0xef, 0x00,
589 0xe9, 0x00,
590 0xea, 0x00,
591 0x90, 0x24,
592 0x91, 0xb2,
593 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300594 0xfd, 0x41,
595 0x00 /* table end */
596 };
597
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300598 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300599 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300600 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300601 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300602 byte = reg_r(gspca_dev, 0x0060);
603 if (!(byte & 0x01))
604 break;
605 msleep(100);
606 }
607 byte = reg_r(gspca_dev, 0x0063);
608 if (byte != 0x17) {
609 err("Bad sensor reset %02x", byte);
610 /* continue? */
611 }
612
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300613 p = sensor_init;
614 while (*p != 0) {
615 val[1] = *p++;
616 val[3] = *p++;
617 if (*p == 0)
618 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300619 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300620 i = 4;
621 while (--i >= 0) {
622 msleep(15);
623 byte = reg_r(gspca_dev, 0x60);
624 if (!(byte & 0x01))
625 break;
626 }
627 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300628 msleep(15);
629 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300630}
631
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632/* this function is called at probe time */
633static int sd_config(struct gspca_dev *gspca_dev,
634 const struct usb_device_id *id)
635{
636 struct sd *sd = (struct sd *) gspca_dev;
637 struct cam *cam;
638
639 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640
641 cam->cam_mode = vga_mode_t16;
642 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
643
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300644 sd->brightness = BRIGHTNESS_DEF;
645 sd->contrast = CONTRAST_DEF;
646 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300647 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300648 sd->autogain = AUTOGAIN_DEF;
649 sd->mirror = MIRROR_DEF;
650 sd->freq = FREQ_DEF;
651 sd->whitebalance = WHITE_BALANCE_DEF;
652 sd->sharpness = SHARPNESS_DEF;
653 sd->effect = EFFECTS_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 return 0;
655}
656
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300657static void setbrightness(struct gspca_dev *gspca_dev)
658{
659 struct sd *sd = (struct sd *) gspca_dev;
660 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300661 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300662
663 brightness = sd->brightness;
664 if (brightness < 7) {
665 set6[1] = 0x26;
666 set6[3] = 0x70 - brightness * 0x10;
667 } else {
668 set6[3] = 0x00 + ((brightness - 7) * 0x10);
669 }
670
671 reg_w_buf(gspca_dev, set6, sizeof set6);
672}
673
674static void setcontrast(struct gspca_dev *gspca_dev)
675{
676 struct sd *sd = (struct sd *) gspca_dev;
677 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300678 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300679
680 if (contrast < 7)
681 reg_to_write = 0x8ea9 - contrast * 0x200;
682 else
683 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
684
685 reg_w(gspca_dev, reg_to_write);
686}
687
688static void setcolors(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300691 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300692
693 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
694 reg_w(gspca_dev, reg_to_write);
695}
696
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300697static void setgamma(struct gspca_dev *gspca_dev)
698{
699 struct sd *sd = (struct sd *) gspca_dev;
700
701 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300702 reg_w_ixbuf(gspca_dev, 0x90,
703 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300704}
705
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300706static void setwhitebalance(struct gspca_dev *gspca_dev)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300710 u8 white_balance[8] =
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300711 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
712
713 if (sd->whitebalance)
714 white_balance[7] = 0x3c;
715
716 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
717}
718
719static void setsharpness(struct gspca_dev *gspca_dev)
720{
721 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300722 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300723
724 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
725
726 reg_w(gspca_dev, reg_to_write);
727}
728
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300729/* this function is called at probe and resume time */
730static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732 /* some of this registers are not really neded, because
733 * they are overriden by setbrigthness, setcontrast, etc,
734 * but wont hurt anyway, and can help someone with similar webcam
735 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300736 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300737 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300738 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300739 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300740 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300742 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300743 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300744 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
745 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300747 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300750 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
751 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300752 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300753 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300754 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300755 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300756 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300757 case 0x0802:
758 PDEBUG(D_PROBE, "sensor lt168g");
759 sd->sensor = SENSOR_LT168G;
760 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300761 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300762 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300763 sd->sensor = SENSOR_OTHER;
764 break;
765 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300766 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300767 sd->sensor = SENSOR_OM6802;
768 break;
769 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300770 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300771 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300772 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300774 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300775 reg_w_buf(gspca_dev, n1, sizeof n1);
776 i = 5;
777 while (--i >= 0) {
778 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
779 test_byte = reg_r(gspca_dev, 0x0063);
780 msleep(100);
781 if (test_byte == 0x17)
782 break; /* OK */
783 }
784 if (i < 0) {
785 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300786 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300787 }
788 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300789 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300790
791 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300793 test_byte = reg_r(gspca_dev, read_indexs[i]);
794 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300795 test_byte);
796 i++;
797 }
798
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300799 sensor = &sensor_data[sd->sensor];
800 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
801 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300802
Nicolau Werneck00e80062010-01-30 16:00:15 -0300803 if (sd->sensor == SENSOR_LT168G) {
804 test_byte = reg_r(gspca_dev, 0x80);
805 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
806 test_byte);
807 reg_w(gspca_dev, 0x6c80);
808 }
809
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300810 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
811 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
812 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300813
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300814 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
815 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
816 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300817
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300818 setbrightness(gspca_dev);
819 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300820 setgamma(gspca_dev);
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300821 setcolors(gspca_dev);
822 setsharpness(gspca_dev);
823 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300825 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300826 reg_w(gspca_dev, 0x2088);
827 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300829 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
830 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
831 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
832 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300833
Nicolau Werneck00e80062010-01-30 16:00:15 -0300834 if (sd->sensor == SENSOR_LT168G) {
835 test_byte = reg_r(gspca_dev, 0x80);
836 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
837 test_byte);
838 reg_w(gspca_dev, 0x6c80);
839 }
840
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300841 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
842 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
843 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844
845 return 0;
846}
847
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848static void setflip(struct gspca_dev *gspca_dev)
849{
850 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300851 u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300852 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300854 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 flipcmd[3] = 0x01;
856
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300857 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858}
859
860static void seteffect(struct gspca_dev *gspca_dev)
861{
862 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300864 reg_w_buf(gspca_dev, effects_table[sd->effect],
865 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 if (sd->effect == 1 || sd->effect == 5) {
867 PDEBUG(D_CONF,
868 "This effect have been disabled for webcam \"safety\"");
869 return;
870 }
871
872 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300873 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300875 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876}
877
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878static void setlightfreq(struct gspca_dev *gspca_dev)
879{
880 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300881 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882
883 if (sd->freq == 2) /* 60hz */
884 freq[1] = 0x00;
885
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300886 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887}
888
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300889/* Is this really needed?
890 * i added some module parameters for test with some users */
891static void poll_sensor(struct gspca_dev *gspca_dev)
892{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300893 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300894 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
895 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
896 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
897 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300898 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300899 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
900 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300901 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300902 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300903 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300904 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
905 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
906 0xc2, 0x80, 0xc3, 0x10};
907
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300908 PDEBUG(D_STREAM, "[Sensor requires polling]");
909 reg_w_buf(gspca_dev, poll1, sizeof poll1);
910 reg_w_buf(gspca_dev, poll2, sizeof poll2);
911 reg_w_buf(gspca_dev, poll3, sizeof poll3);
912 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300913}
914
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300915static int sd_start(struct gspca_dev *gspca_dev)
916{
917 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300918 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300919 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300920 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
921 static const u8 t3[] =
922 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300923
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300924 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300925 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300926 case 0: /* 640x480 (0x00) */
927 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300928 case 1: /* 352x288 */
929 t2[1] = 0x40;
930 break;
931 case 2: /* 320x240 */
932 t2[1] = 0x10;
933 break;
934 case 3: /* 176x144 */
935 t2[1] = 0x50;
936 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300937 default:
938/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300939 t2[1] = 0x20;
940 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300941 }
942
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300943 switch (sd->sensor) {
944 case SENSOR_OM6802:
945 om6802_sensor_init(gspca_dev);
946 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300947 case SENSOR_LT168G:
948 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300949 case SENSOR_OTHER:
950 break;
951 default:
952/* case SENSOR_TAS5130A: */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300953 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300954 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300955 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300956 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300957 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
958 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300959 i++;
960 }
961 reg_w(gspca_dev, 0x3c80);
962 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300963 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300964 sizeof tas5130a_sensor_init[0]);
965 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300966 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300967 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300968 sensor = &sensor_data[sd->sensor];
969 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300970 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300971 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300972 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300973 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300974 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300975 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
976 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300977
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300978 if (sd->sensor == SENSOR_OM6802)
979 poll_sensor(gspca_dev);
980
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300981 return 0;
982}
983
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300984static void sd_stopN(struct gspca_dev *gspca_dev)
985{
986 struct sd *sd = (struct sd *) gspca_dev;
987
988 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
989 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300990 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
991 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300992 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300993 msleep(20);
994 reg_w(gspca_dev, 0x0309);
995 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300996}
997
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300998static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300999 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001000 int len) /* iso packet length */
1001{
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001002 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001003
1004 if (data[0] == 0x5a) {
1005 /* Control Packet, after this came the header again,
1006 * but extra bytes came in the packet before this,
1007 * sometimes an EOF arrives, sometimes not... */
1008 return;
1009 }
1010 data += 2;
1011 len -= 2;
1012 if (data[0] == 0xff && data[1] == 0xd8) {
1013 /* extra bytes....., could be processed too but would be
1014 * a waste of time, right now leave the application and
1015 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001016 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001017 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001018 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001019 return;
1020 }
1021
1022 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1023 /* Just in case, i have seen packets with the marker,
1024 * other's do not include it... */
1025 len -= 2;
1026 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001027 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001028}
1029
1030static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1031{
1032 struct sd *sd = (struct sd *) gspca_dev;
1033
1034 sd->brightness = val;
1035 if (gspca_dev->streaming)
1036 setbrightness(gspca_dev);
1037 return 0;
1038}
1039
1040static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1041{
1042 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001043
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 *val = sd->brightness;
1045 return *val;
1046}
1047
1048static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
1049{
1050 struct sd *sd = (struct sd *) gspca_dev;
1051
1052 sd->whitebalance = val;
1053 if (gspca_dev->streaming)
1054 setwhitebalance(gspca_dev);
1055 return 0;
1056}
1057
1058static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1059{
1060 struct sd *sd = (struct sd *) gspca_dev;
1061
1062 *val = sd->whitebalance;
1063 return *val;
1064}
1065
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001066static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069
1070 sd->mirror = val;
1071 if (gspca_dev->streaming)
1072 setflip(gspca_dev);
1073 return 0;
1074}
1075
1076static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1077{
1078 struct sd *sd = (struct sd *) gspca_dev;
1079
1080 *val = sd->mirror;
1081 return *val;
1082}
1083
1084static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 sd->effect = val;
1089 if (gspca_dev->streaming)
1090 seteffect(gspca_dev);
1091 return 0;
1092}
1093
1094static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1095{
1096 struct sd *sd = (struct sd *) gspca_dev;
1097
1098 *val = sd->effect;
1099 return *val;
1100}
1101
1102static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1103{
1104 struct sd *sd = (struct sd *) gspca_dev;
1105
1106 sd->contrast = val;
1107 if (gspca_dev->streaming)
1108 setcontrast(gspca_dev);
1109 return 0;
1110}
1111
1112static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 *val = sd->contrast;
1117 return *val;
1118}
1119
1120static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1121{
1122 struct sd *sd = (struct sd *) gspca_dev;
1123
1124 sd->colors = val;
1125 if (gspca_dev->streaming)
1126 setcolors(gspca_dev);
1127 return 0;
1128}
1129
1130static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1131{
1132 struct sd *sd = (struct sd *) gspca_dev;
1133
1134 *val = sd->colors;
1135 return 0;
1136}
1137
1138static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1139{
1140 struct sd *sd = (struct sd *) gspca_dev;
1141
1142 sd->gamma = val;
1143 if (gspca_dev->streaming)
1144 setgamma(gspca_dev);
1145 return 0;
1146}
1147
1148static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1149{
1150 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001151
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001152 *val = sd->gamma;
1153 return 0;
1154}
1155
1156static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1157{
1158 struct sd *sd = (struct sd *) gspca_dev;
1159
1160 sd->freq = val;
1161 if (gspca_dev->streaming)
1162 setlightfreq(gspca_dev);
1163 return 0;
1164}
1165
1166static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1167{
1168 struct sd *sd = (struct sd *) gspca_dev;
1169
1170 *val = sd->freq;
1171 return 0;
1172}
1173
1174static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1175{
1176 struct sd *sd = (struct sd *) gspca_dev;
1177
1178 sd->sharpness = val;
1179 if (gspca_dev->streaming)
1180 setsharpness(gspca_dev);
1181 return 0;
1182}
1183
1184static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1185{
1186 struct sd *sd = (struct sd *) gspca_dev;
1187
1188 *val = sd->sharpness;
1189 return 0;
1190}
1191
1192/* Low Light set here......*/
1193static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1194{
1195 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001196
1197 sd->autogain = val;
1198 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001199 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001200 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001201 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001202 return 0;
1203}
1204
1205static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1206{
1207 struct sd *sd = (struct sd *) gspca_dev;
1208
1209 *val = sd->autogain;
1210 return 0;
1211}
1212
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001213static int sd_querymenu(struct gspca_dev *gspca_dev,
1214 struct v4l2_querymenu *menu)
1215{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001216 switch (menu->id) {
1217 case V4L2_CID_POWER_LINE_FREQUENCY:
1218 switch (menu->index) {
1219 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001220 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001221 return 0;
1222 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001223 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001224 return 0;
1225 }
1226 break;
1227 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001228 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1229 strncpy((char *) menu->name,
1230 effects_control[menu->index], 32);
1231 return 0;
1232 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233 break;
1234 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001235 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001236}
1237
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001239static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001240 .name = MODULE_NAME,
1241 .ctrls = sd_ctrls,
1242 .nctrls = ARRAY_SIZE(sd_ctrls),
1243 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001244 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001245 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001246 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001247 .pkt_scan = sd_pkt_scan,
1248 .querymenu = sd_querymenu,
1249};
1250
1251/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001252static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001253 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001254 {}
1255};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001256MODULE_DEVICE_TABLE(usb, device_table);
1257
1258/* -- device connect -- */
1259static int sd_probe(struct usb_interface *intf,
1260 const struct usb_device_id *id)
1261{
1262 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1263 THIS_MODULE);
1264}
1265
1266static struct usb_driver sd_driver = {
1267 .name = MODULE_NAME,
1268 .id_table = device_table,
1269 .probe = sd_probe,
1270 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001271#ifdef CONFIG_PM
1272 .suspend = gspca_suspend,
1273 .resume = gspca_resume,
1274#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001275};
1276
1277/* -- module insert / remove -- */
1278static int __init sd_mod_init(void)
1279{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001280 int ret;
1281 ret = usb_register(&sd_driver);
1282 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001283 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001284 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 return 0;
1286}
1287static void __exit sd_mod_exit(void)
1288{
1289 usb_deregister(&sd_driver);
1290 PDEBUG(D_PROBE, "deregistered");
1291}
1292
1293module_init(sd_mod_init);
1294module_exit(sd_mod_exit);