blob: 00f47e463a05b8ccef3449ec3640fe45fe03e680 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 *Notes: * t613 + tas5130A
3 * * Focus to light do not balance well as in win.
4 * Quality in win is not good, but its kinda better.
5 * * Fix some "extraneous bytes", most of apps will show the image anyway
6 * * Gamma table, is there, but its really doing something?
7 * * 7~8 Fps, its ok, max on win its 10.
8 * Costantino Leandro
9 *
10 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "t613"
28#include "gspca.h"
Jean-Francois Moine739570b2008-07-14 09:38:29 -030029#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
30static const char version[] = "2.1.7";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030031
32#define MAX_GAMMA 0x10 /* 0 to 15 */
33
34/* From LUVCVIEW */
35#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
36
37MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39MODULE_LICENSE("GPL");
40
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 unsigned char brightness;
45 unsigned char contrast;
46 unsigned char colors;
47 unsigned char autogain;
48 unsigned char gamma;
49 unsigned char sharpness;
50 unsigned char freq;
51 unsigned char whitebalance;
52 unsigned char mirror;
53 unsigned char effect;
54};
55
56/* V4L2 controls supported by the driver */
57static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80static struct ctrl sd_ctrls[] = {
81#define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 0x0f,
89 .step = 1,
90 .default_value = 0x09,
91 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95#define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109#define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
123#define SD_GAMMA 3
124 {
125 {
126 .id = V4L2_CID_GAMMA, /* (gamma on win) */
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gamma (Untested)",
129 .minimum = 0,
130 .maximum = MAX_GAMMA,
131 .step = 1,
132 .default_value = 0x09,
133 },
134 .set = sd_setgamma,
135 .get = sd_getgamma,
136 },
137#define SD_AUTOGAIN 4
138 {
139 {
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Low Light",
145 .minimum = 0,
146 .maximum = 1,
147 .step = 1,
148 .default_value = 0x01,
149 },
150 .set = sd_setlowlight,
151 .get = sd_getlowlight,
152 },
153#define SD_MIRROR 5
154 {
155 {
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
159 .minimum = 0,
160 .maximum = 1,
161 .step = 1,
162 .default_value = 0,
163 },
164 .set = sd_setflip,
165 .get = sd_getflip
166 },
167#define SD_LIGHTFREQ 6
168 {
169 {
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
174 .maximum = 2,
175 .step = 1,
176 .default_value = 1,
177 },
178 .set = sd_setfreq,
179 .get = sd_getfreq},
180
181#define SD_WHITE_BALANCE 7
182 {
183 {
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
187 .minimum = 0,
188 .maximum = 1,
189 .step = 1,
190 .default_value = 1,
191 },
192 .set = sd_setwhitebalance,
193 .get = sd_getwhitebalance
194 },
195#define SD_SHARPNESS 8 /* (aka definition on win) */
196 {
197 {
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Sharpness",
201 .minimum = 0,
202 .maximum = MAX_GAMMA, /* 0 to 16 */
203 .step = 1,
204 .default_value = 0x06,
205 },
206 .set = sd_setsharpness,
207 .get = sd_getsharpness,
208 },
209#define SD_EFFECTS 9
210 {
211 {
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
215 .minimum = 0,
216 .maximum = 4,
217 .step = 1,
218 .default_value = 0,
219 },
220 .set = sd_seteffect,
221 .get = sd_geteffect
222 },
223};
224
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300225static char *effects_control[] = {
226 "Normal",
227 "Emboss", /* disabled */
228 "Monochrome",
229 "Sepia",
230 "Sketch",
231 "Sun Effect", /* disabled */
232 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300233};
234
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300235static struct v4l2_pix_format vga_mode_t16[] = {
236 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
237 .bytesperline = 160,
238 .sizeimage = 160 * 120 * 3 / 8 + 590,
239 .colorspace = V4L2_COLORSPACE_JPEG,
240 .priv = 4},
241 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
242 .bytesperline = 176,
243 .sizeimage = 176 * 144 * 3 / 8 + 590,
244 .colorspace = V4L2_COLORSPACE_JPEG,
245 .priv = 3},
246 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
247 .bytesperline = 320,
248 .sizeimage = 320 * 240 * 3 / 8 + 590,
249 .colorspace = V4L2_COLORSPACE_JPEG,
250 .priv = 2},
251 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
252 .bytesperline = 352,
253 .sizeimage = 352 * 288 * 3 / 8 + 590,
254 .colorspace = V4L2_COLORSPACE_JPEG,
255 .priv = 1},
256 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
257 .bytesperline = 640,
258 .sizeimage = 640 * 480 * 3 / 8 + 590,
259 .colorspace = V4L2_COLORSPACE_JPEG,
260 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300261};
262
263#define T16_OFFSET_DATA 631
264#define MAX_EFFECTS 7
265/* easily done by soft, this table could be removed,
266 * i keep it here just in case */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300267static const __u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
269 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
270 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
271 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
272 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
273 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
274 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
275};
276
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300277static const __u8 gamma_table[MAX_GAMMA][34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300278 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
279 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
280 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
281 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
282 0xa0, 0xff},
283 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
284 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
285 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
286 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
287 0xa0, 0xff},
288 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
289 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
290 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
291 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
292 0xa0, 0xff},
293 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
294 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
295 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
296 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
297 0xa0, 0xff},
298 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
299 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
300 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
301 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
302 0xa0, 0xff},
303 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
304 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
305 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
306 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
307 0xa0, 0xff},
308 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
309 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
310 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
311 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
312 0xa0, 0xff},
313 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
314 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
315 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
316 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
317 0xa0, 0xff},
318 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
319 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
320 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
321 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
322 0xa0, 0xff},
323 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
324 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
325 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
326 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
327 0xa0, 0xff},
328 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
329 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
330 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
331 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
332 0xa0, 0xff},
333 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
334 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
335 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
336 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
337 0xa0, 0xff},
338 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
339 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
340 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
341 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
342 0xA0, 0xFF},
343 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
344 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
345 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
346 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
347 0xa0, 0xff},
348 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
349 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
350 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
351 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
352 0xa0, 0xff},
353 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
354 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
355 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
356 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
357 0xA0, 0xFF}
358};
359
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300360static const __u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
362 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
363 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
364 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
365 {},
366};
367
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300368/* read 1 byte */
369static int reg_r_1(struct gspca_dev *gspca_dev,
370 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300372 usb_control_msg(gspca_dev->dev,
373 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374 0, /* request */
375 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300377 index,
378 gspca_dev->usb_buf, 1, 500);
379 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300380}
381
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300382static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383 __u16 value,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300384 __u16 index,
385 const __u8 *buffer, __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300387 if (buffer == NULL) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300388 usb_control_msg(gspca_dev->dev,
389 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300390 0,
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
392 value, index,
393 NULL, 0, 500);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300394 return;
395 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300396 if (len <= sizeof gspca_dev->usb_buf) {
397 memcpy(gspca_dev->usb_buf, buffer, len);
398 usb_control_msg(gspca_dev->dev,
399 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300400 0,
401 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
402 value, index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300403 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300404 } else {
405 __u8 *tmpbuf;
406
407 tmpbuf = kmalloc(len, GFP_KERNEL);
408 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300411 0,
412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
413 value, index,
414 tmpbuf, len, 500);
415 kfree(tmpbuf);
416 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417}
418
419/* this function is called at probe time */
420static int sd_config(struct gspca_dev *gspca_dev,
421 const struct usb_device_id *id)
422{
423 struct sd *sd = (struct sd *) gspca_dev;
424 struct cam *cam;
425
426 cam = &gspca_dev->cam;
427 cam->dev_name = (char *) id->driver_info;
428 cam->epaddr = 0x01;
429
430 cam->cam_mode = vga_mode_t16;
431 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
432
433 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
434 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
435 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
436 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
437 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
438 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
439 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
440 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
441 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
442 return 0;
443}
444
445static int init_default_parameters(struct gspca_dev *gspca_dev)
446{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447 /* some of this registers are not really neded, because
448 * they are overriden by setbrigthness, setcontrast, etc,
449 * but wont hurt anyway, and can help someone with similar webcam
450 * to see the initial parameters.*/
451 int i = 0;
452 __u8 test_byte;
453
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300454 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
456 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300457 static const __u8 n1[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300458 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300459 static const __u8 n2[2] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300460 {0x08, 0x00};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300461 static const __u8 nset[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300462 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300463 static const __u8 n3[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300465 static const __u8 n4[0x46] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
467 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
468 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
469 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
470 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
471 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
472 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
473 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
474 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300475 static const __u8 nset4[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300476 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
477 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
478 0xe8, 0xe0
479 };
480 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300481 static const __u8 nset2[20] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300482 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
483 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
484 0xd8, 0xc8, 0xd9, 0xfc
485 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300486 static const __u8 missing[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300487 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300488 static const __u8 nset3[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
490 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
491 0xcf, 0xe0
492 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300493 static const __u8 nset5[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300495 static const __u8 nset6[34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300496 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
497 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
498 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
499 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
500 0xa0, 0xff
501 }; /* Gamma */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300502 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300504 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300505 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300506 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300508 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300509 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
510
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300511 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
512 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
513 reg_r_1(gspca_dev, 0x0063);
514 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515
516 while (read_indexs[i] != 0x00) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300517 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
518 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 test_byte);
520 i++;
521 }
522
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300523 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
524 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
525 reg_r_1(gspca_dev, 0x0080);
526 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
527 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
528 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
529 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
530 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
531 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
532 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
534 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
535 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
536 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
537 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300539 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300541 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
542 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
543 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
546 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
547 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
548 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
551 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
552 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
553 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554
555 return 0;
556}
557
558static void setbrightness(struct gspca_dev *gspca_dev)
559{
560 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 unsigned int brightness;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300562 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300563 brightness = sd->brightness;
564
565 if (brightness < 7) {
566 set6[3] = 0x70 - (brightness * 0xa);
567 } else {
568 set6[1] = 0x24;
569 set6[3] = 0x00 + ((brightness - 7) * 0xa);
570 }
571
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300573}
574
575static void setflip(struct gspca_dev *gspca_dev)
576{
577 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300579 __u8 flipcmd[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
581
582 if (sd->mirror == 1)
583 flipcmd[3] = 0x01;
584
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300585 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586}
587
588static void seteffect(struct gspca_dev *gspca_dev)
589{
590 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300592 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593 if (sd->effect == 1 || sd->effect == 5) {
594 PDEBUG(D_CONF,
595 "This effect have been disabled for webcam \"safety\"");
596 return;
597 }
598
599 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300602 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603}
604
605static void setwhitebalance(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300609 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
611
612 if (sd->whitebalance == 1)
613 white_balance[7] = 0x3c;
614
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616}
617
618static void setlightfreq(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
622
623 if (sd->freq == 2) /* 60hz */
624 freq[1] = 0x00;
625
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627}
628
629static void setcontrast(struct gspca_dev *gspca_dev)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 unsigned int contrast = sd->contrast;
633 __u16 reg_to_write = 0x00;
634
635 if (contrast < 7)
636 reg_to_write = 0x8ea9 - (0x200 * contrast);
637 else
638 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
639
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300640 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641}
642
643static void setcolors(struct gspca_dev *gspca_dev)
644{
645 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300646 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647
648 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300649 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650}
651
652static void setgamma(struct gspca_dev *gspca_dev)
653{
654}
655
656static void setsharpness(struct gspca_dev *gspca_dev)
657{
658 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300659 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660
661 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
662
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300663 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300664}
665
666static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669
670 sd->brightness = val;
671 if (gspca_dev->streaming)
672 setbrightness(gspca_dev);
673 return 0;
674}
675
676static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
677{
678 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300679
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 *val = sd->brightness;
681 return *val;
682}
683
684static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 sd->whitebalance = val;
689 if (gspca_dev->streaming)
690 setwhitebalance(gspca_dev);
691 return 0;
692}
693
694static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
695{
696 struct sd *sd = (struct sd *) gspca_dev;
697
698 *val = sd->whitebalance;
699 return *val;
700}
701
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 sd->mirror = val;
707 if (gspca_dev->streaming)
708 setflip(gspca_dev);
709 return 0;
710}
711
712static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
713{
714 struct sd *sd = (struct sd *) gspca_dev;
715
716 *val = sd->mirror;
717 return *val;
718}
719
720static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
721{
722 struct sd *sd = (struct sd *) gspca_dev;
723
724 sd->effect = val;
725 if (gspca_dev->streaming)
726 seteffect(gspca_dev);
727 return 0;
728}
729
730static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
731{
732 struct sd *sd = (struct sd *) gspca_dev;
733
734 *val = sd->effect;
735 return *val;
736}
737
738static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741
742 sd->contrast = val;
743 if (gspca_dev->streaming)
744 setcontrast(gspca_dev);
745 return 0;
746}
747
748static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 *val = sd->contrast;
753 return *val;
754}
755
756static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759
760 sd->colors = val;
761 if (gspca_dev->streaming)
762 setcolors(gspca_dev);
763 return 0;
764}
765
766static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769
770 *val = sd->colors;
771 return 0;
772}
773
774static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
778 sd->gamma = val;
779 if (gspca_dev->streaming)
780 setgamma(gspca_dev);
781 return 0;
782}
783
784static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
785{
786 struct sd *sd = (struct sd *) gspca_dev;
787 *val = sd->gamma;
788 return 0;
789}
790
791static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794
795 sd->freq = val;
796 if (gspca_dev->streaming)
797 setlightfreq(gspca_dev);
798 return 0;
799}
800
801static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
802{
803 struct sd *sd = (struct sd *) gspca_dev;
804
805 *val = sd->freq;
806 return 0;
807}
808
809static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
810{
811 struct sd *sd = (struct sd *) gspca_dev;
812
813 sd->sharpness = val;
814 if (gspca_dev->streaming)
815 setsharpness(gspca_dev);
816 return 0;
817}
818
819static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822
823 *val = sd->sharpness;
824 return 0;
825}
826
827/* Low Light set here......*/
828static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
829{
830 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831
832 sd->autogain = val;
833 if (val != 0)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300836 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 return 0;
838}
839
840static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
841{
842 struct sd *sd = (struct sd *) gspca_dev;
843
844 *val = sd->autogain;
845 return 0;
846}
847
848static void sd_start(struct gspca_dev *gspca_dev)
849{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 int mode;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300851
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300852 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300854 static const __u8 t3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
856 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300857 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300859 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860 switch (mode) {
861 case 1: /* 352x288 */
862 t2[1] = 0x40;
863 break;
864 case 2: /* 320x240 */
865 t2[1] = 0x10;
866 break;
867 case 3: /* 176x144 */
868 t2[1] = 0x50;
869 break;
870 case 4: /* 160x120 */
871 t2[1] = 0x20;
872 break;
873 default: /* 640x480 (0x00) */
874 break;
875 }
876
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
879 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
880 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
881 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300883 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
884 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300886 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
887 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
888 reg_r_1(gspca_dev, 0x0012);
889 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
890 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
891 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300892 /* restart on each start, just in case, sometimes regs goes wrong
893 * when using controls from app */
894 setbrightness(gspca_dev);
895 setcontrast(gspca_dev);
896 setcolors(gspca_dev);
897}
898
899static void sd_stopN(struct gspca_dev *gspca_dev)
900{
901}
902
903static void sd_stop0(struct gspca_dev *gspca_dev)
904{
905}
906
907static void sd_close(struct gspca_dev *gspca_dev)
908{
909}
910
911static void sd_pkt_scan(struct gspca_dev *gspca_dev,
912 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300913 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300914 int len) /* iso packet length */
915{
916 int sof = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300917 static __u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918
919 if (data[0] == 0x5a) {
920 /* Control Packet, after this came the header again,
921 * but extra bytes came in the packet before this,
922 * sometimes an EOF arrives, sometimes not... */
923 return;
924 }
925
926 if (data[len - 1] == 0xff && data[len] == 0xd9) {
927 /* Just in case, i have seen packets with the marker,
928 * other's do not include it... */
929 data += 2;
930 len -= 4;
931 } else if (data[2] == 0xff && data[3] == 0xd8) {
932 sof = 1;
933 data += 2;
934 len -= 2;
935 } else {
936 data += 2;
937 len -= 2;
938 }
939
940 if (sof) {
941 /* extra bytes....., could be processed too but would be
942 * a waste of time, right now leave the application and
943 * libjpeg do it for ourserlves.. */
944 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
945 ffd9, 2);
946 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
947 return;
948 }
949
950 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
951}
952
953static int sd_querymenu(struct gspca_dev *gspca_dev,
954 struct v4l2_querymenu *menu)
955{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 switch (menu->id) {
957 case V4L2_CID_POWER_LINE_FREQUENCY:
958 switch (menu->index) {
959 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300960 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 return 0;
962 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300963 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964 return 0;
965 }
966 break;
967 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300968 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
969 strncpy((char *) menu->name,
970 effects_control[menu->index], 32);
971 return 0;
972 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 break;
974 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300975 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976}
977
978/* this function is called at open time */
979static int sd_open(struct gspca_dev *gspca_dev)
980{
981 init_default_parameters(gspca_dev);
982 return 0;
983}
984
985/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300986static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 .name = MODULE_NAME,
988 .ctrls = sd_ctrls,
989 .nctrls = ARRAY_SIZE(sd_ctrls),
990 .config = sd_config,
991 .open = sd_open,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .stop0 = sd_stop0,
995 .close = sd_close,
996 .pkt_scan = sd_pkt_scan,
997 .querymenu = sd_querymenu,
998};
999
1000/* -- module initialisation -- */
1001#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001002static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001003 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1004 {}
1005};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001006MODULE_DEVICE_TABLE(usb, device_table);
1007
1008/* -- device connect -- */
1009static int sd_probe(struct usb_interface *intf,
1010 const struct usb_device_id *id)
1011{
1012 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1013 THIS_MODULE);
1014}
1015
1016static struct usb_driver sd_driver = {
1017 .name = MODULE_NAME,
1018 .id_table = device_table,
1019 .probe = sd_probe,
1020 .disconnect = gspca_disconnect,
1021};
1022
1023/* -- module insert / remove -- */
1024static int __init sd_mod_init(void)
1025{
1026 if (usb_register(&sd_driver) < 0)
1027 return -1;
1028 PDEBUG(D_PROBE, "v%s registered", version);
1029 return 0;
1030}
1031static void __exit sd_mod_exit(void)
1032{
1033 usb_deregister(&sd_driver);
1034 PDEBUG(D_PROBE, "deregistered");
1035}
1036
1037module_init(sd_mod_init);
1038module_exit(sd_mod_exit);