blob: 76ba2c9588d7d286d763aab6cecbefea0aa76923 [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
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030031#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
40 unsigned char brightness;
41 unsigned char contrast;
42 unsigned char colors;
43 unsigned char autogain;
44 unsigned char gamma;
45 unsigned char sharpness;
46 unsigned char freq;
47 unsigned char whitebalance;
48 unsigned char mirror;
49 unsigned char effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030050
51 __u8 sensor;
52#define SENSOR_TAS5130A 0
Jean-Francois Moine236088d2008-10-17 04:53:02 -030053#define SENSOR_OM6802 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030054};
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,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030088 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030090 .default_value = 8,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091 },
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 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300123#define GAMMA_MAX 16
124#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 {
126 {
127 .id = V4L2_CID_GAMMA, /* (gamma on win) */
128 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300129 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300131 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300132 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300133 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 },
135 .set = sd_setgamma,
136 .get = sd_getgamma,
137 },
138#define SD_AUTOGAIN 4
139 {
140 {
141 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
142 * some apps dont bring up the
143 * backligth_compensation control) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Low Light",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149 .default_value = 0x01,
150 },
151 .set = sd_setlowlight,
152 .get = sd_getlowlight,
153 },
154#define SD_MIRROR 5
155 {
156 {
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
163 .default_value = 0,
164 },
165 .set = sd_setflip,
166 .get = sd_getflip
167 },
168#define SD_LIGHTFREQ 6
169 {
170 {
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
175 .maximum = 2,
176 .step = 1,
177 .default_value = 1,
178 },
179 .set = sd_setfreq,
180 .get = sd_getfreq},
181
182#define SD_WHITE_BALANCE 7
183 {
184 {
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
188 .minimum = 0,
189 .maximum = 1,
190 .step = 1,
Jean-Francois Moinecbc51c62008-10-17 05:07:45 -0300191 .default_value = 0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192 },
193 .set = sd_setwhitebalance,
194 .get = sd_getwhitebalance
195 },
196#define SD_SHARPNESS 8 /* (aka definition on win) */
197 {
198 {
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Sharpness",
202 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300203 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 .step = 1,
205 .default_value = 0x06,
206 },
207 .set = sd_setsharpness,
208 .get = sd_getsharpness,
209 },
210#define SD_EFFECTS 9
211 {
212 {
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
216 .minimum = 0,
217 .maximum = 4,
218 .step = 1,
219 .default_value = 0,
220 },
221 .set = sd_seteffect,
222 .get = sd_geteffect
223 },
224};
225
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300226static char *effects_control[] = {
227 "Normal",
228 "Emboss", /* disabled */
229 "Monochrome",
230 "Sepia",
231 "Sketch",
232 "Sun Effect", /* disabled */
233 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300234};
235
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300236static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300237 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
238 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300239 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300240 .colorspace = V4L2_COLORSPACE_JPEG,
241 .priv = 4},
242 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
243 .bytesperline = 176,
244 .sizeimage = 176 * 144 * 3 / 8 + 590,
245 .colorspace = V4L2_COLORSPACE_JPEG,
246 .priv = 3},
247 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
248 .bytesperline = 320,
249 .sizeimage = 320 * 240 * 3 / 8 + 590,
250 .colorspace = V4L2_COLORSPACE_JPEG,
251 .priv = 2},
252 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .bytesperline = 352,
254 .sizeimage = 352 * 288 * 3 / 8 + 590,
255 .colorspace = V4L2_COLORSPACE_JPEG,
256 .priv = 1},
257 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
258 .bytesperline = 640,
259 .sizeimage = 640 * 480 * 3 / 8 + 590,
260 .colorspace = V4L2_COLORSPACE_JPEG,
261 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300262};
263
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300264/* sensor specific data */
265struct additional_sensor_data {
266 const __u8 data1[20];
267 const __u8 data2[18];
268 const __u8 data3[18];
269 const __u8 data4[4];
270 const __u8 data5[6];
271 const __u8 stream[4];
272};
273
274const static struct additional_sensor_data sensor_data[] = {
275 { /* TAS5130A */
276 .data1 =
277 {0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10,
278 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
279 0xd8, 0xc8, 0xd9, 0xfc},
280 .data2 =
281 {0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60,
282 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
283 0xe8, 0xe0},
284 .data3 =
285 {0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60,
286 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
287 0xcf, 0xe0},
288 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
289 {0x66, 0x00, 0xa8, 0xe8},
290 .data5 =
291 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
292 .stream =
293 {0x0b, 0x04, 0x0a, 0x40},
294 },
295 { /* OM6802 */
296 .data1 =
297 {0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22,
298 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06,
299 0xd8, 0xb3, 0xd9, 0xfc},
300 .data2 =
301 {0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80,
302 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff,
303 0xe8, 0xff},
304 .data3 =
305 {0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80,
306 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff,
307 0xcf, 0xff},
308 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
309 {0x66, 0xca, 0xa8, 0xf0 },
310 .data5 = /* this could be removed later */
311 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
312 .stream =
313 {0x0b, 0x04, 0x0a, 0x78},
314 }
315};
316
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317#define MAX_EFFECTS 7
318/* easily done by soft, this table could be removed,
319 * i keep it here just in case */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300320static const __u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300321 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
322 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
323 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
324 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
325 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
326 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
327 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
328};
329
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300330static const __u8 gamma_table[GAMMA_MAX][34] = {
331 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300332 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
333 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
334 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
335 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300336 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */
337 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
338 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
339 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300341 {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */
342 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
343 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
344 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300345 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300346 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */
347 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
348 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
349 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300350 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300351 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300352 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300353 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
354 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300355 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300356 {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300358 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
359 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300361 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
363 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
364 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
365 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300366 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */
367 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
368 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
369 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300371 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */
372 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
373 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
374 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300375 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300376 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
378 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
379 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
380 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300381 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */
382 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
383 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
384 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300386 {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */
387 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
388 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
389 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300390 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300391 {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */
392 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
393 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
394 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300396 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */
397 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
398 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
399 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300400 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300401 {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */
402 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
403 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
404 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
405 0xa0, 0xff},
406 {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */
407 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
408 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
409 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
410 0xa0, 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411};
412
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300413static const __u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300414 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
415 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
416 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
417 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
418 {},
419};
420
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300421static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
422
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300423/* read 1 byte */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300424static int reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300425 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300426{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300427 usb_control_msg(gspca_dev->dev,
428 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300429 0, /* request */
430 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
431 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300432 index,
433 gspca_dev->usb_buf, 1, 500);
434 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435}
436
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300437static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300438 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300440 usb_control_msg(gspca_dev->dev,
441 usb_sndctrlpipe(gspca_dev->dev, 0),
442 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300443 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300444 0, index,
445 NULL, 0, 500);
446}
447
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300448static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300449 const __u8 *buffer, __u16 len)
450{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300451 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300452 memcpy(gspca_dev->usb_buf, buffer, len);
453 usb_control_msg(gspca_dev->dev,
454 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300455 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300456 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300457 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300458 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300459 } else {
460 __u8 *tmpbuf;
461
462 tmpbuf = kmalloc(len, GFP_KERNEL);
463 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300464 usb_control_msg(gspca_dev->dev,
465 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300466 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300467 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300468 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300469 tmpbuf, len, 500);
470 kfree(tmpbuf);
471 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472}
473
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300474/* Reported as OM6802*/
475static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300476{
477 int i;
478 const __u8 *p;
479 __u8 byte;
480 __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
481 static const __u8 sensor_init[] = {
482 0xdf, 0x6d,
483 0xdd, 0x18,
484 0x5a, 0xe0,
485 0x5c, 0x07,
486 0x5d, 0xb0,
487 0x5e, 0x1e,
488 0x60, 0x71,
489 0xef, 0x00,
490 0xe9, 0x00,
491 0xea, 0x00,
492 0x90, 0x24,
493 0x91, 0xb2,
494 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300495 0xfd, 0x41,
496 0x00 /* table end */
497 };
498
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300499 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
500 msleep(5);
501 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300502 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300503 byte = reg_r(gspca_dev, 0x0060);
504 if (!(byte & 0x01))
505 break;
506 msleep(100);
507 }
508 byte = reg_r(gspca_dev, 0x0063);
509 if (byte != 0x17) {
510 err("Bad sensor reset %02x", byte);
511 /* continue? */
512 }
513
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300514 p = sensor_init;
515 while (*p != 0) {
516 val[1] = *p++;
517 val[3] = *p++;
518 if (*p == 0)
519 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300520 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300521 i = 4;
522 while (--i >= 0) {
523 msleep(15);
524 byte = reg_r(gspca_dev, 0x60);
525 if (!(byte & 0x01))
526 break;
527 }
528 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300529 msleep(15);
530 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300531}
532
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533/* this function is called at probe time */
534static int sd_config(struct gspca_dev *gspca_dev,
535 const struct usb_device_id *id)
536{
537 struct sd *sd = (struct sd *) gspca_dev;
538 struct cam *cam;
539
540 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541
542 cam->cam_mode = vga_mode_t16;
543 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
544
545 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
546 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
547 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300548 sd->gamma = GAMMA_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
550 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
551 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
552 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
553 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
554 return 0;
555}
556
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300557static void setbrightness(struct gspca_dev *gspca_dev)
558{
559 struct sd *sd = (struct sd *) gspca_dev;
560 unsigned int brightness;
561 __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
562
563 brightness = sd->brightness;
564 if (brightness < 7) {
565 set6[1] = 0x26;
566 set6[3] = 0x70 - brightness * 0x10;
567 } else {
568 set6[3] = 0x00 + ((brightness - 7) * 0x10);
569 }
570
571 reg_w_buf(gspca_dev, set6, sizeof set6);
572}
573
574static void setcontrast(struct gspca_dev *gspca_dev)
575{
576 struct sd *sd = (struct sd *) gspca_dev;
577 unsigned int contrast = sd->contrast;
578 __u16 reg_to_write;
579
580 if (contrast < 7)
581 reg_to_write = 0x8ea9 - contrast * 0x200;
582 else
583 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
584
585 reg_w(gspca_dev, reg_to_write);
586}
587
588static void setcolors(struct gspca_dev *gspca_dev)
589{
590 struct sd *sd = (struct sd *) gspca_dev;
591 __u16 reg_to_write;
592
593 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
594 reg_w(gspca_dev, reg_to_write);
595}
596
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300597static void setgamma(struct gspca_dev *gspca_dev)
598{
599 struct sd *sd = (struct sd *) gspca_dev;
600
601 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300602 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300603}
604
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300605static void setwhitebalance(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608
609 __u8 white_balance[8] =
610 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
611
612 if (sd->whitebalance)
613 white_balance[7] = 0x3c;
614
615 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
616}
617
618static void setsharpness(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 __u16 reg_to_write;
622
623 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
624
625 reg_w(gspca_dev, reg_to_write);
626}
627
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300628/* this function is called at probe and resume time */
629static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 /* some of this registers are not really neded, because
632 * they are overriden by setbrigthness, setcontrast, etc,
633 * but wont hurt anyway, and can help someone with similar webcam
634 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300635 struct sd *sd = (struct sd *) gspca_dev;
636 int i;
637 __u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300639 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
641 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300642 static const __u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300644 static const __u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 {0x08, 0x00};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300646 static const __u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300648 static const __u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
650 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
651 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
652 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
653 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
654 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
655 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
656 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
657 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300658 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300659 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300660 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300661 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300663 byte = reg_r(gspca_dev, 0x06);
664 test_byte = reg_r(gspca_dev, 0x07);
665 if (byte == 0x08 && test_byte == 0x07) {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300666 PDEBUG(D_CONF, "sensor om6802");
667 sd->sensor = SENSOR_OM6802;
668 } else if (byte == 0x08 && test_byte == 0x01) {
669 PDEBUG(D_CONF, "sensor tas5130a");
670 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300671 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300672 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300673 sd->sensor = SENSOR_TAS5130A;
674 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300676 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300677 test_byte = 0;
678 i = 5;
679 while (--i >= 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300680 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300681 test_byte = reg_r(gspca_dev, 0x0063);
682 msleep(100);
683 if (test_byte == 0x17)
684 break; /* OK */
685 }
686 if (i < 0) {
687 err("Bad sensor reset %02x", test_byte);
688/* return -EIO; */
689/*fixme: test - continue */
690 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300691 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300692
693 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300695 test_byte = reg_r(gspca_dev, read_indexs[i]);
696 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 test_byte);
698 i++;
699 }
700
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300701 reg_w_buf(gspca_dev, n3, sizeof n3);
702 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300703 reg_r(gspca_dev, 0x0080);
704 reg_w(gspca_dev, 0x2c80);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300705
706 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
707 sizeof sensor_data[sd->sensor].data1);
708 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
709 sizeof sensor_data[sd->sensor].data3);
710 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
711 sizeof sensor_data[sd->sensor].data2);
712
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300713 reg_w(gspca_dev, 0x3880);
714 reg_w(gspca_dev, 0x3880);
715 reg_w(gspca_dev, 0x338e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300716
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300717 setbrightness(gspca_dev);
718 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300719 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300720 setcolors(gspca_dev);
721 setsharpness(gspca_dev);
722 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300724 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300725 reg_w(gspca_dev, 0x2088);
726 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300728 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
729 sizeof sensor_data[sd->sensor].data4);
730 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
731 sizeof sensor_data[sd->sensor].data5);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300732 reg_w_buf(gspca_dev, nset8, sizeof nset8);
733 reg_w_buf(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300735 reg_w(gspca_dev, 0x2880);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300736
737 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
738 sizeof sensor_data[sd->sensor].data1);
739 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
740 sizeof sensor_data[sd->sensor].data3);
741 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
742 sizeof sensor_data[sd->sensor].data2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743
744 return 0;
745}
746
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747static void setflip(struct gspca_dev *gspca_dev)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300750 __u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300751 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300753 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300754 flipcmd[3] = 0x01;
755
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300756 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757}
758
759static void seteffect(struct gspca_dev *gspca_dev)
760{
761 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300763 reg_w_buf(gspca_dev, effects_table[sd->effect],
764 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 if (sd->effect == 1 || sd->effect == 5) {
766 PDEBUG(D_CONF,
767 "This effect have been disabled for webcam \"safety\"");
768 return;
769 }
770
771 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300772 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300774 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775}
776
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300777static void setlightfreq(struct gspca_dev *gspca_dev)
778{
779 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
781
782 if (sd->freq == 2) /* 60hz */
783 freq[1] = 0x00;
784
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300785 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786}
787
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300788/* Is this really needed?
789 * i added some module parameters for test with some users */
790static void poll_sensor(struct gspca_dev *gspca_dev)
791{
792 struct sd *sd = (struct sd *) gspca_dev;
793 static const __u8 poll1[] =
794 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
795 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
796 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
797 0x60, 0x14};
798 static const __u8 poll2[] =
799 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
800 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
801 static const __u8 poll3[] =
802 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
803 static const __u8 poll4[] =
804 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
805 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
806 0xc2, 0x80, 0xc3, 0x10};
807
808 if (sd->sensor != SENSOR_TAS5130A) {
809 PDEBUG(D_STREAM, "[Sensor requires polling]");
810 reg_w_buf(gspca_dev, poll1, sizeof poll1);
811 reg_w_buf(gspca_dev, poll2, sizeof poll2);
812 reg_w_buf(gspca_dev, poll3, sizeof poll3);
813 reg_w_buf(gspca_dev, poll4, sizeof poll4);
814 }
815}
816
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300817static int sd_start(struct gspca_dev *gspca_dev)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
820 int i, mode;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300821 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
822 static const __u8 t3[] =
823 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
824 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300825
826 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
827 switch (mode) {
828 case 1: /* 352x288 */
829 t2[1] = 0x40;
830 break;
831 case 2: /* 320x240 */
832 t2[1] = 0x10;
833 break;
834 case 3: /* 176x144 */
835 t2[1] = 0x50;
836 break;
837 case 4: /* 160x120 */
838 t2[1] = 0x20;
839 break;
840 default: /* 640x480 (0x00) */
841 break;
842 }
843
844 if (sd->sensor == SENSOR_TAS5130A) {
845 i = 0;
846 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300847 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300848 sizeof tas5130a_sensor_init[0]);
849 i++;
850 }
851 reg_w(gspca_dev, 0x3c80);
852 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300853 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300854 sizeof tas5130a_sensor_init[0]);
855 reg_w(gspca_dev, 0x3c80);
856 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300857 om6802_sensor_init(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300858 }
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300859 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
860 sizeof sensor_data[sd->sensor].data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300861 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300862 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300863 reg_w_buf(gspca_dev, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300864 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300865 msleep(15);
866 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
867 sizeof sensor_data[sd->sensor].stream);
868 poll_sensor(gspca_dev);
869
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300870 /* restart on each start, just in case, sometimes regs goes wrong
871 * when using controls from app */
872 setbrightness(gspca_dev);
873 setcontrast(gspca_dev);
874 setcolors(gspca_dev);
875 return 0;
876}
877
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300878static void sd_stopN(struct gspca_dev *gspca_dev)
879{
880 struct sd *sd = (struct sd *) gspca_dev;
881
882 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
883 sizeof sensor_data[sd->sensor].stream);
884 msleep(20);
885 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
886 sizeof sensor_data[sd->sensor].stream);
887 msleep(20);
888 reg_w(gspca_dev, 0x0309);
889}
890
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300891static void sd_pkt_scan(struct gspca_dev *gspca_dev,
892 struct gspca_frame *frame, /* target */
893 __u8 *data, /* isoc packet */
894 int len) /* iso packet length */
895{
896 static __u8 ffd9[] = { 0xff, 0xd9 };
897
898 if (data[0] == 0x5a) {
899 /* Control Packet, after this came the header again,
900 * but extra bytes came in the packet before this,
901 * sometimes an EOF arrives, sometimes not... */
902 return;
903 }
904 data += 2;
905 len -= 2;
906 if (data[0] == 0xff && data[1] == 0xd8) {
907 /* extra bytes....., could be processed too but would be
908 * a waste of time, right now leave the application and
909 * libjpeg do it for ourserlves.. */
910 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
911 ffd9, 2);
912 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
913 return;
914 }
915
916 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
917 /* Just in case, i have seen packets with the marker,
918 * other's do not include it... */
919 len -= 2;
920 }
921 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922}
923
924static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 sd->brightness = val;
929 if (gspca_dev->streaming)
930 setbrightness(gspca_dev);
931 return 0;
932}
933
934static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
935{
936 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300937
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938 *val = sd->brightness;
939 return *val;
940}
941
942static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
943{
944 struct sd *sd = (struct sd *) gspca_dev;
945
946 sd->whitebalance = val;
947 if (gspca_dev->streaming)
948 setwhitebalance(gspca_dev);
949 return 0;
950}
951
952static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
953{
954 struct sd *sd = (struct sd *) gspca_dev;
955
956 *val = sd->whitebalance;
957 return *val;
958}
959
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
961{
962 struct sd *sd = (struct sd *) gspca_dev;
963
964 sd->mirror = val;
965 if (gspca_dev->streaming)
966 setflip(gspca_dev);
967 return 0;
968}
969
970static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
971{
972 struct sd *sd = (struct sd *) gspca_dev;
973
974 *val = sd->mirror;
975 return *val;
976}
977
978static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 sd->effect = val;
983 if (gspca_dev->streaming)
984 seteffect(gspca_dev);
985 return 0;
986}
987
988static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
989{
990 struct sd *sd = (struct sd *) gspca_dev;
991
992 *val = sd->effect;
993 return *val;
994}
995
996static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 sd->contrast = val;
1001 if (gspca_dev->streaming)
1002 setcontrast(gspca_dev);
1003 return 0;
1004}
1005
1006static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1007{
1008 struct sd *sd = (struct sd *) gspca_dev;
1009
1010 *val = sd->contrast;
1011 return *val;
1012}
1013
1014static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1015{
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 sd->colors = val;
1019 if (gspca_dev->streaming)
1020 setcolors(gspca_dev);
1021 return 0;
1022}
1023
1024static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1025{
1026 struct sd *sd = (struct sd *) gspca_dev;
1027
1028 *val = sd->colors;
1029 return 0;
1030}
1031
1032static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1033{
1034 struct sd *sd = (struct sd *) gspca_dev;
1035
1036 sd->gamma = val;
1037 if (gspca_dev->streaming)
1038 setgamma(gspca_dev);
1039 return 0;
1040}
1041
1042static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1043{
1044 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001045
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 *val = sd->gamma;
1047 return 0;
1048}
1049
1050static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1051{
1052 struct sd *sd = (struct sd *) gspca_dev;
1053
1054 sd->freq = val;
1055 if (gspca_dev->streaming)
1056 setlightfreq(gspca_dev);
1057 return 0;
1058}
1059
1060static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1061{
1062 struct sd *sd = (struct sd *) gspca_dev;
1063
1064 *val = sd->freq;
1065 return 0;
1066}
1067
1068static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1069{
1070 struct sd *sd = (struct sd *) gspca_dev;
1071
1072 sd->sharpness = val;
1073 if (gspca_dev->streaming)
1074 setsharpness(gspca_dev);
1075 return 0;
1076}
1077
1078static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1079{
1080 struct sd *sd = (struct sd *) gspca_dev;
1081
1082 *val = sd->sharpness;
1083 return 0;
1084}
1085
1086/* Low Light set here......*/
1087static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1088{
1089 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090
1091 sd->autogain = val;
1092 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001093 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001094 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001095 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001096 return 0;
1097}
1098
1099static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102
1103 *val = sd->autogain;
1104 return 0;
1105}
1106
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001107static int sd_querymenu(struct gspca_dev *gspca_dev,
1108 struct v4l2_querymenu *menu)
1109{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110 switch (menu->id) {
1111 case V4L2_CID_POWER_LINE_FREQUENCY:
1112 switch (menu->index) {
1113 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001114 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001115 return 0;
1116 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001117 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001118 return 0;
1119 }
1120 break;
1121 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001122 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1123 strncpy((char *) menu->name,
1124 effects_control[menu->index], 32);
1125 return 0;
1126 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127 break;
1128 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001129 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001130}
1131
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001132/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001133static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001134 .name = MODULE_NAME,
1135 .ctrls = sd_ctrls,
1136 .nctrls = ARRAY_SIZE(sd_ctrls),
1137 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001138 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001139 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001140 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001141 .pkt_scan = sd_pkt_scan,
1142 .querymenu = sd_querymenu,
1143};
1144
1145/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001146static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001147 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001148 {}
1149};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001150MODULE_DEVICE_TABLE(usb, device_table);
1151
1152/* -- device connect -- */
1153static int sd_probe(struct usb_interface *intf,
1154 const struct usb_device_id *id)
1155{
1156 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1157 THIS_MODULE);
1158}
1159
1160static struct usb_driver sd_driver = {
1161 .name = MODULE_NAME,
1162 .id_table = device_table,
1163 .probe = sd_probe,
1164 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001165#ifdef CONFIG_PM
1166 .suspend = gspca_suspend,
1167 .resume = gspca_resume,
1168#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001169};
1170
1171/* -- module insert / remove -- */
1172static int __init sd_mod_init(void)
1173{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001174 int ret;
1175 ret = usb_register(&sd_driver);
1176 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001177 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001178 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001179 return 0;
1180}
1181static void __exit sd_mod_exit(void)
1182{
1183 usb_deregister(&sd_driver);
1184 PDEBUG(D_PROBE, "deregistered");
1185}
1186
1187module_init(sd_mod_init);
1188module_exit(sd_mod_exit);