blob: 8e89024b913544b060796c6798642f15347ba70b [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
Jean-Francois Moine82e25492009-01-22 07:18:48 -030040 u8 brightness;
41 u8 contrast;
42 u8 colors;
43 u8 autogain;
44 u8 gamma;
45 u8 sharpness;
46 u8 freq;
47 u8 whitebalance;
48 u8 mirror;
49 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030050
Jean-Francois Moine82e25492009-01-22 07:18:48 -030051 u8 sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030052#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[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081 {
82 {
83 .id = V4L2_CID_BRIGHTNESS,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "Brightness",
86 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030087 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030088 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -030089#define BRIGHTNESS_DEF 8
90 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030095 {
96 {
97 .id = V4L2_CID_CONTRAST,
98 .type = V4L2_CTRL_TYPE_INTEGER,
99 .name = "Contrast",
100 .minimum = 0,
101 .maximum = 0x0d,
102 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300103#define CONTRAST_DEF 0x07
104 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300109 {
110 {
111 .id = V4L2_CID_SATURATION,
112 .type = V4L2_CTRL_TYPE_INTEGER,
113 .name = "Color",
114 .minimum = 0,
115 .maximum = 0x0f,
116 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300117#define COLORS_DEF 0x05
118 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119 },
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 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300138 {
139 {
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Low Light",
145 .minimum = 0,
146 .maximum = 1,
147 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300148#define AUTOGAIN_DEF 0x01
149 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150 },
151 .set = sd_setlowlight,
152 .get = sd_getlowlight,
153 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154 {
155 {
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
159 .minimum = 0,
160 .maximum = 1,
161 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300162#define MIRROR_DEF 0
163 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300164 },
165 .set = sd_setflip,
166 .get = sd_getflip
167 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168 {
169 {
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
174 .maximum = 2,
175 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300176#define FREQ_DEF 1
177 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178 },
179 .set = sd_setfreq,
180 .get = sd_getfreq},
181
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182 {
183 {
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
187 .minimum = 0,
188 .maximum = 1,
189 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300190#define WHITE_BALANCE_DEF 0
191 .default_value = WHITE_BALANCE_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192 },
193 .set = sd_setwhitebalance,
194 .get = sd_getwhitebalance
195 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300196 {
197 {
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Sharpness",
201 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300202 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300204#define SHARPNESS_DEF 0x06
205 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300206 },
207 .set = sd_setsharpness,
208 .get = sd_getsharpness,
209 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300210 {
211 {
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
215 .minimum = 0,
216 .maximum = 4,
217 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300218#define EFFECTS_DEF 0
219 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300220 },
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 {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300266 const u8 data1[10];
267 const u8 data2[9];
268 const u8 data3[9];
269 const u8 data4[4];
270 const u8 data5[6];
271 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300272};
273
274const static struct additional_sensor_data sensor_data[] = {
275 { /* TAS5130A */
276 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300277 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
278 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300279 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300280 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
281 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300282 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
283 {0x66, 0x00, 0xa8, 0xe8},
284 .data5 =
285 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
286 .stream =
287 {0x0b, 0x04, 0x0a, 0x40},
288 },
289 { /* OM6802 */
290 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300291 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
292 0xb3, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300293 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300294 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
295 0xff},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300296 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
297 {0x66, 0xca, 0xa8, 0xf0 },
298 .data5 = /* this could be removed later */
299 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
300 .stream =
301 {0x0b, 0x04, 0x0a, 0x78},
302 }
303};
304
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300305#define MAX_EFFECTS 7
306/* easily done by soft, this table could be removed,
307 * i keep it here just in case */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300308static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
310 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
311 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
312 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
313 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
314 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
315 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
316};
317
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300318static const u8 gamma_table[GAMMA_MAX][17] = {
319 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
320 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
321 0xff},
322 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
323 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
324 0xff},
325 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
326 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
327 0xff},
328 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
329 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
330 0xff},
331 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
332 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
333 0xff},
334 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
335 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
336 0xff},
337 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
338 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
339 0xff},
340 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
341 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
342 0xff},
343 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
344 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
345 0xff},
346 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
347 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
348 0xff},
349 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
350 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
351 0xff},
352 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8D, 0x9B, /* 11 */
353 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
354 0xff},
355 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
356 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
357 0xff},
358 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
359 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
360 0xff},
361 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
362 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
363 0xff},
364 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
365 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
366 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367};
368
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300369static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
371 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
372 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
373 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
374 {},
375};
376
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300377static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300378
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300379/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300380static u8 reg_r(struct gspca_dev *gspca_dev,
381 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300383 usb_control_msg(gspca_dev->dev,
384 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385 0, /* request */
386 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
387 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300388 index,
389 gspca_dev->usb_buf, 1, 500);
390 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300391}
392
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300393static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300394 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300396 usb_control_msg(gspca_dev->dev,
397 usb_sndctrlpipe(gspca_dev->dev, 0),
398 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300399 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300400 0, index,
401 NULL, 0, 500);
402}
403
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300404static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300405 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300406{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300407 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300408 memcpy(gspca_dev->usb_buf, buffer, len);
409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300411 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300413 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300414 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300415 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300416 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300417
418 tmpbuf = kmalloc(len, GFP_KERNEL);
419 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300420 usb_control_msg(gspca_dev->dev,
421 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300422 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300423 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300424 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300425 tmpbuf, len, 500);
426 kfree(tmpbuf);
427 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300428}
429
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300430/* write values to consecutive registers */
431static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
432 u8 reg,
433 const u8 *buffer, u16 len)
434{
435 int i;
436 u8 *p, *tmpbuf;
437
438 if (len * 2 <= USB_BUF_SZ)
439 p = tmpbuf = gspca_dev->usb_buf;
440 else
441 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
442 i = len;
443 while (--i >= 0) {
444 *p++ = reg++;
445 *p++ = *buffer++;
446 }
447 usb_control_msg(gspca_dev->dev,
448 usb_sndctrlpipe(gspca_dev->dev, 0),
449 0,
450 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
451 0x01, 0,
452 tmpbuf, len * 2, 500);
453 if (len * 2 > USB_BUF_SZ)
454 kfree(tmpbuf);
455}
456
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300457/* Reported as OM6802*/
458static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300459{
460 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300461 const u8 *p;
462 u8 byte;
463 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
464 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300465 0xdf, 0x6d,
466 0xdd, 0x18,
467 0x5a, 0xe0,
468 0x5c, 0x07,
469 0x5d, 0xb0,
470 0x5e, 0x1e,
471 0x60, 0x71,
472 0xef, 0x00,
473 0xe9, 0x00,
474 0xea, 0x00,
475 0x90, 0x24,
476 0x91, 0xb2,
477 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300478 0xfd, 0x41,
479 0x00 /* table end */
480 };
481
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300482 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
483 msleep(5);
484 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300485 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300486 byte = reg_r(gspca_dev, 0x0060);
487 if (!(byte & 0x01))
488 break;
489 msleep(100);
490 }
491 byte = reg_r(gspca_dev, 0x0063);
492 if (byte != 0x17) {
493 err("Bad sensor reset %02x", byte);
494 /* continue? */
495 }
496
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300497 p = sensor_init;
498 while (*p != 0) {
499 val[1] = *p++;
500 val[3] = *p++;
501 if (*p == 0)
502 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300503 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300504 i = 4;
505 while (--i >= 0) {
506 msleep(15);
507 byte = reg_r(gspca_dev, 0x60);
508 if (!(byte & 0x01))
509 break;
510 }
511 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300512 msleep(15);
513 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300514}
515
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516/* this function is called at probe time */
517static int sd_config(struct gspca_dev *gspca_dev,
518 const struct usb_device_id *id)
519{
520 struct sd *sd = (struct sd *) gspca_dev;
521 struct cam *cam;
522
523 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524
525 cam->cam_mode = vga_mode_t16;
526 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
527
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300528 sd->brightness = BRIGHTNESS_DEF;
529 sd->contrast = CONTRAST_DEF;
530 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300531 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300532 sd->autogain = AUTOGAIN_DEF;
533 sd->mirror = MIRROR_DEF;
534 sd->freq = FREQ_DEF;
535 sd->whitebalance = WHITE_BALANCE_DEF;
536 sd->sharpness = SHARPNESS_DEF;
537 sd->effect = EFFECTS_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538 return 0;
539}
540
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300541static void setbrightness(struct gspca_dev *gspca_dev)
542{
543 struct sd *sd = (struct sd *) gspca_dev;
544 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300545 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300546
547 brightness = sd->brightness;
548 if (brightness < 7) {
549 set6[1] = 0x26;
550 set6[3] = 0x70 - brightness * 0x10;
551 } else {
552 set6[3] = 0x00 + ((brightness - 7) * 0x10);
553 }
554
555 reg_w_buf(gspca_dev, set6, sizeof set6);
556}
557
558static void setcontrast(struct gspca_dev *gspca_dev)
559{
560 struct sd *sd = (struct sd *) gspca_dev;
561 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300562 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300563
564 if (contrast < 7)
565 reg_to_write = 0x8ea9 - contrast * 0x200;
566 else
567 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
568
569 reg_w(gspca_dev, reg_to_write);
570}
571
572static void setcolors(struct gspca_dev *gspca_dev)
573{
574 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300575 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300576
577 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
578 reg_w(gspca_dev, reg_to_write);
579}
580
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300581static void setgamma(struct gspca_dev *gspca_dev)
582{
583 struct sd *sd = (struct sd *) gspca_dev;
584
585 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300586 reg_w_ixbuf(gspca_dev, 0x90,
587 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300588}
589
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300590static void setwhitebalance(struct gspca_dev *gspca_dev)
591{
592 struct sd *sd = (struct sd *) gspca_dev;
593
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300594 u8 white_balance[8] =
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300595 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
596
597 if (sd->whitebalance)
598 white_balance[7] = 0x3c;
599
600 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
601}
602
603static void setsharpness(struct gspca_dev *gspca_dev)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300606 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300607
608 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
609
610 reg_w(gspca_dev, reg_to_write);
611}
612
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300613/* this function is called at probe and resume time */
614static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616 /* some of this registers are not really neded, because
617 * they are overriden by setbrigthness, setcontrast, etc,
618 * but wont hurt anyway, and can help someone with similar webcam
619 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300620 struct sd *sd = (struct sd *) gspca_dev;
621 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300622 u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300624 static const u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300626 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
627 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300629 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630 {0x08, 0x00};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300631 static const u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300633 static const u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
635 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
636 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
637 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
638 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
639 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
640 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
641 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
642 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300643 static const u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300645 static const u8 nset9[4] =
646 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300648 byte = reg_r(gspca_dev, 0x06);
649 test_byte = reg_r(gspca_dev, 0x07);
650 if (byte == 0x08 && test_byte == 0x07) {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300651 PDEBUG(D_CONF, "sensor om6802");
652 sd->sensor = SENSOR_OM6802;
653 } else if (byte == 0x08 && test_byte == 0x01) {
654 PDEBUG(D_CONF, "sensor tas5130a");
655 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300656 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300657 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300658 sd->sensor = SENSOR_TAS5130A;
659 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300661 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300662 test_byte = 0;
663 i = 5;
664 while (--i >= 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300665 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300666 test_byte = reg_r(gspca_dev, 0x0063);
667 msleep(100);
668 if (test_byte == 0x17)
669 break; /* OK */
670 }
671 if (i < 0) {
672 err("Bad sensor reset %02x", test_byte);
673/* return -EIO; */
674/*fixme: test - continue */
675 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300676 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300677
678 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300680 test_byte = reg_r(gspca_dev, read_indexs[i]);
681 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 test_byte);
683 i++;
684 }
685
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300686 reg_w_buf(gspca_dev, n3, sizeof n3);
687 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300688 reg_r(gspca_dev, 0x0080);
689 reg_w(gspca_dev, 0x2c80);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300690
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300691 reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1,
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300692 sizeof sensor_data[sd->sensor].data1);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300693 reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2,
694 sizeof sensor_data[sd->sensor].data2);
695 reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2,
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300696 sizeof sensor_data[sd->sensor].data2);
697
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300698 reg_w(gspca_dev, 0x3880);
699 reg_w(gspca_dev, 0x3880);
700 reg_w(gspca_dev, 0x338e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300701
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300702 setbrightness(gspca_dev);
703 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300704 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300705 setcolors(gspca_dev);
706 setsharpness(gspca_dev);
707 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300709 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300710 reg_w(gspca_dev, 0x2088);
711 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300713 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
714 sizeof sensor_data[sd->sensor].data4);
715 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
716 sizeof sensor_data[sd->sensor].data5);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300717 reg_w_buf(gspca_dev, nset8, sizeof nset8);
718 reg_w_buf(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300720 reg_w(gspca_dev, 0x2880);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300721
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300722 reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1,
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300723 sizeof sensor_data[sd->sensor].data1);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300724 reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2,
725 sizeof sensor_data[sd->sensor].data2);
726 reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2,
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300727 sizeof sensor_data[sd->sensor].data2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728
729 return 0;
730}
731
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732static void setflip(struct gspca_dev *gspca_dev)
733{
734 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300735 u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300736 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300738 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739 flipcmd[3] = 0x01;
740
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300741 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742}
743
744static void seteffect(struct gspca_dev *gspca_dev)
745{
746 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300748 reg_w_buf(gspca_dev, effects_table[sd->effect],
749 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750 if (sd->effect == 1 || sd->effect == 5) {
751 PDEBUG(D_CONF,
752 "This effect have been disabled for webcam \"safety\"");
753 return;
754 }
755
756 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300757 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300759 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300760}
761
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762static void setlightfreq(struct gspca_dev *gspca_dev)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300765 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300766
767 if (sd->freq == 2) /* 60hz */
768 freq[1] = 0x00;
769
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300770 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771}
772
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300773/* Is this really needed?
774 * i added some module parameters for test with some users */
775static void poll_sensor(struct gspca_dev *gspca_dev)
776{
777 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300778 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300779 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
780 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
781 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
782 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300783 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300784 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
785 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300786 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300787 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300788 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300789 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
790 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
791 0xc2, 0x80, 0xc3, 0x10};
792
793 if (sd->sensor != SENSOR_TAS5130A) {
794 PDEBUG(D_STREAM, "[Sensor requires polling]");
795 reg_w_buf(gspca_dev, poll1, sizeof poll1);
796 reg_w_buf(gspca_dev, poll2, sizeof poll2);
797 reg_w_buf(gspca_dev, poll3, sizeof poll3);
798 reg_w_buf(gspca_dev, poll4, sizeof poll4);
799 }
800}
801
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300802static int sd_start(struct gspca_dev *gspca_dev)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300806 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
807 static const u8 t3[] =
808 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300809
810 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
811 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300812 case 0: /* 640x480 (0x00) */
813 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300814 case 1: /* 352x288 */
815 t2[1] = 0x40;
816 break;
817 case 2: /* 320x240 */
818 t2[1] = 0x10;
819 break;
820 case 3: /* 176x144 */
821 t2[1] = 0x50;
822 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300823 default:
824/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300825 t2[1] = 0x20;
826 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300827 }
828
829 if (sd->sensor == SENSOR_TAS5130A) {
830 i = 0;
831 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300832 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300833 sizeof tas5130a_sensor_init[0]);
834 i++;
835 }
836 reg_w(gspca_dev, 0x3c80);
837 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300838 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300839 sizeof tas5130a_sensor_init[0]);
840 reg_w(gspca_dev, 0x3c80);
841 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300842 om6802_sensor_init(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300843 }
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300844 reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
845 sizeof sensor_data[sd->sensor].data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300846 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300847 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300848 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300849 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300850 msleep(15);
851 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
852 sizeof sensor_data[sd->sensor].stream);
853 poll_sensor(gspca_dev);
854
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300855 /* restart on each start, just in case, sometimes regs goes wrong
856 * when using controls from app */
857 setbrightness(gspca_dev);
858 setcontrast(gspca_dev);
859 setcolors(gspca_dev);
860 return 0;
861}
862
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300863static void sd_stopN(struct gspca_dev *gspca_dev)
864{
865 struct sd *sd = (struct sd *) gspca_dev;
866
867 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
868 sizeof sensor_data[sd->sensor].stream);
869 msleep(20);
870 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
871 sizeof sensor_data[sd->sensor].stream);
872 msleep(20);
873 reg_w(gspca_dev, 0x0309);
874}
875
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300876static void sd_pkt_scan(struct gspca_dev *gspca_dev,
877 struct gspca_frame *frame, /* target */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300878 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300879 int len) /* iso packet length */
880{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300881 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300882
883 if (data[0] == 0x5a) {
884 /* Control Packet, after this came the header again,
885 * but extra bytes came in the packet before this,
886 * sometimes an EOF arrives, sometimes not... */
887 return;
888 }
889 data += 2;
890 len -= 2;
891 if (data[0] == 0xff && data[1] == 0xd8) {
892 /* extra bytes....., could be processed too but would be
893 * a waste of time, right now leave the application and
894 * libjpeg do it for ourserlves.. */
895 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
896 ffd9, 2);
897 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
898 return;
899 }
900
901 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
902 /* Just in case, i have seen packets with the marker,
903 * other's do not include it... */
904 len -= 2;
905 }
906 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907}
908
909static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
910{
911 struct sd *sd = (struct sd *) gspca_dev;
912
913 sd->brightness = val;
914 if (gspca_dev->streaming)
915 setbrightness(gspca_dev);
916 return 0;
917}
918
919static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
920{
921 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300922
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923 *val = sd->brightness;
924 return *val;
925}
926
927static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930
931 sd->whitebalance = val;
932 if (gspca_dev->streaming)
933 setwhitebalance(gspca_dev);
934 return 0;
935}
936
937static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
941 *val = sd->whitebalance;
942 return *val;
943}
944
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300945static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948
949 sd->mirror = val;
950 if (gspca_dev->streaming)
951 setflip(gspca_dev);
952 return 0;
953}
954
955static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
956{
957 struct sd *sd = (struct sd *) gspca_dev;
958
959 *val = sd->mirror;
960 return *val;
961}
962
963static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
964{
965 struct sd *sd = (struct sd *) gspca_dev;
966
967 sd->effect = val;
968 if (gspca_dev->streaming)
969 seteffect(gspca_dev);
970 return 0;
971}
972
973static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
974{
975 struct sd *sd = (struct sd *) gspca_dev;
976
977 *val = sd->effect;
978 return *val;
979}
980
981static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
984
985 sd->contrast = val;
986 if (gspca_dev->streaming)
987 setcontrast(gspca_dev);
988 return 0;
989}
990
991static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 *val = sd->contrast;
996 return *val;
997}
998
999static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1000{
1001 struct sd *sd = (struct sd *) gspca_dev;
1002
1003 sd->colors = val;
1004 if (gspca_dev->streaming)
1005 setcolors(gspca_dev);
1006 return 0;
1007}
1008
1009static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1010{
1011 struct sd *sd = (struct sd *) gspca_dev;
1012
1013 *val = sd->colors;
1014 return 0;
1015}
1016
1017static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1018{
1019 struct sd *sd = (struct sd *) gspca_dev;
1020
1021 sd->gamma = val;
1022 if (gspca_dev->streaming)
1023 setgamma(gspca_dev);
1024 return 0;
1025}
1026
1027static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001030
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031 *val = sd->gamma;
1032 return 0;
1033}
1034
1035static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1036{
1037 struct sd *sd = (struct sd *) gspca_dev;
1038
1039 sd->freq = val;
1040 if (gspca_dev->streaming)
1041 setlightfreq(gspca_dev);
1042 return 0;
1043}
1044
1045static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1046{
1047 struct sd *sd = (struct sd *) gspca_dev;
1048
1049 *val = sd->freq;
1050 return 0;
1051}
1052
1053static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
1056
1057 sd->sharpness = val;
1058 if (gspca_dev->streaming)
1059 setsharpness(gspca_dev);
1060 return 0;
1061}
1062
1063static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1064{
1065 struct sd *sd = (struct sd *) gspca_dev;
1066
1067 *val = sd->sharpness;
1068 return 0;
1069}
1070
1071/* Low Light set here......*/
1072static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1073{
1074 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075
1076 sd->autogain = val;
1077 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001078 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001079 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001080 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001081 return 0;
1082}
1083
1084static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 *val = sd->autogain;
1089 return 0;
1090}
1091
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001092static int sd_querymenu(struct gspca_dev *gspca_dev,
1093 struct v4l2_querymenu *menu)
1094{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001095 switch (menu->id) {
1096 case V4L2_CID_POWER_LINE_FREQUENCY:
1097 switch (menu->index) {
1098 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001099 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001100 return 0;
1101 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001102 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001103 return 0;
1104 }
1105 break;
1106 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001107 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1108 strncpy((char *) menu->name,
1109 effects_control[menu->index], 32);
1110 return 0;
1111 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 break;
1113 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001114 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001115}
1116
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001118static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119 .name = MODULE_NAME,
1120 .ctrls = sd_ctrls,
1121 .nctrls = ARRAY_SIZE(sd_ctrls),
1122 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001123 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001124 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001125 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001126 .pkt_scan = sd_pkt_scan,
1127 .querymenu = sd_querymenu,
1128};
1129
1130/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001131static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001132 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001133 {}
1134};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001135MODULE_DEVICE_TABLE(usb, device_table);
1136
1137/* -- device connect -- */
1138static int sd_probe(struct usb_interface *intf,
1139 const struct usb_device_id *id)
1140{
1141 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1142 THIS_MODULE);
1143}
1144
1145static struct usb_driver sd_driver = {
1146 .name = MODULE_NAME,
1147 .id_table = device_table,
1148 .probe = sd_probe,
1149 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001150#ifdef CONFIG_PM
1151 .suspend = gspca_suspend,
1152 .resume = gspca_resume,
1153#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001154};
1155
1156/* -- module insert / remove -- */
1157static int __init sd_mod_init(void)
1158{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001159 int ret;
1160 ret = usb_register(&sd_driver);
1161 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001162 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001163 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001164 return 0;
1165}
1166static void __exit sd_mod_exit(void)
1167{
1168 usb_deregister(&sd_driver);
1169 PDEBUG(D_PROBE, "deregistered");
1170}
1171
1172module_init(sd_mod_init);
1173module_exit(sd_mod_exit);