blob: fc1c62e5a2fdde720f66317f53560e0f395143b0 [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
31#define MAX_GAMMA 0x10 /* 0 to 15 */
32
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030033#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
34
35MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
36MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
37MODULE_LICENSE("GPL");
38
39struct sd {
40 struct gspca_dev gspca_dev; /* !! must be the first item */
41
42 unsigned char brightness;
43 unsigned char contrast;
44 unsigned char colors;
45 unsigned char autogain;
46 unsigned char gamma;
47 unsigned char sharpness;
48 unsigned char freq;
49 unsigned char whitebalance;
50 unsigned char mirror;
51 unsigned char effect;
52};
53
54/* V4L2 controls supported by the driver */
55static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
57static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_querymenu(struct gspca_dev *gspca_dev,
76 struct v4l2_querymenu *menu);
77
78static struct ctrl sd_ctrls[] = {
79#define SD_BRIGHTNESS 0
80 {
81 {
82 .id = V4L2_CID_BRIGHTNESS,
83 .type = V4L2_CTRL_TYPE_INTEGER,
84 .name = "Brightness",
85 .minimum = 0,
86 .maximum = 0x0f,
87 .step = 1,
88 .default_value = 0x09,
89 },
90 .set = sd_setbrightness,
91 .get = sd_getbrightness,
92 },
93#define SD_CONTRAST 1
94 {
95 {
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100 .maximum = 0x0d,
101 .step = 1,
102 .default_value = 0x07,
103 },
104 .set = sd_setcontrast,
105 .get = sd_getcontrast,
106 },
107#define SD_COLOR 2
108 {
109 {
110 .id = V4L2_CID_SATURATION,
111 .type = V4L2_CTRL_TYPE_INTEGER,
112 .name = "Color",
113 .minimum = 0,
114 .maximum = 0x0f,
115 .step = 1,
116 .default_value = 0x05,
117 },
118 .set = sd_setcolors,
119 .get = sd_getcolors,
120 },
121#define SD_GAMMA 3
122 {
123 {
124 .id = V4L2_CID_GAMMA, /* (gamma on win) */
125 .type = V4L2_CTRL_TYPE_INTEGER,
126 .name = "Gamma (Untested)",
127 .minimum = 0,
128 .maximum = MAX_GAMMA,
129 .step = 1,
130 .default_value = 0x09,
131 },
132 .set = sd_setgamma,
133 .get = sd_getgamma,
134 },
135#define SD_AUTOGAIN 4
136 {
137 {
138 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
139 * some apps dont bring up the
140 * backligth_compensation control) */
141 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Low Light",
143 .minimum = 0,
144 .maximum = 1,
145 .step = 1,
146 .default_value = 0x01,
147 },
148 .set = sd_setlowlight,
149 .get = sd_getlowlight,
150 },
151#define SD_MIRROR 5
152 {
153 {
154 .id = V4L2_CID_HFLIP,
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .name = "Mirror Image",
157 .minimum = 0,
158 .maximum = 1,
159 .step = 1,
160 .default_value = 0,
161 },
162 .set = sd_setflip,
163 .get = sd_getflip
164 },
165#define SD_LIGHTFREQ 6
166 {
167 {
168 .id = V4L2_CID_POWER_LINE_FREQUENCY,
169 .type = V4L2_CTRL_TYPE_MENU,
170 .name = "Light Frequency Filter",
171 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
172 .maximum = 2,
173 .step = 1,
174 .default_value = 1,
175 },
176 .set = sd_setfreq,
177 .get = sd_getfreq},
178
179#define SD_WHITE_BALANCE 7
180 {
181 {
182 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "White Balance",
185 .minimum = 0,
186 .maximum = 1,
187 .step = 1,
188 .default_value = 1,
189 },
190 .set = sd_setwhitebalance,
191 .get = sd_getwhitebalance
192 },
193#define SD_SHARPNESS 8 /* (aka definition on win) */
194 {
195 {
196 .id = V4L2_CID_SHARPNESS,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "Sharpness",
199 .minimum = 0,
200 .maximum = MAX_GAMMA, /* 0 to 16 */
201 .step = 1,
202 .default_value = 0x06,
203 },
204 .set = sd_setsharpness,
205 .get = sd_getsharpness,
206 },
207#define SD_EFFECTS 9
208 {
209 {
210 .id = V4L2_CID_EFFECTS,
211 .type = V4L2_CTRL_TYPE_MENU,
212 .name = "Webcam Effects",
213 .minimum = 0,
214 .maximum = 4,
215 .step = 1,
216 .default_value = 0,
217 },
218 .set = sd_seteffect,
219 .get = sd_geteffect
220 },
221};
222
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300223static char *effects_control[] = {
224 "Normal",
225 "Emboss", /* disabled */
226 "Monochrome",
227 "Sepia",
228 "Sketch",
229 "Sun Effect", /* disabled */
230 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300231};
232
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300233static struct v4l2_pix_format vga_mode_t16[] = {
234 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
235 .bytesperline = 160,
236 .sizeimage = 160 * 120 * 3 / 8 + 590,
237 .colorspace = V4L2_COLORSPACE_JPEG,
238 .priv = 4},
239 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
240 .bytesperline = 176,
241 .sizeimage = 176 * 144 * 3 / 8 + 590,
242 .colorspace = V4L2_COLORSPACE_JPEG,
243 .priv = 3},
244 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
245 .bytesperline = 320,
246 .sizeimage = 320 * 240 * 3 / 8 + 590,
247 .colorspace = V4L2_COLORSPACE_JPEG,
248 .priv = 2},
249 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
250 .bytesperline = 352,
251 .sizeimage = 352 * 288 * 3 / 8 + 590,
252 .colorspace = V4L2_COLORSPACE_JPEG,
253 .priv = 1},
254 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
255 .bytesperline = 640,
256 .sizeimage = 640 * 480 * 3 / 8 + 590,
257 .colorspace = V4L2_COLORSPACE_JPEG,
258 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300259};
260
261#define T16_OFFSET_DATA 631
262#define MAX_EFFECTS 7
263/* easily done by soft, this table could be removed,
264 * i keep it here just in case */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300265static const __u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300266 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
267 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
269 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
270 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
271 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
272 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
273};
274
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300275static const __u8 gamma_table[MAX_GAMMA][34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300276 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
277 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
278 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
279 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
280 0xa0, 0xff},
281 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
282 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
283 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
284 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
285 0xa0, 0xff},
286 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
287 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
288 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
289 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
290 0xa0, 0xff},
291 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
292 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
293 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
294 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
295 0xa0, 0xff},
296 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
297 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
298 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
299 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
300 0xa0, 0xff},
301 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
302 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
303 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
304 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
305 0xa0, 0xff},
306 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
307 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
308 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
309 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
310 0xa0, 0xff},
311 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
312 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
313 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
314 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
315 0xa0, 0xff},
316 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
317 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
318 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
319 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
320 0xa0, 0xff},
321 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
322 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
323 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
324 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
325 0xa0, 0xff},
326 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
327 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
328 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
329 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
330 0xa0, 0xff},
331 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
332 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
333 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
334 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
335 0xa0, 0xff},
336 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
337 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
338 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
339 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
340 0xA0, 0xFF},
341 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
342 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
343 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
344 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
345 0xa0, 0xff},
346 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
347 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
348 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
349 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
350 0xa0, 0xff},
351 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
352 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
353 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
354 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
355 0xA0, 0xFF}
356};
357
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300358static const __u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300359 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
360 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
361 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
362 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
363 {},
364};
365
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300366/* read 1 byte */
367static int reg_r_1(struct gspca_dev *gspca_dev,
368 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300369{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300370 usb_control_msg(gspca_dev->dev,
371 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 0, /* request */
373 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
374 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300375 index,
376 gspca_dev->usb_buf, 1, 500);
377 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300378}
379
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300380static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381 __u16 value,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300382 __u16 index,
383 const __u8 *buffer, __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300385 if (buffer == NULL) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300386 usb_control_msg(gspca_dev->dev,
387 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300388 0,
389 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
390 value, index,
391 NULL, 0, 500);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300392 return;
393 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300394 if (len <= sizeof gspca_dev->usb_buf) {
395 memcpy(gspca_dev->usb_buf, buffer, len);
396 usb_control_msg(gspca_dev->dev,
397 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300398 0,
399 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
400 value, index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300401 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300402 } else {
403 __u8 *tmpbuf;
404
405 tmpbuf = kmalloc(len, GFP_KERNEL);
406 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300407 usb_control_msg(gspca_dev->dev,
408 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300409 0,
410 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
411 value, index,
412 tmpbuf, len, 500);
413 kfree(tmpbuf);
414 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300415}
416
417/* this function is called at probe time */
418static int sd_config(struct gspca_dev *gspca_dev,
419 const struct usb_device_id *id)
420{
421 struct sd *sd = (struct sd *) gspca_dev;
422 struct cam *cam;
423
424 cam = &gspca_dev->cam;
425 cam->dev_name = (char *) id->driver_info;
426 cam->epaddr = 0x01;
427
428 cam->cam_mode = vga_mode_t16;
429 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
430
431 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
432 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
433 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
434 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
435 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
436 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
437 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
438 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
439 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
440 return 0;
441}
442
443static int init_default_parameters(struct gspca_dev *gspca_dev)
444{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445 /* some of this registers are not really neded, because
446 * they are overriden by setbrigthness, setcontrast, etc,
447 * but wont hurt anyway, and can help someone with similar webcam
448 * to see the initial parameters.*/
449 int i = 0;
450 __u8 test_byte;
451
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300452 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
454 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300455 static const __u8 n1[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300457 static const __u8 n2[2] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300458 {0x08, 0x00};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300459 static const __u8 nset[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300460 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300461 static const __u8 n3[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300462 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300463 static const __u8 n4[0x46] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
465 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
466 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
467 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
468 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
469 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
470 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
471 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
472 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300473 static const __u8 nset4[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300474 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
475 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
476 0xe8, 0xe0
477 };
478 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300479 static const __u8 nset2[20] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
481 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
482 0xd8, 0xc8, 0xd9, 0xfc
483 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300484 static const __u8 missing[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300485 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300486 static const __u8 nset3[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300487 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
488 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
489 0xcf, 0xe0
490 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300491 static const __u8 nset5[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300493 static const __u8 nset6[34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
495 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
496 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
497 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
498 0xa0, 0xff
499 }; /* Gamma */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300500 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300501 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300502 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300504 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300505 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300506 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
508
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300509 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
510 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
511 reg_r_1(gspca_dev, 0x0063);
512 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513
514 while (read_indexs[i] != 0x00) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300515 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
516 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 test_byte);
518 i++;
519 }
520
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300521 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
522 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
523 reg_r_1(gspca_dev, 0x0080);
524 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
525 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
526 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
527 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
528 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
529 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
530 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
531 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
532 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
534 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
535 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300537 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300539 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
540 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
541 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
544 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
545 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
546 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300548 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
549 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
550 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
551 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300552
553 return 0;
554}
555
556static void setbrightness(struct gspca_dev *gspca_dev)
557{
558 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 unsigned int brightness;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300560 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 brightness = sd->brightness;
562
563 if (brightness < 7) {
564 set6[3] = 0x70 - (brightness * 0xa);
565 } else {
566 set6[1] = 0x24;
567 set6[3] = 0x00 + ((brightness - 7) * 0xa);
568 }
569
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300570 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571}
572
573static void setflip(struct gspca_dev *gspca_dev)
574{
575 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300576
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300577 __u8 flipcmd[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
579
580 if (sd->mirror == 1)
581 flipcmd[3] = 0x01;
582
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300583 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584}
585
586static void seteffect(struct gspca_dev *gspca_dev)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300589
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300590 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591 if (sd->effect == 1 || sd->effect == 5) {
592 PDEBUG(D_CONF,
593 "This effect have been disabled for webcam \"safety\"");
594 return;
595 }
596
597 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300598 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300599 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601}
602
603static void setwhitebalance(struct gspca_dev *gspca_dev)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300606
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300607 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
609
610 if (sd->whitebalance == 1)
611 white_balance[7] = 0x3c;
612
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300613 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614}
615
616static void setlightfreq(struct gspca_dev *gspca_dev)
617{
618 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
620
621 if (sd->freq == 2) /* 60hz */
622 freq[1] = 0x00;
623
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300624 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625}
626
627static void setcontrast(struct gspca_dev *gspca_dev)
628{
629 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630 unsigned int contrast = sd->contrast;
631 __u16 reg_to_write = 0x00;
632
633 if (contrast < 7)
634 reg_to_write = 0x8ea9 - (0x200 * contrast);
635 else
636 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
637
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300638 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639}
640
641static void setcolors(struct gspca_dev *gspca_dev)
642{
643 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300644 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645
646 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300647 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648}
649
650static void setgamma(struct gspca_dev *gspca_dev)
651{
652}
653
654static void setsharpness(struct gspca_dev *gspca_dev)
655{
656 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300657 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658
659 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
660
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300661 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662}
663
664static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
665{
666 struct sd *sd = (struct sd *) gspca_dev;
667
668 sd->brightness = val;
669 if (gspca_dev->streaming)
670 setbrightness(gspca_dev);
671 return 0;
672}
673
674static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
675{
676 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300677
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 *val = sd->brightness;
679 return *val;
680}
681
682static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
683{
684 struct sd *sd = (struct sd *) gspca_dev;
685
686 sd->whitebalance = val;
687 if (gspca_dev->streaming)
688 setwhitebalance(gspca_dev);
689 return 0;
690}
691
692static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
693{
694 struct sd *sd = (struct sd *) gspca_dev;
695
696 *val = sd->whitebalance;
697 return *val;
698}
699
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
701{
702 struct sd *sd = (struct sd *) gspca_dev;
703
704 sd->mirror = val;
705 if (gspca_dev->streaming)
706 setflip(gspca_dev);
707 return 0;
708}
709
710static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
711{
712 struct sd *sd = (struct sd *) gspca_dev;
713
714 *val = sd->mirror;
715 return *val;
716}
717
718static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
719{
720 struct sd *sd = (struct sd *) gspca_dev;
721
722 sd->effect = val;
723 if (gspca_dev->streaming)
724 seteffect(gspca_dev);
725 return 0;
726}
727
728static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
729{
730 struct sd *sd = (struct sd *) gspca_dev;
731
732 *val = sd->effect;
733 return *val;
734}
735
736static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
737{
738 struct sd *sd = (struct sd *) gspca_dev;
739
740 sd->contrast = val;
741 if (gspca_dev->streaming)
742 setcontrast(gspca_dev);
743 return 0;
744}
745
746static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
747{
748 struct sd *sd = (struct sd *) gspca_dev;
749
750 *val = sd->contrast;
751 return *val;
752}
753
754static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757
758 sd->colors = val;
759 if (gspca_dev->streaming)
760 setcolors(gspca_dev);
761 return 0;
762}
763
764static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
765{
766 struct sd *sd = (struct sd *) gspca_dev;
767
768 *val = sd->colors;
769 return 0;
770}
771
772static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
773{
774 struct sd *sd = (struct sd *) gspca_dev;
775
776 sd->gamma = val;
777 if (gspca_dev->streaming)
778 setgamma(gspca_dev);
779 return 0;
780}
781
782static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
783{
784 struct sd *sd = (struct sd *) gspca_dev;
785 *val = sd->gamma;
786 return 0;
787}
788
789static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
790{
791 struct sd *sd = (struct sd *) gspca_dev;
792
793 sd->freq = val;
794 if (gspca_dev->streaming)
795 setlightfreq(gspca_dev);
796 return 0;
797}
798
799static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
800{
801 struct sd *sd = (struct sd *) gspca_dev;
802
803 *val = sd->freq;
804 return 0;
805}
806
807static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
808{
809 struct sd *sd = (struct sd *) gspca_dev;
810
811 sd->sharpness = val;
812 if (gspca_dev->streaming)
813 setsharpness(gspca_dev);
814 return 0;
815}
816
817static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
820
821 *val = sd->sharpness;
822 return 0;
823}
824
825/* Low Light set here......*/
826static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
827{
828 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829
830 sd->autogain = val;
831 if (val != 0)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300832 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300834 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 return 0;
836}
837
838static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
839{
840 struct sd *sd = (struct sd *) gspca_dev;
841
842 *val = sd->autogain;
843 return 0;
844}
845
846static void sd_start(struct gspca_dev *gspca_dev)
847{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 int mode;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300850 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300851 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300852 static const __u8 t3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
854 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300855 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300857 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858 switch (mode) {
859 case 1: /* 352x288 */
860 t2[1] = 0x40;
861 break;
862 case 2: /* 320x240 */
863 t2[1] = 0x10;
864 break;
865 case 3: /* 176x144 */
866 t2[1] = 0x50;
867 break;
868 case 4: /* 160x120 */
869 t2[1] = 0x20;
870 break;
871 default: /* 640x480 (0x00) */
872 break;
873 }
874
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300875 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
876 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
879 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300881 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
882 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300884 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
885 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
886 reg_r_1(gspca_dev, 0x0012);
887 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
888 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
889 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 /* restart on each start, just in case, sometimes regs goes wrong
891 * when using controls from app */
892 setbrightness(gspca_dev);
893 setcontrast(gspca_dev);
894 setcolors(gspca_dev);
895}
896
897static void sd_stopN(struct gspca_dev *gspca_dev)
898{
899}
900
901static void sd_stop0(struct gspca_dev *gspca_dev)
902{
903}
904
905static void sd_close(struct gspca_dev *gspca_dev)
906{
907}
908
909static void sd_pkt_scan(struct gspca_dev *gspca_dev,
910 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300911 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 int len) /* iso packet length */
913{
914 int sof = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300915 static __u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916
917 if (data[0] == 0x5a) {
918 /* Control Packet, after this came the header again,
919 * but extra bytes came in the packet before this,
920 * sometimes an EOF arrives, sometimes not... */
921 return;
922 }
923
924 if (data[len - 1] == 0xff && data[len] == 0xd9) {
925 /* Just in case, i have seen packets with the marker,
926 * other's do not include it... */
927 data += 2;
928 len -= 4;
929 } else if (data[2] == 0xff && data[3] == 0xd8) {
930 sof = 1;
931 data += 2;
932 len -= 2;
933 } else {
934 data += 2;
935 len -= 2;
936 }
937
938 if (sof) {
939 /* extra bytes....., could be processed too but would be
940 * a waste of time, right now leave the application and
941 * libjpeg do it for ourserlves.. */
942 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
943 ffd9, 2);
944 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
945 return;
946 }
947
948 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
949}
950
951static int sd_querymenu(struct gspca_dev *gspca_dev,
952 struct v4l2_querymenu *menu)
953{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300954 switch (menu->id) {
955 case V4L2_CID_POWER_LINE_FREQUENCY:
956 switch (menu->index) {
957 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300958 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959 return 0;
960 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300961 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 return 0;
963 }
964 break;
965 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300966 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
967 strncpy((char *) menu->name,
968 effects_control[menu->index], 32);
969 return 0;
970 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300971 break;
972 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300973 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300974}
975
976/* this function is called at open time */
977static int sd_open(struct gspca_dev *gspca_dev)
978{
979 init_default_parameters(gspca_dev);
980 return 0;
981}
982
983/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300984static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 .name = MODULE_NAME,
986 .ctrls = sd_ctrls,
987 .nctrls = ARRAY_SIZE(sd_ctrls),
988 .config = sd_config,
989 .open = sd_open,
990 .start = sd_start,
991 .stopN = sd_stopN,
992 .stop0 = sd_stop0,
993 .close = sd_close,
994 .pkt_scan = sd_pkt_scan,
995 .querymenu = sd_querymenu,
996};
997
998/* -- module initialisation -- */
999#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001000static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001001 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1002 {}
1003};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004MODULE_DEVICE_TABLE(usb, device_table);
1005
1006/* -- device connect -- */
1007static int sd_probe(struct usb_interface *intf,
1008 const struct usb_device_id *id)
1009{
1010 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1011 THIS_MODULE);
1012}
1013
1014static struct usb_driver sd_driver = {
1015 .name = MODULE_NAME,
1016 .id_table = device_table,
1017 .probe = sd_probe,
1018 .disconnect = gspca_disconnect,
1019};
1020
1021/* -- module insert / remove -- */
1022static int __init sd_mod_init(void)
1023{
1024 if (usb_register(&sd_driver) < 0)
1025 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001026 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 return 0;
1028}
1029static void __exit sd_mod_exit(void)
1030{
1031 usb_deregister(&sd_driver);
1032 PDEBUG(D_PROBE, "deregistered");
1033}
1034
1035module_init(sd_mod_init);
1036module_exit(sd_mod_exit);