blob: 81b175e15ca75e47cdfbc93d93059ce9de0d6cb6 [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 Moinef9b4a372008-09-03 16:48:14 -030033#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030034
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,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300236 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300237 .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;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425 cam->epaddr = 0x01;
426
427 cam->cam_mode = vga_mode_t16;
428 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
429
430 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
431 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
432 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
433 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
434 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
435 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
436 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
437 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
438 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
439 return 0;
440}
441
442static int init_default_parameters(struct gspca_dev *gspca_dev)
443{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300444 /* some of this registers are not really neded, because
445 * they are overriden by setbrigthness, setcontrast, etc,
446 * but wont hurt anyway, and can help someone with similar webcam
447 * to see the initial parameters.*/
448 int i = 0;
449 __u8 test_byte;
450
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300451 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
453 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300454 static const __u8 n1[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300456 static const __u8 n2[2] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 {0x08, 0x00};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300458 static const __u8 nset[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300459 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300460 static const __u8 n3[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300462 static const __u8 n4[0x46] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
464 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
465 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
466 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
467 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
468 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
469 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
470 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
471 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300472 static const __u8 nset4[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
474 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
475 0xe8, 0xe0
476 };
477 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300478 static const __u8 nset2[20] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300479 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
480 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
481 0xd8, 0xc8, 0xd9, 0xfc
482 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300483 static const __u8 missing[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300484 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300485 static const __u8 nset3[18] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300486 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
487 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
488 0xcf, 0xe0
489 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300490 static const __u8 nset5[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300491 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300492 static const __u8 nset6[34] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
494 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
495 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
496 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
497 0xa0, 0xff
498 }; /* Gamma */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300499 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300501 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300502 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300503 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300505 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
507
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300508 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
509 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
510 reg_r_1(gspca_dev, 0x0063);
511 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512
513 while (read_indexs[i] != 0x00) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300514 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
515 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516 test_byte);
517 i++;
518 }
519
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300520 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
521 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
522 reg_r_1(gspca_dev, 0x0080);
523 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
524 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
525 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
526 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
527 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
528 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
529 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
530 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
531 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
532 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
533 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
534 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300536 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
539 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
540 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
543 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
544 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
545 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
548 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
549 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
550 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551
552 return 0;
553}
554
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300555/* this function is called at probe and resume time */
556static int sd_init(struct gspca_dev *gspca_dev)
557{
558 init_default_parameters(gspca_dev);
559 return 0;
560}
561
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562static void setbrightness(struct gspca_dev *gspca_dev)
563{
564 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 unsigned int brightness;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300566 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300567 brightness = sd->brightness;
568
569 if (brightness < 7) {
570 set6[3] = 0x70 - (brightness * 0xa);
571 } else {
572 set6[1] = 0x24;
573 set6[3] = 0x00 + ((brightness - 7) * 0xa);
574 }
575
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577}
578
579static void setflip(struct gspca_dev *gspca_dev)
580{
581 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300582
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300583 __u8 flipcmd[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
585
586 if (sd->mirror == 1)
587 flipcmd[3] = 0x01;
588
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300589 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300590}
591
592static void seteffect(struct gspca_dev *gspca_dev)
593{
594 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300596 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 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)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300604 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300605 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300606 reg_w(gspca_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;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300613 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
615
616 if (sd->whitebalance == 1)
617 white_balance[7] = 0x3c;
618
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620}
621
622static void setlightfreq(struct gspca_dev *gspca_dev)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
626
627 if (sd->freq == 2) /* 60hz */
628 freq[1] = 0x00;
629
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300630 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631}
632
633static void setcontrast(struct gspca_dev *gspca_dev)
634{
635 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636 unsigned int contrast = sd->contrast;
637 __u16 reg_to_write = 0x00;
638
639 if (contrast < 7)
640 reg_to_write = 0x8ea9 - (0x200 * contrast);
641 else
642 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
643
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645}
646
647static void setcolors(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300650 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651
652 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300653 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654}
655
656static void setgamma(struct gspca_dev *gspca_dev)
657{
658}
659
660static void setsharpness(struct gspca_dev *gspca_dev)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300663 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300664
665 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
666
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300667 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668}
669
670static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673
674 sd->brightness = val;
675 if (gspca_dev->streaming)
676 setbrightness(gspca_dev);
677 return 0;
678}
679
680static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300683
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684 *val = sd->brightness;
685 return *val;
686}
687
688static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 sd->whitebalance = val;
693 if (gspca_dev->streaming)
694 setwhitebalance(gspca_dev);
695 return 0;
696}
697
698static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
699{
700 struct sd *sd = (struct sd *) gspca_dev;
701
702 *val = sd->whitebalance;
703 return *val;
704}
705
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
710 sd->mirror = val;
711 if (gspca_dev->streaming)
712 setflip(gspca_dev);
713 return 0;
714}
715
716static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 *val = sd->mirror;
721 return *val;
722}
723
724static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727
728 sd->effect = val;
729 if (gspca_dev->streaming)
730 seteffect(gspca_dev);
731 return 0;
732}
733
734static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
735{
736 struct sd *sd = (struct sd *) gspca_dev;
737
738 *val = sd->effect;
739 return *val;
740}
741
742static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
743{
744 struct sd *sd = (struct sd *) gspca_dev;
745
746 sd->contrast = val;
747 if (gspca_dev->streaming)
748 setcontrast(gspca_dev);
749 return 0;
750}
751
752static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
753{
754 struct sd *sd = (struct sd *) gspca_dev;
755
756 *val = sd->contrast;
757 return *val;
758}
759
760static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
761{
762 struct sd *sd = (struct sd *) gspca_dev;
763
764 sd->colors = val;
765 if (gspca_dev->streaming)
766 setcolors(gspca_dev);
767 return 0;
768}
769
770static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
771{
772 struct sd *sd = (struct sd *) gspca_dev;
773
774 *val = sd->colors;
775 return 0;
776}
777
778static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
779{
780 struct sd *sd = (struct sd *) gspca_dev;
781
782 sd->gamma = val;
783 if (gspca_dev->streaming)
784 setgamma(gspca_dev);
785 return 0;
786}
787
788static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
789{
790 struct sd *sd = (struct sd *) gspca_dev;
791 *val = sd->gamma;
792 return 0;
793}
794
795static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798
799 sd->freq = val;
800 if (gspca_dev->streaming)
801 setlightfreq(gspca_dev);
802 return 0;
803}
804
805static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
806{
807 struct sd *sd = (struct sd *) gspca_dev;
808
809 *val = sd->freq;
810 return 0;
811}
812
813static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
814{
815 struct sd *sd = (struct sd *) gspca_dev;
816
817 sd->sharpness = val;
818 if (gspca_dev->streaming)
819 setsharpness(gspca_dev);
820 return 0;
821}
822
823static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826
827 *val = sd->sharpness;
828 return 0;
829}
830
831/* Low Light set here......*/
832static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
833{
834 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835
836 sd->autogain = val;
837 if (val != 0)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300838 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839 else
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300840 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300841 return 0;
842}
843
844static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
845{
846 struct sd *sd = (struct sd *) gspca_dev;
847
848 *val = sd->autogain;
849 return 0;
850}
851
852static void sd_start(struct gspca_dev *gspca_dev)
853{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854 int mode;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300856 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300858 static const __u8 t3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
860 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300861 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300863 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 switch (mode) {
865 case 1: /* 352x288 */
866 t2[1] = 0x40;
867 break;
868 case 2: /* 320x240 */
869 t2[1] = 0x10;
870 break;
871 case 3: /* 176x144 */
872 t2[1] = 0x50;
873 break;
874 case 4: /* 160x120 */
875 t2[1] = 0x20;
876 break;
877 default: /* 640x480 (0x00) */
878 break;
879 }
880
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300881 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
882 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
883 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
884 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
885 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300887 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
888 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300890 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
891 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
892 reg_r_1(gspca_dev, 0x0012);
893 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
894 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
895 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896 /* restart on each start, just in case, sometimes regs goes wrong
897 * when using controls from app */
898 setbrightness(gspca_dev);
899 setcontrast(gspca_dev);
900 setcolors(gspca_dev);
901}
902
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903static void sd_pkt_scan(struct gspca_dev *gspca_dev,
904 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300905 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906 int len) /* iso packet length */
907{
908 int sof = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300909 static __u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910
911 if (data[0] == 0x5a) {
912 /* Control Packet, after this came the header again,
913 * but extra bytes came in the packet before this,
914 * sometimes an EOF arrives, sometimes not... */
915 return;
916 }
917
918 if (data[len - 1] == 0xff && data[len] == 0xd9) {
919 /* Just in case, i have seen packets with the marker,
920 * other's do not include it... */
921 data += 2;
922 len -= 4;
923 } else if (data[2] == 0xff && data[3] == 0xd8) {
924 sof = 1;
925 data += 2;
926 len -= 2;
927 } else {
928 data += 2;
929 len -= 2;
930 }
931
932 if (sof) {
933 /* extra bytes....., could be processed too but would be
934 * a waste of time, right now leave the application and
935 * libjpeg do it for ourserlves.. */
936 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
937 ffd9, 2);
938 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
939 return;
940 }
941
942 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
943}
944
945static int sd_querymenu(struct gspca_dev *gspca_dev,
946 struct v4l2_querymenu *menu)
947{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 switch (menu->id) {
949 case V4L2_CID_POWER_LINE_FREQUENCY:
950 switch (menu->index) {
951 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300952 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 return 0;
954 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300955 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 return 0;
957 }
958 break;
959 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300960 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
961 strncpy((char *) menu->name,
962 effects_control[menu->index], 32);
963 return 0;
964 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965 break;
966 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300967 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968}
969
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300971static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300972 .name = MODULE_NAME,
973 .ctrls = sd_ctrls,
974 .nctrls = ARRAY_SIZE(sd_ctrls),
975 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300976 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977 .start = sd_start,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 .pkt_scan = sd_pkt_scan,
979 .querymenu = sd_querymenu,
980};
981
982/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300983static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300984 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 {}
986};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987MODULE_DEVICE_TABLE(usb, device_table);
988
989/* -- device connect -- */
990static int sd_probe(struct usb_interface *intf,
991 const struct usb_device_id *id)
992{
993 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
994 THIS_MODULE);
995}
996
997static struct usb_driver sd_driver = {
998 .name = MODULE_NAME,
999 .id_table = device_table,
1000 .probe = sd_probe,
1001 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001002#ifdef CONFIG_PM
1003 .suspend = gspca_suspend,
1004 .resume = gspca_resume,
1005#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001006};
1007
1008/* -- module insert / remove -- */
1009static int __init sd_mod_init(void)
1010{
1011 if (usb_register(&sd_driver) < 0)
1012 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001013 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014 return 0;
1015}
1016static void __exit sd_mod_exit(void)
1017{
1018 usb_deregister(&sd_driver);
1019 PDEBUG(D_PROBE, "deregistered");
1020}
1021
1022module_init(sd_mod_init);
1023module_exit(sd_mod_exit);