blob: 299f84584e82ae202124040fef51599c982892ba [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 Moinec2446b32008-07-05 11:49:20 -030029#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
30static const char version[] = "2.1.5";
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
368static void t16RegRead(struct usb_device *dev,
369 __u16 index, __u8 *buffer, __u16 length)
370{
371 usb_control_msg(dev,
372 usb_rcvctrlpipe(dev, 0),
373 0, /* request */
374 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
375 0, /* value */
376 index, buffer, length, 500);
377}
378
379static void t16RegWrite(struct usb_device *dev,
380 __u16 value,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300381 __u16 index,
382 const __u8 *buffer, __u16 len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300384 if (buffer == NULL) {
385 usb_control_msg(dev,
386 usb_sndctrlpipe(dev, 0),
387 0,
388 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
389 value, index,
390 NULL, 0, 500);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300391 return;
392 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300393 if (len < 16) {
394 __u8 tmpbuf[16];
395
396 memcpy(tmpbuf, buffer, len);
397 usb_control_msg(dev,
398 usb_sndctrlpipe(dev, 0),
399 0,
400 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
401 value, index,
402 tmpbuf, len, 500);
403 } else {
404 __u8 *tmpbuf;
405
406 tmpbuf = kmalloc(len, GFP_KERNEL);
407 memcpy(tmpbuf, buffer, len);
408 usb_control_msg(dev,
409 usb_sndctrlpipe(dev, 0),
410 0,
411 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
412 value, index,
413 tmpbuf, len, 500);
414 kfree(tmpbuf);
415 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300416}
417
418/* this function is called at probe time */
419static int sd_config(struct gspca_dev *gspca_dev,
420 const struct usb_device_id *id)
421{
422 struct sd *sd = (struct sd *) gspca_dev;
423 struct cam *cam;
424
425 cam = &gspca_dev->cam;
426 cam->dev_name = (char *) id->driver_info;
427 cam->epaddr = 0x01;
428
429 cam->cam_mode = vga_mode_t16;
430 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
431
432 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
433 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
434 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
435 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
436 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
437 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
438 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
439 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
440 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
441 return 0;
442}
443
444static int init_default_parameters(struct gspca_dev *gspca_dev)
445{
446 struct usb_device *dev = gspca_dev->dev;
447
448 /* some of this registers are not really neded, because
449 * they are overriden by setbrigthness, setcontrast, etc,
450 * but wont hurt anyway, and can help someone with similar webcam
451 * to see the initial parameters.*/
452 int i = 0;
453 __u8 test_byte;
454
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300455 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
457 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300458 static const __u8 n1[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300459 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300460 static const __u8 n2[2] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 {0x08, 0x00};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300462 static const __u8 nset[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300464 static const __u8 n3[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300465 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300466 static const __u8 n4[0x46] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
468 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
469 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
470 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
471 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
472 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
473 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
474 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
475 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300476 static const __u8 nset4[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300477 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
478 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
479 0xe8, 0xe0
480 };
481 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300482 static const __u8 nset2[20] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300483 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
484 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
485 0xd8, 0xc8, 0xd9, 0xfc
486 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300487 static const __u8 missing[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300489 static const __u8 nset3[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300490 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
491 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
492 0xcf, 0xe0
493 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300494 static const __u8 nset5[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300495 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300496 static const __u8 nset6[34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300497 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
498 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
499 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
500 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
501 0xa0, 0xff
502 }; /* Gamma */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300503 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300505 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300507 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300509 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
511
512 t16RegWrite(dev, 0x01, 0x0000, n1, 0x06);
513 t16RegWrite(dev, 0x01, 0x0000, nset, 0x06);
514 t16RegRead(dev, 0x0063, &test_byte, 1);
515 t16RegWrite(dev, 0x01, 0x0000, n2, 0x02);
516
517 while (read_indexs[i] != 0x00) {
518 t16RegRead(dev, read_indexs[i], &test_byte, 1);
519 PDEBUG(D_CONF, "Reg 0x%x => 0x%x", read_indexs[i],
520 test_byte);
521 i++;
522 }
523
524 t16RegWrite(dev, 0x01, 0x0000, n3, 0x06);
525 t16RegWrite(dev, 0x01, 0x0000, n4, 0x46);
526 t16RegRead(dev, 0x0080, &test_byte, 1);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300527 t16RegWrite(dev, 0x00, 0x2c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 t16RegWrite(dev, 0x01, 0x0000, nset2, 0x14);
529 t16RegWrite(dev, 0x01, 0x0000, nset3, 0x12);
530 t16RegWrite(dev, 0x01, 0x0000, nset4, 0x12);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300531 t16RegWrite(dev, 0x00, 0x3880, NULL, 0);
532 t16RegWrite(dev, 0x00, 0x3880, NULL, 0);
533 t16RegWrite(dev, 0x00, 0x338e, NULL, 0);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300534 t16RegWrite(dev, 0x01, 0x0000, nset5, 0x04);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300535 t16RegWrite(dev, 0x00, 0x00a9, NULL, 0);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300536 t16RegWrite(dev, 0x01, 0x0000, nset6, 0x22);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300537 t16RegWrite(dev, 0x00, 0x86bb, NULL, 0);
538 t16RegWrite(dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300540 t16RegWrite(dev, 0x01, 0x0000, missing, 0x08);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541
Harvey Harrisonefab8212008-07-05 06:12:47 -0300542 t16RegWrite(dev, 0x00, 0x2087, NULL, 0);
543 t16RegWrite(dev, 0x00, 0x2088, NULL, 0);
544 t16RegWrite(dev, 0x00, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300546 t16RegWrite(dev, 0x01, 0x0000, nset7, 0x04);
547 t16RegWrite(dev, 0x01, 0x0000, nset10, 0x06);
548 t16RegWrite(dev, 0x01, 0x0000, nset8, 0x06);
549 t16RegWrite(dev, 0x01, 0x0000, nset9, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550
Harvey Harrisonefab8212008-07-05 06:12:47 -0300551 t16RegWrite(dev, 0x00, 0x2880, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300552 t16RegWrite(dev, 0x01, 0x0000, nset2, 0x14);
553 t16RegWrite(dev, 0x01, 0x0000, nset3, 0x12);
554 t16RegWrite(dev, 0x01, 0x0000, nset4, 0x12);
555
556 return 0;
557}
558
559static void setbrightness(struct gspca_dev *gspca_dev)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 struct usb_device *dev = gspca_dev->dev;
563 unsigned int brightness;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300564 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 brightness = sd->brightness;
566
567 if (brightness < 7) {
568 set6[3] = 0x70 - (brightness * 0xa);
569 } else {
570 set6[1] = 0x24;
571 set6[3] = 0x00 + ((brightness - 7) * 0xa);
572 }
573
574 t16RegWrite(dev, 0x01, 0x0000, set6, 4);
575}
576
577static void setflip(struct gspca_dev *gspca_dev)
578{
579 struct sd *sd = (struct sd *) gspca_dev;
580 struct usb_device *dev = gspca_dev->dev;
581
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300582 __u8 flipcmd[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300583 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
584
585 if (sd->mirror == 1)
586 flipcmd[3] = 0x01;
587
588 t16RegWrite(dev, 0x01, 0x0000, flipcmd, 8);
589}
590
591static void seteffect(struct gspca_dev *gspca_dev)
592{
593 struct sd *sd = (struct sd *) gspca_dev;
594 struct usb_device *dev = gspca_dev->dev;
595
596 t16RegWrite(dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
597 if (sd->effect == 1 || sd->effect == 5) {
598 PDEBUG(D_CONF,
599 "This effect have been disabled for webcam \"safety\"");
600 return;
601 }
602
603 if (sd->effect == 1 || sd->effect == 4)
Harvey Harrisonefab8212008-07-05 06:12:47 -0300604 t16RegWrite(dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300605 else
Harvey Harrisonefab8212008-07-05 06:12:47 -0300606 t16RegWrite(dev, 0x00, 0xfaa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607}
608
609static void setwhitebalance(struct gspca_dev *gspca_dev)
610{
611 struct sd *sd = (struct sd *) gspca_dev;
612 struct usb_device *dev = gspca_dev->dev;
613
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300614 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
616
617 if (sd->whitebalance == 1)
618 white_balance[7] = 0x3c;
619
620 t16RegWrite(dev, 0x01, 0x0000, white_balance, 8);
621}
622
623static void setlightfreq(struct gspca_dev *gspca_dev)
624{
625 struct sd *sd = (struct sd *) gspca_dev;
626 struct usb_device *dev = gspca_dev->dev;
627 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
628
629 if (sd->freq == 2) /* 60hz */
630 freq[1] = 0x00;
631
632 t16RegWrite(dev, 0x1, 0x0000, freq, 0x4);
633}
634
635static void setcontrast(struct gspca_dev *gspca_dev)
636{
637 struct sd *sd = (struct sd *) gspca_dev;
638 struct usb_device *dev = gspca_dev->dev;
639 unsigned int contrast = sd->contrast;
640 __u16 reg_to_write = 0x00;
641
642 if (contrast < 7)
643 reg_to_write = 0x8ea9 - (0x200 * contrast);
644 else
645 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
646
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300647 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648}
649
650static void setcolors(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300654 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655
656 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300657 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658}
659
660static void setgamma(struct gspca_dev *gspca_dev)
661{
662}
663
664static void setsharpness(struct gspca_dev *gspca_dev)
665{
666 struct sd *sd = (struct sd *) gspca_dev;
667 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300668 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300669
670 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
671
Harvey Harrisonefab8212008-07-05 06:12:47 -0300672 t16RegWrite(dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673}
674
675static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
676{
677 struct sd *sd = (struct sd *) gspca_dev;
678
679 sd->brightness = val;
680 if (gspca_dev->streaming)
681 setbrightness(gspca_dev);
682 return 0;
683}
684
685static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
686{
687 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300688
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300689 *val = sd->brightness;
690 return *val;
691}
692
693static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696
697 sd->whitebalance = val;
698 if (gspca_dev->streaming)
699 setwhitebalance(gspca_dev);
700 return 0;
701}
702
703static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
706
707 *val = sd->whitebalance;
708 return *val;
709}
710
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
712{
713 struct sd *sd = (struct sd *) gspca_dev;
714
715 sd->mirror = val;
716 if (gspca_dev->streaming)
717 setflip(gspca_dev);
718 return 0;
719}
720
721static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
722{
723 struct sd *sd = (struct sd *) gspca_dev;
724
725 *val = sd->mirror;
726 return *val;
727}
728
729static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
730{
731 struct sd *sd = (struct sd *) gspca_dev;
732
733 sd->effect = val;
734 if (gspca_dev->streaming)
735 seteffect(gspca_dev);
736 return 0;
737}
738
739static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
740{
741 struct sd *sd = (struct sd *) gspca_dev;
742
743 *val = sd->effect;
744 return *val;
745}
746
747static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750
751 sd->contrast = val;
752 if (gspca_dev->streaming)
753 setcontrast(gspca_dev);
754 return 0;
755}
756
757static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
758{
759 struct sd *sd = (struct sd *) gspca_dev;
760
761 *val = sd->contrast;
762 return *val;
763}
764
765static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768
769 sd->colors = val;
770 if (gspca_dev->streaming)
771 setcolors(gspca_dev);
772 return 0;
773}
774
775static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
776{
777 struct sd *sd = (struct sd *) gspca_dev;
778
779 *val = sd->colors;
780 return 0;
781}
782
783static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 sd->gamma = val;
788 if (gspca_dev->streaming)
789 setgamma(gspca_dev);
790 return 0;
791}
792
793static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
796 *val = sd->gamma;
797 return 0;
798}
799
800static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
801{
802 struct sd *sd = (struct sd *) gspca_dev;
803
804 sd->freq = val;
805 if (gspca_dev->streaming)
806 setlightfreq(gspca_dev);
807 return 0;
808}
809
810static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813
814 *val = sd->freq;
815 return 0;
816}
817
818static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
819{
820 struct sd *sd = (struct sd *) gspca_dev;
821
822 sd->sharpness = val;
823 if (gspca_dev->streaming)
824 setsharpness(gspca_dev);
825 return 0;
826}
827
828static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
829{
830 struct sd *sd = (struct sd *) gspca_dev;
831
832 *val = sd->sharpness;
833 return 0;
834}
835
836/* Low Light set here......*/
837static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
838{
839 struct sd *sd = (struct sd *) gspca_dev;
840 struct usb_device *dev = gspca_dev->dev;
841
842 sd->autogain = val;
843 if (val != 0)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300844 t16RegWrite(dev, 0x00, 0xf48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 else
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300846 t16RegWrite(dev, 0x00, 0xb48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847 return 0;
848}
849
850static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
851{
852 struct sd *sd = (struct sd *) gspca_dev;
853
854 *val = sd->autogain;
855 return 0;
856}
857
858static void sd_start(struct gspca_dev *gspca_dev)
859{
860 struct usb_device *dev = gspca_dev->dev;
861 int mode;
862 __u8 test_byte;
863
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300864 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300866 static const __u8 t3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
868 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300869 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300871 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872 switch (mode) {
873 case 1: /* 352x288 */
874 t2[1] = 0x40;
875 break;
876 case 2: /* 320x240 */
877 t2[1] = 0x10;
878 break;
879 case 3: /* 176x144 */
880 t2[1] = 0x50;
881 break;
882 case 4: /* 160x120 */
883 t2[1] = 0x20;
884 break;
885 default: /* 640x480 (0x00) */
886 break;
887 }
888
889 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
890 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
891 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
892 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300893 t16RegWrite(dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 /* just in case and to keep sync with logs (for mine) */
895 t16RegWrite(dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300896 t16RegWrite(dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300897 /* just in case and to keep sync with logs (for mine) */
898 t16RegWrite(dev, 0x01, 0x0000, t1, 4);
899 t16RegWrite(dev, 0x01, 0x0000, t2, 6);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300900 t16RegRead(dev, 0x0012, &test_byte, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901 t16RegWrite(dev, 0x01, 0x0000, t3, 0x10);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300902 t16RegWrite(dev, 0x00, 0x0013, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903 t16RegWrite(dev, 0x01, 0x0000, t4, 0x4);
904 /* restart on each start, just in case, sometimes regs goes wrong
905 * when using controls from app */
906 setbrightness(gspca_dev);
907 setcontrast(gspca_dev);
908 setcolors(gspca_dev);
909}
910
911static void sd_stopN(struct gspca_dev *gspca_dev)
912{
913}
914
915static void sd_stop0(struct gspca_dev *gspca_dev)
916{
917}
918
919static void sd_close(struct gspca_dev *gspca_dev)
920{
921}
922
923static void sd_pkt_scan(struct gspca_dev *gspca_dev,
924 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300925 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 int len) /* iso packet length */
927{
928 int sof = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300929 static __u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930
931 if (data[0] == 0x5a) {
932 /* Control Packet, after this came the header again,
933 * but extra bytes came in the packet before this,
934 * sometimes an EOF arrives, sometimes not... */
935 return;
936 }
937
938 if (data[len - 1] == 0xff && data[len] == 0xd9) {
939 /* Just in case, i have seen packets with the marker,
940 * other's do not include it... */
941 data += 2;
942 len -= 4;
943 } else if (data[2] == 0xff && data[3] == 0xd8) {
944 sof = 1;
945 data += 2;
946 len -= 2;
947 } else {
948 data += 2;
949 len -= 2;
950 }
951
952 if (sof) {
953 /* extra bytes....., could be processed too but would be
954 * a waste of time, right now leave the application and
955 * libjpeg do it for ourserlves.. */
956 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
957 ffd9, 2);
958 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
959 return;
960 }
961
962 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
963}
964
965static int sd_querymenu(struct gspca_dev *gspca_dev,
966 struct v4l2_querymenu *menu)
967{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968 switch (menu->id) {
969 case V4L2_CID_POWER_LINE_FREQUENCY:
970 switch (menu->index) {
971 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300972 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 return 0;
974 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300975 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976 return 0;
977 }
978 break;
979 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300980 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
981 strncpy((char *) menu->name,
982 effects_control[menu->index], 32);
983 return 0;
984 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 break;
986 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300987 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988}
989
990/* this function is called at open time */
991static int sd_open(struct gspca_dev *gspca_dev)
992{
993 init_default_parameters(gspca_dev);
994 return 0;
995}
996
997/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300998static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999 .name = MODULE_NAME,
1000 .ctrls = sd_ctrls,
1001 .nctrls = ARRAY_SIZE(sd_ctrls),
1002 .config = sd_config,
1003 .open = sd_open,
1004 .start = sd_start,
1005 .stopN = sd_stopN,
1006 .stop0 = sd_stop0,
1007 .close = sd_close,
1008 .pkt_scan = sd_pkt_scan,
1009 .querymenu = sd_querymenu,
1010};
1011
1012/* -- module initialisation -- */
1013#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001014static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1016 {}
1017};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001018MODULE_DEVICE_TABLE(usb, device_table);
1019
1020/* -- device connect -- */
1021static int sd_probe(struct usb_interface *intf,
1022 const struct usb_device_id *id)
1023{
1024 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1025 THIS_MODULE);
1026}
1027
1028static struct usb_driver sd_driver = {
1029 .name = MODULE_NAME,
1030 .id_table = device_table,
1031 .probe = sd_probe,
1032 .disconnect = gspca_disconnect,
1033};
1034
1035/* -- module insert / remove -- */
1036static int __init sd_mod_init(void)
1037{
1038 if (usb_register(&sd_driver) < 0)
1039 return -1;
1040 PDEBUG(D_PROBE, "v%s registered", version);
1041 return 0;
1042}
1043static void __exit sd_mod_exit(void)
1044{
1045 usb_deregister(&sd_driver);
1046 PDEBUG(D_PROBE, "deregistered");
1047}
1048
1049module_init(sd_mod_init);
1050module_exit(sd_mod_exit);