blob: eac245d7a7561af56241fb806472eb00d877a9ad [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 Moinec2446b32008-07-05 11:49:20 -0300236static struct v4l2_pix_format vga_mode_t16[] = {
237 {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;
502 while (--i < 0) {
503 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 cam->epaddr = 0x01;
542
543 cam->cam_mode = vga_mode_t16;
544 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
545
546 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
547 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
548 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300549 sd->gamma = GAMMA_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
551 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
552 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
553 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
554 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
555 return 0;
556}
557
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300558static void setbrightness(struct gspca_dev *gspca_dev)
559{
560 struct sd *sd = (struct sd *) gspca_dev;
561 unsigned int brightness;
562 __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
563
564 brightness = sd->brightness;
565 if (brightness < 7) {
566 set6[1] = 0x26;
567 set6[3] = 0x70 - brightness * 0x10;
568 } else {
569 set6[3] = 0x00 + ((brightness - 7) * 0x10);
570 }
571
572 reg_w_buf(gspca_dev, set6, sizeof set6);
573}
574
575static void setcontrast(struct gspca_dev *gspca_dev)
576{
577 struct sd *sd = (struct sd *) gspca_dev;
578 unsigned int contrast = sd->contrast;
579 __u16 reg_to_write;
580
581 if (contrast < 7)
582 reg_to_write = 0x8ea9 - contrast * 0x200;
583 else
584 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
585
586 reg_w(gspca_dev, reg_to_write);
587}
588
589static void setcolors(struct gspca_dev *gspca_dev)
590{
591 struct sd *sd = (struct sd *) gspca_dev;
592 __u16 reg_to_write;
593
594 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
595 reg_w(gspca_dev, reg_to_write);
596}
597
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300598static void setgamma(struct gspca_dev *gspca_dev)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601
602 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300603 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300604}
605
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300606static void setwhitebalance(struct gspca_dev *gspca_dev)
607{
608 struct sd *sd = (struct sd *) gspca_dev;
609
610 __u8 white_balance[8] =
611 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
612
613 if (sd->whitebalance)
614 white_balance[7] = 0x3c;
615
616 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
617}
618
619static void setsharpness(struct gspca_dev *gspca_dev)
620{
621 struct sd *sd = (struct sd *) gspca_dev;
622 __u16 reg_to_write;
623
624 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
625
626 reg_w(gspca_dev, reg_to_write);
627}
628
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300629/* this function is called at probe and resume time */
630static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 /* some of this registers are not really neded, because
633 * they are overriden by setbrigthness, setcontrast, etc,
634 * but wont hurt anyway, and can help someone with similar webcam
635 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300636 struct sd *sd = (struct sd *) gspca_dev;
637 int i;
638 __u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300640 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
642 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300643 static const __u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300645 static const __u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646 {0x08, 0x00};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300647 static const __u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300649 static const __u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
651 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
652 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
653 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
654 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
655 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
656 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
657 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
658 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300659 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300661 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300663
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300664 byte = reg_r(gspca_dev, 0x06);
665 test_byte = reg_r(gspca_dev, 0x07);
666 if (byte == 0x08 && test_byte == 0x07) {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300667 PDEBUG(D_CONF, "sensor om6802");
668 sd->sensor = SENSOR_OM6802;
669 } else if (byte == 0x08 && test_byte == 0x01) {
670 PDEBUG(D_CONF, "sensor tas5130a");
671 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300672 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300673 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300674 sd->sensor = SENSOR_TAS5130A;
675 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300677 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300678 test_byte = 0;
679 i = 5;
680 while (--i >= 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300681 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300682 test_byte = reg_r(gspca_dev, 0x0063);
683 msleep(100);
684 if (test_byte == 0x17)
685 break; /* OK */
686 }
687 if (i < 0) {
688 err("Bad sensor reset %02x", test_byte);
689/* return -EIO; */
690/*fixme: test - continue */
691 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300692 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300693
694 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300696 test_byte = reg_r(gspca_dev, read_indexs[i]);
697 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698 test_byte);
699 i++;
700 }
701
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300702 reg_w_buf(gspca_dev, n3, sizeof n3);
703 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300704 reg_r(gspca_dev, 0x0080);
705 reg_w(gspca_dev, 0x2c80);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300706
707 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
708 sizeof sensor_data[sd->sensor].data1);
709 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
710 sizeof sensor_data[sd->sensor].data3);
711 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
712 sizeof sensor_data[sd->sensor].data2);
713
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300714 reg_w(gspca_dev, 0x3880);
715 reg_w(gspca_dev, 0x3880);
716 reg_w(gspca_dev, 0x338e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300717
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300718 setbrightness(gspca_dev);
719 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300720 setgamma(gspca_dev);
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300721 setcolors(gspca_dev);
722 setsharpness(gspca_dev);
723 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300724
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300725 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300726 reg_w(gspca_dev, 0x2088);
727 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300729 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
730 sizeof sensor_data[sd->sensor].data4);
731 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
732 sizeof sensor_data[sd->sensor].data5);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300733 reg_w_buf(gspca_dev, nset8, sizeof nset8);
734 reg_w_buf(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300736 reg_w(gspca_dev, 0x2880);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300737
738 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
739 sizeof sensor_data[sd->sensor].data1);
740 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
741 sizeof sensor_data[sd->sensor].data3);
742 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
743 sizeof sensor_data[sd->sensor].data2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744
745 return 0;
746}
747
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748static void setflip(struct gspca_dev *gspca_dev)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300751 __u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300752 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300754 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755 flipcmd[3] = 0x01;
756
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300757 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758}
759
760static void seteffect(struct gspca_dev *gspca_dev)
761{
762 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300763
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300764 reg_w_buf(gspca_dev, effects_table[sd->effect],
765 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300766 if (sd->effect == 1 || sd->effect == 5) {
767 PDEBUG(D_CONF,
768 "This effect have been disabled for webcam \"safety\"");
769 return;
770 }
771
772 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300773 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300775 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300776}
777
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778static void setlightfreq(struct gspca_dev *gspca_dev)
779{
780 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
782
783 if (sd->freq == 2) /* 60hz */
784 freq[1] = 0x00;
785
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300786 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300787}
788
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300789/* Is this really needed?
790 * i added some module parameters for test with some users */
791static void poll_sensor(struct gspca_dev *gspca_dev)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794 static const __u8 poll1[] =
795 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
796 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
797 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
798 0x60, 0x14};
799 static const __u8 poll2[] =
800 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
801 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
802 static const __u8 poll3[] =
803 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
804 static const __u8 poll4[] =
805 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
806 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
807 0xc2, 0x80, 0xc3, 0x10};
808
809 if (sd->sensor != SENSOR_TAS5130A) {
810 PDEBUG(D_STREAM, "[Sensor requires polling]");
811 reg_w_buf(gspca_dev, poll1, sizeof poll1);
812 reg_w_buf(gspca_dev, poll2, sizeof poll2);
813 reg_w_buf(gspca_dev, poll3, sizeof poll3);
814 reg_w_buf(gspca_dev, poll4, sizeof poll4);
815 }
816}
817
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300818static int sd_start(struct gspca_dev *gspca_dev)
819{
820 struct sd *sd = (struct sd *) gspca_dev;
821 int i, mode;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300822 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
823 static const __u8 t3[] =
824 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
825 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300826
827 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
828 switch (mode) {
829 case 1: /* 352x288 */
830 t2[1] = 0x40;
831 break;
832 case 2: /* 320x240 */
833 t2[1] = 0x10;
834 break;
835 case 3: /* 176x144 */
836 t2[1] = 0x50;
837 break;
838 case 4: /* 160x120 */
839 t2[1] = 0x20;
840 break;
841 default: /* 640x480 (0x00) */
842 break;
843 }
844
845 if (sd->sensor == SENSOR_TAS5130A) {
846 i = 0;
847 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300848 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300849 sizeof tas5130a_sensor_init[0]);
850 i++;
851 }
852 reg_w(gspca_dev, 0x3c80);
853 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300854 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300855 sizeof tas5130a_sensor_init[0]);
856 reg_w(gspca_dev, 0x3c80);
857 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300858 om6802_sensor_init(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300859 }
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300860 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
861 sizeof sensor_data[sd->sensor].data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300862 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300863 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300864 reg_w_buf(gspca_dev, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300865 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300866 msleep(15);
867 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
868 sizeof sensor_data[sd->sensor].stream);
869 poll_sensor(gspca_dev);
870
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300871 /* restart on each start, just in case, sometimes regs goes wrong
872 * when using controls from app */
873 setbrightness(gspca_dev);
874 setcontrast(gspca_dev);
875 setcolors(gspca_dev);
876 return 0;
877}
878
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300879static void sd_stopN(struct gspca_dev *gspca_dev)
880{
881 struct sd *sd = (struct sd *) gspca_dev;
882
883 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
884 sizeof sensor_data[sd->sensor].stream);
885 msleep(20);
886 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
887 sizeof sensor_data[sd->sensor].stream);
888 msleep(20);
889 reg_w(gspca_dev, 0x0309);
890}
891
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300892static void sd_pkt_scan(struct gspca_dev *gspca_dev,
893 struct gspca_frame *frame, /* target */
894 __u8 *data, /* isoc packet */
895 int len) /* iso packet length */
896{
897 static __u8 ffd9[] = { 0xff, 0xd9 };
898
899 if (data[0] == 0x5a) {
900 /* Control Packet, after this came the header again,
901 * but extra bytes came in the packet before this,
902 * sometimes an EOF arrives, sometimes not... */
903 return;
904 }
905 data += 2;
906 len -= 2;
907 if (data[0] == 0xff && data[1] == 0xd8) {
908 /* extra bytes....., could be processed too but would be
909 * a waste of time, right now leave the application and
910 * libjpeg do it for ourserlves.. */
911 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
912 ffd9, 2);
913 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
914 return;
915 }
916
917 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
918 /* Just in case, i have seen packets with the marker,
919 * other's do not include it... */
920 len -= 2;
921 }
922 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923}
924
925static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
926{
927 struct sd *sd = (struct sd *) gspca_dev;
928
929 sd->brightness = val;
930 if (gspca_dev->streaming)
931 setbrightness(gspca_dev);
932 return 0;
933}
934
935static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300938
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939 *val = sd->brightness;
940 return *val;
941}
942
943static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 sd->whitebalance = val;
948 if (gspca_dev->streaming)
949 setwhitebalance(gspca_dev);
950 return 0;
951}
952
953static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
956
957 *val = sd->whitebalance;
958 return *val;
959}
960
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
962{
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 sd->mirror = val;
966 if (gspca_dev->streaming)
967 setflip(gspca_dev);
968 return 0;
969}
970
971static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
974
975 *val = sd->mirror;
976 return *val;
977}
978
979static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
983 sd->effect = val;
984 if (gspca_dev->streaming)
985 seteffect(gspca_dev);
986 return 0;
987}
988
989static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
990{
991 struct sd *sd = (struct sd *) gspca_dev;
992
993 *val = sd->effect;
994 return *val;
995}
996
997static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000
1001 sd->contrast = val;
1002 if (gspca_dev->streaming)
1003 setcontrast(gspca_dev);
1004 return 0;
1005}
1006
1007static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1008{
1009 struct sd *sd = (struct sd *) gspca_dev;
1010
1011 *val = sd->contrast;
1012 return *val;
1013}
1014
1015static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1016{
1017 struct sd *sd = (struct sd *) gspca_dev;
1018
1019 sd->colors = val;
1020 if (gspca_dev->streaming)
1021 setcolors(gspca_dev);
1022 return 0;
1023}
1024
1025static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1026{
1027 struct sd *sd = (struct sd *) gspca_dev;
1028
1029 *val = sd->colors;
1030 return 0;
1031}
1032
1033static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1034{
1035 struct sd *sd = (struct sd *) gspca_dev;
1036
1037 sd->gamma = val;
1038 if (gspca_dev->streaming)
1039 setgamma(gspca_dev);
1040 return 0;
1041}
1042
1043static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1044{
1045 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001046
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047 *val = sd->gamma;
1048 return 0;
1049}
1050
1051static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1052{
1053 struct sd *sd = (struct sd *) gspca_dev;
1054
1055 sd->freq = val;
1056 if (gspca_dev->streaming)
1057 setlightfreq(gspca_dev);
1058 return 0;
1059}
1060
1061static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1062{
1063 struct sd *sd = (struct sd *) gspca_dev;
1064
1065 *val = sd->freq;
1066 return 0;
1067}
1068
1069static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1070{
1071 struct sd *sd = (struct sd *) gspca_dev;
1072
1073 sd->sharpness = val;
1074 if (gspca_dev->streaming)
1075 setsharpness(gspca_dev);
1076 return 0;
1077}
1078
1079static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1080{
1081 struct sd *sd = (struct sd *) gspca_dev;
1082
1083 *val = sd->sharpness;
1084 return 0;
1085}
1086
1087/* Low Light set here......*/
1088static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1089{
1090 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091
1092 sd->autogain = val;
1093 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001094 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001095 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001096 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001097 return 0;
1098}
1099
1100static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 *val = sd->autogain;
1105 return 0;
1106}
1107
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001108static int sd_querymenu(struct gspca_dev *gspca_dev,
1109 struct v4l2_querymenu *menu)
1110{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001111 switch (menu->id) {
1112 case V4L2_CID_POWER_LINE_FREQUENCY:
1113 switch (menu->index) {
1114 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001115 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001116 return 0;
1117 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001118 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119 return 0;
1120 }
1121 break;
1122 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001123 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1124 strncpy((char *) menu->name,
1125 effects_control[menu->index], 32);
1126 return 0;
1127 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001128 break;
1129 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001130 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001131}
1132
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001133/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001134static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001135 .name = MODULE_NAME,
1136 .ctrls = sd_ctrls,
1137 .nctrls = ARRAY_SIZE(sd_ctrls),
1138 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001139 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001141 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142 .pkt_scan = sd_pkt_scan,
1143 .querymenu = sd_querymenu,
1144};
1145
1146/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001147static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001148 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001149 {}
1150};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001151MODULE_DEVICE_TABLE(usb, device_table);
1152
1153/* -- device connect -- */
1154static int sd_probe(struct usb_interface *intf,
1155 const struct usb_device_id *id)
1156{
1157 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1158 THIS_MODULE);
1159}
1160
1161static struct usb_driver sd_driver = {
1162 .name = MODULE_NAME,
1163 .id_table = device_table,
1164 .probe = sd_probe,
1165 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001166#ifdef CONFIG_PM
1167 .suspend = gspca_suspend,
1168 .resume = gspca_resume,
1169#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001170};
1171
1172/* -- module insert / remove -- */
1173static int __init sd_mod_init(void)
1174{
1175 if (usb_register(&sd_driver) < 0)
1176 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001177 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001178 return 0;
1179}
1180static void __exit sd_mod_exit(void)
1181{
1182 usb_deregister(&sd_driver);
1183 PDEBUG(D_PROBE, "deregistered");
1184}
1185
1186module_init(sd_mod_init);
1187module_exit(sd_mod_exit);