blob: a3eccd81576625119350e6177cb834d72c7ba652 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
Jean-François Moinecd8955b2010-06-04 07:22:57 -03002 * T613 subdriver
3 *
4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030019 *
20 *Notes: * t613 + tas5130A
21 * * Focus to light do not balance well as in win.
22 * Quality in win is not good, but its kinda better.
23 * * Fix some "extraneous bytes", most of apps will show the image anyway
24 * * Gamma table, is there, but its really doing something?
25 * * 7~8 Fps, its ok, max on win its 10.
26 * Costantino Leandro
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027 */
28
29#define MODULE_NAME "t613"
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030030
Jean-François Moinebe2a9fa2010-06-04 06:42:32 -030031#include <linux/slab.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030033
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030034#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030035
36MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
37MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
42
Jean-Francois Moine82e25492009-01-22 07:18:48 -030043 u8 brightness;
44 u8 contrast;
45 u8 colors;
46 u8 autogain;
47 u8 gamma;
48 u8 sharpness;
49 u8 freq;
Jean-François Moinee9b15652010-06-05 07:07:56 -030050 u8 red_gain;
51 u8 blue_gain;
52 u8 green_gain;
Jean-François Moinecd8955b2010-06-04 07:22:57 -030053 u8 awb; /* set default r/g/b and activate */
Jean-Francois Moine82e25492009-01-22 07:18:48 -030054 u8 mirror;
55 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030056
Jean-Francois Moine82e25492009-01-22 07:18:48 -030057 u8 sensor;
Jean-François Moine11ce8842010-07-26 06:39:40 -030058};
59enum sensors {
Jean-François Moinecd8955b2010-06-04 07:22:57 -030060 SENSOR_OM6802,
61 SENSOR_OTHER,
62 SENSOR_TAS5130A,
63 SENSOR_LT168G, /* must verify if this is the actual model */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064};
65
66/* V4L2 controls supported by the driver */
67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030081
Jean-François Moinecd8955b2010-06-04 07:22:57 -030082static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
Jean-François Moinee9b15652010-06-05 07:07:56 -030084static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030090
Jean-François Moinecd8955b2010-06-04 07:22:57 -030091static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
95static int sd_querymenu(struct gspca_dev *gspca_dev,
96 struct v4l2_querymenu *menu);
97
Marton Nemeth7e64dc42009-12-30 09:12:41 -030098static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030099 {
100 {
101 .id = V4L2_CID_BRIGHTNESS,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Brightness",
104 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300105 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300106 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300107#define BRIGHTNESS_DEF 8
108 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300109 },
110 .set = sd_setbrightness,
111 .get = sd_getbrightness,
112 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300113 {
114 {
115 .id = V4L2_CID_CONTRAST,
116 .type = V4L2_CTRL_TYPE_INTEGER,
117 .name = "Contrast",
118 .minimum = 0,
119 .maximum = 0x0d,
120 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300121#define CONTRAST_DEF 0x07
122 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300123 },
124 .set = sd_setcontrast,
125 .get = sd_getcontrast,
126 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127 {
128 {
129 .id = V4L2_CID_SATURATION,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "Color",
132 .minimum = 0,
133 .maximum = 0x0f,
134 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300135#define COLORS_DEF 0x05
136 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300137 },
138 .set = sd_setcolors,
139 .get = sd_getcolors,
140 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300141#define GAMMA_MAX 16
142#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143 {
144 {
145 .id = V4L2_CID_GAMMA, /* (gamma on win) */
146 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300147 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300148 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300149 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300151 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152 },
153 .set = sd_setgamma,
154 .get = sd_getgamma,
155 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156 {
157 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300158 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300159 * some apps dont bring up the
160 * backligth_compensation control) */
161 .type = V4L2_CTRL_TYPE_INTEGER,
162 .name = "Low Light",
163 .minimum = 0,
164 .maximum = 1,
165 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300166#define AUTOGAIN_DEF 0x01
167 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168 },
169 .set = sd_setlowlight,
170 .get = sd_getlowlight,
171 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 {
173 {
174 .id = V4L2_CID_HFLIP,
175 .type = V4L2_CTRL_TYPE_BOOLEAN,
176 .name = "Mirror Image",
177 .minimum = 0,
178 .maximum = 1,
179 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300180#define MIRROR_DEF 0
181 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300183 .set = sd_setmirror,
184 .get = sd_getmirror
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300185 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300186 {
187 {
188 .id = V4L2_CID_POWER_LINE_FREQUENCY,
189 .type = V4L2_CTRL_TYPE_MENU,
190 .name = "Light Frequency Filter",
191 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
192 .maximum = 2,
193 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300194#define FREQ_DEF 1
195 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300196 },
197 .set = sd_setfreq,
198 .get = sd_getfreq},
199
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300200 {
201 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300202 .id = V4L2_CID_AUTO_WHITE_BALANCE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300204 .name = "Auto White Balance",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300205 .minimum = 0,
206 .maximum = 1,
207 .step = 1,
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300208#define AWB_DEF 0
209 .default_value = AWB_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300210 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300211 .set = sd_setawb,
212 .get = sd_getawb
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300213 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300214 {
215 {
216 .id = V4L2_CID_SHARPNESS,
217 .type = V4L2_CTRL_TYPE_INTEGER,
218 .name = "Sharpness",
219 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300220 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300221 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300222#define SHARPNESS_DEF 0x06
223 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300224 },
225 .set = sd_setsharpness,
226 .get = sd_getsharpness,
227 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228 {
229 {
230 .id = V4L2_CID_EFFECTS,
231 .type = V4L2_CTRL_TYPE_MENU,
232 .name = "Webcam Effects",
233 .minimum = 0,
234 .maximum = 4,
235 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300236#define EFFECTS_DEF 0
237 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300238 },
239 .set = sd_seteffect,
240 .get = sd_geteffect
241 },
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300242 {
243 {
244 .id = V4L2_CID_BLUE_BALANCE,
245 .type = V4L2_CTRL_TYPE_INTEGER,
246 .name = "Blue Balance",
247 .minimum = 0x10,
248 .maximum = 0x40,
249 .step = 1,
Jean-François Moinee9b15652010-06-05 07:07:56 -0300250#define BLUE_GAIN_DEF 0x20
251 .default_value = BLUE_GAIN_DEF,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300252 },
Jean-François Moinee9b15652010-06-05 07:07:56 -0300253 .set = sd_setblue_gain,
254 .get = sd_getblue_gain,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300255 },
256 {
257 {
258 .id = V4L2_CID_RED_BALANCE,
259 .type = V4L2_CTRL_TYPE_INTEGER,
260 .name = "Red Balance",
261 .minimum = 0x10,
262 .maximum = 0x40,
263 .step = 1,
Jean-François Moinee9b15652010-06-05 07:07:56 -0300264#define RED_GAIN_DEF 0x20
265 .default_value = RED_GAIN_DEF,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300266 },
Jean-François Moinee9b15652010-06-05 07:07:56 -0300267 .set = sd_setred_gain,
268 .get = sd_getred_gain,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300269 },
270 {
271 {
272 .id = V4L2_CID_GAIN,
273 .type = V4L2_CTRL_TYPE_INTEGER,
274 .name = "Gain",
275 .minimum = 0x10,
276 .maximum = 0x40,
277 .step = 1,
Jean-François Moinee9b15652010-06-05 07:07:56 -0300278#define GAIN_DEF 0x20
279 .default_value = GAIN_DEF,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300280 },
Jean-François Moinee9b15652010-06-05 07:07:56 -0300281 .set = sd_setgain,
282 .get = sd_getgain,
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300283 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300284};
285
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300286static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300287 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
288 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300289 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300290 .colorspace = V4L2_COLORSPACE_JPEG,
291 .priv = 4},
292 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
293 .bytesperline = 176,
294 .sizeimage = 176 * 144 * 3 / 8 + 590,
295 .colorspace = V4L2_COLORSPACE_JPEG,
296 .priv = 3},
297 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
298 .bytesperline = 320,
299 .sizeimage = 320 * 240 * 3 / 8 + 590,
300 .colorspace = V4L2_COLORSPACE_JPEG,
301 .priv = 2},
302 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
303 .bytesperline = 352,
304 .sizeimage = 352 * 288 * 3 / 8 + 590,
305 .colorspace = V4L2_COLORSPACE_JPEG,
306 .priv = 1},
307 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
308 .bytesperline = 640,
309 .sizeimage = 640 * 480 * 3 / 8 + 590,
310 .colorspace = V4L2_COLORSPACE_JPEG,
311 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312};
313
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300314/* sensor specific data */
315struct additional_sensor_data {
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300316 const u8 n3[6];
317 const u8 *n4, n4sz;
318 const u8 reg80, reg8e;
319 const u8 nset8[6];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300320 const u8 data1[10];
321 const u8 data2[9];
322 const u8 data3[9];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300323 const u8 data5[6];
324 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300325};
326
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300327static const u8 n4_om6802[] = {
328 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
329 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
330 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
331 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
332 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
333 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
334 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
335 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
336 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
337};
338static const u8 n4_other[] = {
339 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
340 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
341 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
342 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
343 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
344 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
345 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
346 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
347};
348static const u8 n4_tas5130a[] = {
349 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
350 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
351 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
352 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
353 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
354 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
355 0xc6, 0xda
356};
Nicolau Werneck00e80062010-01-30 16:00:15 -0300357static const u8 n4_lt168g[] = {
358 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
359 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
360 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
361 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
362 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
363 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
364 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
365 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
366 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
367};
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300368
Tobias Klausere23b2902009-02-09 18:06:49 -0300369static const struct additional_sensor_data sensor_data[] = {
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300370[SENSOR_OM6802] = {
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300371 .n3 =
372 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
373 .n4 = n4_om6802,
374 .n4sz = sizeof n4_om6802,
375 .reg80 = 0x3c,
376 .reg8e = 0x33,
377 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300378 .data1 =
379 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
380 0xb3, 0xfc},
381 .data2 =
382 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
383 0xff},
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300384 .data3 =
385 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
386 0xff},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300387 .data5 = /* this could be removed later */
388 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
389 .stream =
390 {0x0b, 0x04, 0x0a, 0x78},
391 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300392[SENSOR_OTHER] = {
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300393 .n3 =
394 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
395 .n4 = n4_other,
396 .n4sz = sizeof n4_other,
397 .reg80 = 0xac,
398 .reg8e = 0xb8,
399 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300400 .data1 =
401 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
402 0xe8, 0xfc},
403 .data2 =
404 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
405 0xd9},
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300406 .data3 =
407 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
408 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300409 .data5 =
410 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
411 .stream =
412 {0x0b, 0x04, 0x0a, 0x00},
413 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300414[SENSOR_TAS5130A] = {
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300415 .n3 =
416 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
417 .n4 = n4_tas5130a,
418 .n4sz = sizeof n4_tas5130a,
419 .reg80 = 0x3c,
420 .reg8e = 0xb4,
421 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300422 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300423 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
424 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300425 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300426 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
427 0xe0},
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300428 .data3 =
429 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
430 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300431 .data5 =
432 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
433 .stream =
434 {0x0b, 0x04, 0x0a, 0x40},
435 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300436[SENSOR_LT168G] = {
Nicolau Werneck00e80062010-01-30 16:00:15 -0300437 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
438 .n4 = n4_lt168g,
439 .n4sz = sizeof n4_lt168g,
440 .reg80 = 0x7c,
441 .reg8e = 0xb3,
442 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
443 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
444 0xb0, 0xf4},
445 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446 0xff},
447 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
448 0xff},
Nicolau Werneck00e80062010-01-30 16:00:15 -0300449 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
450 .stream = {0x0b, 0x04, 0x0a, 0x28},
451 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300452};
453
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300454#define MAX_EFFECTS 7
455/* easily done by soft, this table could be removed,
456 * i keep it here just in case */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300457static char *effects_control[MAX_EFFECTS] = {
458 "Normal",
459 "Emboss", /* disabled */
460 "Monochrome",
461 "Sepia",
462 "Sketch",
463 "Sun Effect", /* disabled */
464 "Negative",
465};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300466static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
468 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
470 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
471 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
473 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
474};
475
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300476static const u8 gamma_table[GAMMA_MAX][17] = {
Jean-François Moine79960d32010-06-04 07:24:53 -0300477/* gamma table from cam1690.ini */
478 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
479 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300480 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300481 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
482 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300483 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300484 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
485 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300486 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300487 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
488 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300489 0xff},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300490 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
Jean-François Moine79960d32010-06-04 07:24:53 -0300491 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300492 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300493 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
494 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300495 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300496 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300497 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
498 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300499 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300500 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
501 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300502 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
503 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300504 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300505 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
506 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300507 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300508 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
509 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300510 0xff},
Jean-François Moine79960d32010-06-04 07:24:53 -0300511 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300512 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
513 0xff},
514 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
515 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
516 0xff},
517 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
518 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
519 0xff},
520 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
521 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
522 0xff},
523 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
524 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
525 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300526};
527
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300528static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
530 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
531 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532};
533
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300534static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300535
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300536/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300537static u8 reg_r(struct gspca_dev *gspca_dev,
538 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300540 usb_control_msg(gspca_dev->dev,
541 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 0, /* request */
543 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
544 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 index,
546 gspca_dev->usb_buf, 1, 500);
547 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548}
549
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300551 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300552{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300553 usb_control_msg(gspca_dev->dev,
554 usb_sndctrlpipe(gspca_dev->dev, 0),
555 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300556 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300557 0, index,
558 NULL, 0, 500);
559}
560
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300561static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300562 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300563{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300564 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300565 memcpy(gspca_dev->usb_buf, buffer, len);
566 usb_control_msg(gspca_dev->dev,
567 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300568 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300569 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300570 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300571 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300572 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300573 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300574
Julia Lawallfeda79b2010-07-01 01:30:11 -0300575 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300576 if (!tmpbuf) {
577 err("Out of memory");
578 return;
579 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300580 usb_control_msg(gspca_dev->dev,
581 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300582 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300583 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300584 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300585 tmpbuf, len, 500);
586 kfree(tmpbuf);
587 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588}
589
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300590/* write values to consecutive registers */
591static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
592 u8 reg,
593 const u8 *buffer, u16 len)
594{
595 int i;
596 u8 *p, *tmpbuf;
597
Jean-François Moine24f222e2010-03-07 05:58:55 -0300598 if (len * 2 <= USB_BUF_SZ) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300599 p = tmpbuf = gspca_dev->usb_buf;
Jean-François Moine24f222e2010-03-07 05:58:55 -0300600 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300601 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300602 if (!tmpbuf) {
603 err("Out of memory");
604 return;
605 }
606 }
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300607 i = len;
608 while (--i >= 0) {
609 *p++ = reg++;
610 *p++ = *buffer++;
611 }
612 usb_control_msg(gspca_dev->dev,
613 usb_sndctrlpipe(gspca_dev->dev, 0),
614 0,
615 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
616 0x01, 0,
617 tmpbuf, len * 2, 500);
618 if (len * 2 > USB_BUF_SZ)
619 kfree(tmpbuf);
620}
621
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300622static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300623{
624 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300625 const u8 *p;
626 u8 byte;
627 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
628 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300629 0xdf, 0x6d,
630 0xdd, 0x18,
631 0x5a, 0xe0,
632 0x5c, 0x07,
633 0x5d, 0xb0,
634 0x5e, 0x1e,
635 0x60, 0x71,
636 0xef, 0x00,
637 0xe9, 0x00,
638 0xea, 0x00,
639 0x90, 0x24,
640 0x91, 0xb2,
641 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300642 0xfd, 0x41,
643 0x00 /* table end */
644 };
645
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300646 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300647 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300648 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300649 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300650 byte = reg_r(gspca_dev, 0x0060);
651 if (!(byte & 0x01))
652 break;
653 msleep(100);
654 }
655 byte = reg_r(gspca_dev, 0x0063);
656 if (byte != 0x17) {
657 err("Bad sensor reset %02x", byte);
658 /* continue? */
659 }
660
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300661 p = sensor_init;
662 while (*p != 0) {
663 val[1] = *p++;
664 val[3] = *p++;
665 if (*p == 0)
666 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300667 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300668 i = 4;
669 while (--i >= 0) {
670 msleep(15);
671 byte = reg_r(gspca_dev, 0x60);
672 if (!(byte & 0x01))
673 break;
674 }
675 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300676 msleep(15);
677 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300678}
679
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680/* this function is called at probe time */
681static int sd_config(struct gspca_dev *gspca_dev,
682 const struct usb_device_id *id)
683{
684 struct sd *sd = (struct sd *) gspca_dev;
685 struct cam *cam;
686
687 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300688
689 cam->cam_mode = vga_mode_t16;
690 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
691
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300692 sd->brightness = BRIGHTNESS_DEF;
693 sd->contrast = CONTRAST_DEF;
694 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300695 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300696 sd->autogain = AUTOGAIN_DEF;
697 sd->mirror = MIRROR_DEF;
698 sd->freq = FREQ_DEF;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300699 sd->awb = AWB_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300700 sd->sharpness = SHARPNESS_DEF;
701 sd->effect = EFFECTS_DEF;
Jean-François Moinee9b15652010-06-05 07:07:56 -0300702 sd->red_gain = RED_GAIN_DEF;
703 sd->blue_gain = BLUE_GAIN_DEF;
704 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300705
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706 return 0;
707}
708
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300709static void setbrightness(struct gspca_dev *gspca_dev)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300713 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300714
715 brightness = sd->brightness;
716 if (brightness < 7) {
717 set6[1] = 0x26;
718 set6[3] = 0x70 - brightness * 0x10;
719 } else {
720 set6[3] = 0x00 + ((brightness - 7) * 0x10);
721 }
722
723 reg_w_buf(gspca_dev, set6, sizeof set6);
724}
725
726static void setcontrast(struct gspca_dev *gspca_dev)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300730 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300731
732 if (contrast < 7)
733 reg_to_write = 0x8ea9 - contrast * 0x200;
734 else
735 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
736
737 reg_w(gspca_dev, reg_to_write);
738}
739
740static void setcolors(struct gspca_dev *gspca_dev)
741{
742 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300743 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300744
745 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
746 reg_w(gspca_dev, reg_to_write);
747}
748
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300749static void setgamma(struct gspca_dev *gspca_dev)
750{
751 struct sd *sd = (struct sd *) gspca_dev;
752
753 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300754 reg_w_ixbuf(gspca_dev, 0x90,
755 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300756}
757
Jean-François Moinee9b15652010-06-05 07:07:56 -0300758static void setRGB(struct gspca_dev *gspca_dev)
759{
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300760 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinee9b15652010-06-05 07:07:56 -0300761 u8 all_gain_reg[6] =
762 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
763
764 all_gain_reg[1] = sd->red_gain;
765 all_gain_reg[3] = sd->blue_gain;
766 all_gain_reg[5] = sd->green_gain;
767 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300768}
769
Jean-François Moinee9b15652010-06-05 07:07:56 -0300770/* Generic fnc for r/b balance, exposure and awb */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300771static void setawb(struct gspca_dev *gspca_dev)
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300772{
773 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinee9b15652010-06-05 07:07:56 -0300774 u16 reg80;
775
776 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300777
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300778 /* on awb leave defaults values */
Jean-François Moinee9b15652010-06-05 07:07:56 -0300779 if (!sd->awb) {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300780 /* shoud we wait here.. */
Jean-François Moinee9b15652010-06-05 07:07:56 -0300781 /* update and reset RGB gains with webcam values */
782 sd->red_gain = reg_r(gspca_dev, 0x0087);
783 sd->blue_gain = reg_r(gspca_dev, 0x0088);
784 sd->green_gain = reg_r(gspca_dev, 0x0089);
785 reg80 &= ~0x0400; /* AWB off */
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300786 }
Jean-François Moinee9b15652010-06-05 07:07:56 -0300787 reg_w(gspca_dev, reg80);
788 reg_w(gspca_dev, reg80);
789}
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300790
Jean-François Moinee9b15652010-06-05 07:07:56 -0300791static void init_gains(struct gspca_dev *gspca_dev)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794 u16 reg80;
795 u8 all_gain_reg[8] =
796 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
797
798 all_gain_reg[1] = sd->red_gain;
799 all_gain_reg[3] = sd->blue_gain;
800 all_gain_reg[5] = sd->green_gain;
801 reg80 = sensor_data[sd->sensor].reg80;
802 if (!sd->awb)
803 reg80 &= ~0x04;
804 all_gain_reg[7] = reg80;
805 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
806
807 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87);
808 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
809 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300810}
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300811
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300812static void setsharpness(struct gspca_dev *gspca_dev)
813{
814 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300815 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300816
817 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
818
819 reg_w(gspca_dev, reg_to_write);
820}
821
Jean-François Moine78b98cb2010-06-05 07:01:46 -0300822static void setfreq(struct gspca_dev *gspca_dev)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
825 u8 reg66;
826 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
827
828 switch (sd->sensor) {
829 case SENSOR_LT168G:
830 if (sd->freq != 0)
831 freq[3] = 0xa8;
832 reg66 = 0x41;
833 break;
834 case SENSOR_OM6802:
835 reg66 = 0xca;
836 break;
837 default:
838 reg66 = 0x40;
839 break;
840 }
841 switch (sd->freq) {
842 case 0: /* no flicker */
843 freq[3] = 0xf0;
844 break;
845 case 2: /* 60Hz */
846 reg66 &= ~0x40;
847 break;
848 }
849 freq[1] = reg66;
850
851 reg_w_buf(gspca_dev, freq, sizeof freq);
852}
853
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300854/* this function is called at probe and resume time */
855static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857 /* some of this registers are not really neded, because
858 * they are overriden by setbrigthness, setcontrast, etc,
859 * but wont hurt anyway, and can help someone with similar webcam
860 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300861 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300862 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300863 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300864 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300865 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300867 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300868 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300869 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
870 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300871 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300872 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300875 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
876 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300877 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300878 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300879 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300880 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300881 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300882 case 0x0802:
883 PDEBUG(D_PROBE, "sensor lt168g");
884 sd->sensor = SENSOR_LT168G;
885 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300886 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300887 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300888 sd->sensor = SENSOR_OTHER;
889 break;
890 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300891 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300892 sd->sensor = SENSOR_OM6802;
893 break;
894 default:
Jean-François Moine0b656322010-09-13 05:19:58 -0300895 err("unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300896 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300897 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300899 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300900 reg_w_buf(gspca_dev, n1, sizeof n1);
901 i = 5;
902 while (--i >= 0) {
903 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
904 test_byte = reg_r(gspca_dev, 0x0063);
905 msleep(100);
906 if (test_byte == 0x17)
907 break; /* OK */
908 }
909 if (i < 0) {
910 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300911 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300912 }
913 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300914 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300915
916 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300918 test_byte = reg_r(gspca_dev, read_indexs[i]);
919 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 test_byte);
921 i++;
922 }
923
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300924 sensor = &sensor_data[sd->sensor];
925 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
926 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300927
Nicolau Werneck00e80062010-01-30 16:00:15 -0300928 if (sd->sensor == SENSOR_LT168G) {
929 test_byte = reg_r(gspca_dev, 0x80);
930 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
931 test_byte);
932 reg_w(gspca_dev, 0x6c80);
933 }
934
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300935 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
936 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
937 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300938
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300939 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
940 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
941 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300942
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300943 setbrightness(gspca_dev);
944 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300945 setgamma(gspca_dev);
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300946 setcolors(gspca_dev);
947 setsharpness(gspca_dev);
Jean-François Moinee9b15652010-06-05 07:07:56 -0300948 init_gains(gspca_dev);
Jean-François Moine78b98cb2010-06-05 07:01:46 -0300949 setfreq(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300951 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
952 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
953 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300954
Nicolau Werneck00e80062010-01-30 16:00:15 -0300955 if (sd->sensor == SENSOR_LT168G) {
956 test_byte = reg_r(gspca_dev, 0x80);
957 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
958 test_byte);
959 reg_w(gspca_dev, 0x6c80);
960 }
961
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -0300962 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
963 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
964 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965
966 return 0;
967}
968
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300969static void setmirror(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970{
971 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300972 u8 hflipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300973 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300974
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300975 if (sd->mirror)
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300976 hflipcmd[3] = 0x01;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300978 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979}
980
981static void seteffect(struct gspca_dev *gspca_dev)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300985 reg_w_buf(gspca_dev, effects_table[sd->effect],
986 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 if (sd->effect == 1 || sd->effect == 5) {
988 PDEBUG(D_CONF,
989 "This effect have been disabled for webcam \"safety\"");
990 return;
991 }
992
993 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300994 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300996 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997}
998
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300999/* Is this really needed?
1000 * i added some module parameters for test with some users */
1001static void poll_sensor(struct gspca_dev *gspca_dev)
1002{
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001003 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001004 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1005 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1006 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1007 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001008 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001009 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1010 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-François Moine98388242010-06-04 07:30:21 -03001011 static const u8 noise03[] = /* (some differences / ms-drv) */
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001012 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1013 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1014 0xc2, 0x80, 0xc3, 0x10};
1015
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001016 PDEBUG(D_STREAM, "[Sensor requires polling]");
1017 reg_w_buf(gspca_dev, poll1, sizeof poll1);
1018 reg_w_buf(gspca_dev, poll2, sizeof poll2);
Jean-François Moine98388242010-06-04 07:30:21 -03001019 reg_w_buf(gspca_dev, noise03, sizeof noise03);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001020}
1021
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001022static int sd_start(struct gspca_dev *gspca_dev)
1023{
1024 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001025 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001026 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001027 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1028 static const u8 t3[] =
1029 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001030
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001031 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001032 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001033 case 0: /* 640x480 (0x00) */
1034 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001035 case 1: /* 352x288 */
1036 t2[1] = 0x40;
1037 break;
1038 case 2: /* 320x240 */
1039 t2[1] = 0x10;
1040 break;
1041 case 3: /* 176x144 */
1042 t2[1] = 0x50;
1043 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001044 default:
1045/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001046 t2[1] = 0x20;
1047 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001048 }
1049
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001050 switch (sd->sensor) {
1051 case SENSOR_OM6802:
1052 om6802_sensor_init(gspca_dev);
1053 break;
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001054 case SENSOR_TAS5130A:
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001055 i = 0;
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001056 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -03001057 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001058 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001059 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1060 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001061 i++;
1062 }
1063 reg_w(gspca_dev, 0x3c80);
1064 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001065 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001066 sizeof tas5130a_sensor_init[0]);
1067 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001068 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001069 }
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001070 sensor = &sensor_data[sd->sensor];
Jean-François Moine78b98cb2010-06-05 07:01:46 -03001071 setfreq(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001072 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001073 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001074 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001075 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001076 msleep(15);
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001077 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1078 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001079
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001080 if (sd->sensor == SENSOR_OM6802)
1081 poll_sensor(gspca_dev);
1082
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001083 return 0;
1084}
1085
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001086static void sd_stopN(struct gspca_dev *gspca_dev)
1087{
1088 struct sd *sd = (struct sd *) gspca_dev;
1089
1090 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1091 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001092 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1093 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d74e2009-07-07 04:03:24 -03001094 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001095 msleep(20);
1096 reg_w(gspca_dev, 0x0309);
1097 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001098}
1099
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001100static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001101 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001102 int len) /* iso packet length */
1103{
Jean-François Moineebb78c52010-06-05 06:56:48 -03001104 int pkt_type;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001105
1106 if (data[0] == 0x5a) {
1107 /* Control Packet, after this came the header again,
1108 * but extra bytes came in the packet before this,
1109 * sometimes an EOF arrives, sometimes not... */
1110 return;
1111 }
1112 data += 2;
1113 len -= 2;
Jean-François Moineebb78c52010-06-05 06:56:48 -03001114 if (data[0] == 0xff && data[1] == 0xd8)
1115 pkt_type = FIRST_PACKET;
1116 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1117 pkt_type = LAST_PACKET;
1118 else
1119 pkt_type = INTER_PACKET;
1120 gspca_frame_add(gspca_dev, pkt_type, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001121}
1122
Jean-François Moinee9b15652010-06-05 07:07:56 -03001123static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001124{
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
Jean-François Moinee9b15652010-06-05 07:07:56 -03001127 sd->blue_gain = val;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001128 if (gspca_dev->streaming)
1129 reg_w(gspca_dev, (val << 8) + 0x88);
1130 return 0;
1131}
1132
Jean-François Moinee9b15652010-06-05 07:07:56 -03001133static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136
Jean-François Moinee9b15652010-06-05 07:07:56 -03001137 *val = sd->blue_gain;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001138 return 0;
1139}
1140
Jean-François Moinee9b15652010-06-05 07:07:56 -03001141static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
Jean-François Moinee9b15652010-06-05 07:07:56 -03001145 sd->red_gain = val;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001146 if (gspca_dev->streaming)
1147 reg_w(gspca_dev, (val << 8) + 0x87);
1148
1149 return 0;
1150}
1151
Jean-François Moinee9b15652010-06-05 07:07:56 -03001152static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001153{
1154 struct sd *sd = (struct sd *) gspca_dev;
1155
Jean-François Moinee9b15652010-06-05 07:07:56 -03001156 *val = sd->red_gain;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001157 return 0;
1158}
1159
Jean-François Moinee9b15652010-06-05 07:07:56 -03001160static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001161{
1162 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinee9b15652010-06-05 07:07:56 -03001163 u16 psg, nsg;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001164
Jean-François Moinee9b15652010-06-05 07:07:56 -03001165 psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1166 nsg = val * 3;
1167 sd->red_gain = sd->red_gain * nsg / psg;
1168 if (sd->red_gain > 0x40)
1169 sd->red_gain = 0x40;
1170 else if (sd->red_gain < 0x10)
1171 sd->red_gain = 0x10;
1172 sd->blue_gain = sd->blue_gain * nsg / psg;
1173 if (sd->blue_gain > 0x40)
1174 sd->blue_gain = 0x40;
1175 else if (sd->blue_gain < 0x10)
1176 sd->blue_gain = 0x10;
1177 sd->green_gain = sd->green_gain * nsg / psg;
1178 if (sd->green_gain > 0x40)
1179 sd->green_gain = 0x40;
1180 else if (sd->green_gain < 0x10)
1181 sd->green_gain = 0x10;
1182
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001183 if (gspca_dev->streaming)
Jean-François Moinee9b15652010-06-05 07:07:56 -03001184 setRGB(gspca_dev);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001185 return 0;
1186}
1187
Jean-François Moinee9b15652010-06-05 07:07:56 -03001188static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001189{
1190 struct sd *sd = (struct sd *) gspca_dev;
1191
Jean-François Moinee9b15652010-06-05 07:07:56 -03001192 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001193 return 0;
1194}
1195
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001196static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1197{
1198 struct sd *sd = (struct sd *) gspca_dev;
1199
1200 sd->brightness = val;
1201 if (gspca_dev->streaming)
1202 setbrightness(gspca_dev);
1203 return 0;
1204}
1205
1206static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1207{
1208 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001209
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 *val = sd->brightness;
1211 return *val;
1212}
1213
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001214static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001215{
1216 struct sd *sd = (struct sd *) gspca_dev;
1217
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001218 sd->awb = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001220 setawb(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001221 return 0;
1222}
1223
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001224static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225{
1226 struct sd *sd = (struct sd *) gspca_dev;
1227
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001228 *val = sd->awb;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229 return *val;
1230}
1231
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001232static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233{
1234 struct sd *sd = (struct sd *) gspca_dev;
1235
1236 sd->mirror = val;
1237 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001238 setmirror(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001239 return 0;
1240}
1241
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001242static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001243{
1244 struct sd *sd = (struct sd *) gspca_dev;
1245
1246 *val = sd->mirror;
1247 return *val;
1248}
1249
1250static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1251{
1252 struct sd *sd = (struct sd *) gspca_dev;
1253
1254 sd->effect = val;
1255 if (gspca_dev->streaming)
1256 seteffect(gspca_dev);
1257 return 0;
1258}
1259
1260static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1261{
1262 struct sd *sd = (struct sd *) gspca_dev;
1263
1264 *val = sd->effect;
1265 return *val;
1266}
1267
1268static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1269{
1270 struct sd *sd = (struct sd *) gspca_dev;
1271
1272 sd->contrast = val;
1273 if (gspca_dev->streaming)
1274 setcontrast(gspca_dev);
1275 return 0;
1276}
1277
1278static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1279{
1280 struct sd *sd = (struct sd *) gspca_dev;
1281
1282 *val = sd->contrast;
1283 return *val;
1284}
1285
1286static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1287{
1288 struct sd *sd = (struct sd *) gspca_dev;
1289
1290 sd->colors = val;
1291 if (gspca_dev->streaming)
1292 setcolors(gspca_dev);
1293 return 0;
1294}
1295
1296static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1297{
1298 struct sd *sd = (struct sd *) gspca_dev;
1299
1300 *val = sd->colors;
1301 return 0;
1302}
1303
1304static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1305{
1306 struct sd *sd = (struct sd *) gspca_dev;
1307
1308 sd->gamma = val;
1309 if (gspca_dev->streaming)
1310 setgamma(gspca_dev);
1311 return 0;
1312}
1313
1314static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1315{
1316 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001317
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001318 *val = sd->gamma;
1319 return 0;
1320}
1321
1322static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
1325
1326 sd->freq = val;
1327 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001328 setfreq(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001329 return 0;
1330}
1331
1332static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1333{
1334 struct sd *sd = (struct sd *) gspca_dev;
1335
1336 *val = sd->freq;
1337 return 0;
1338}
1339
1340static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343
1344 sd->sharpness = val;
1345 if (gspca_dev->streaming)
1346 setsharpness(gspca_dev);
1347 return 0;
1348}
1349
1350static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1351{
1352 struct sd *sd = (struct sd *) gspca_dev;
1353
1354 *val = sd->sharpness;
1355 return 0;
1356}
1357
1358/* Low Light set here......*/
1359static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1360{
1361 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001362
1363 sd->autogain = val;
1364 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001365 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001366 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001367 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001368 return 0;
1369}
1370
1371static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1372{
1373 struct sd *sd = (struct sd *) gspca_dev;
1374
1375 *val = sd->autogain;
1376 return 0;
1377}
1378
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001379static int sd_querymenu(struct gspca_dev *gspca_dev,
1380 struct v4l2_querymenu *menu)
1381{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001382 switch (menu->id) {
1383 case V4L2_CID_POWER_LINE_FREQUENCY:
1384 switch (menu->index) {
1385 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001386 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001387 return 0;
1388 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001389 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001390 return 0;
1391 }
1392 break;
1393 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001394 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1395 strncpy((char *) menu->name,
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001396 effects_control[menu->index],
1397 sizeof menu->name);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001398 return 0;
1399 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001400 break;
1401 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001402 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001403}
1404
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001405/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001406static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001411 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001412 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001413 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001414 .pkt_scan = sd_pkt_scan,
1415 .querymenu = sd_querymenu,
1416};
1417
1418/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001419static const struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001420 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001421 {}
1422};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001423MODULE_DEVICE_TABLE(usb, device_table);
1424
1425/* -- device connect -- */
1426static int sd_probe(struct usb_interface *intf,
1427 const struct usb_device_id *id)
1428{
1429 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1430 THIS_MODULE);
1431}
1432
1433static struct usb_driver sd_driver = {
1434 .name = MODULE_NAME,
1435 .id_table = device_table,
1436 .probe = sd_probe,
1437 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001438#ifdef CONFIG_PM
1439 .suspend = gspca_suspend,
1440 .resume = gspca_resume,
1441#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001442};
1443
1444/* -- module insert / remove -- */
1445static int __init sd_mod_init(void)
1446{
Jean-François Moine54826432010-09-13 04:53:03 -03001447 return usb_register(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001448}
1449static void __exit sd_mod_exit(void)
1450{
1451 usb_deregister(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001452}
1453
1454module_init(sd_mod_init);
1455module_exit(sd_mod_exit);