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