blob: abb2b605d578401a71d50b6b7f118615da556156 [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-Francois Moine6a7eba22008-06-30 15:50:11 -030031#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030033#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030034
35MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
36MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
37MODULE_LICENSE("GPL");
38
39struct sd {
40 struct gspca_dev gspca_dev; /* !! must be the first item */
41
Jean-Francois Moine82e25492009-01-22 07:18:48 -030042 u8 brightness;
43 u8 contrast;
44 u8 colors;
45 u8 autogain;
46 u8 gamma;
47 u8 sharpness;
48 u8 freq;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030049 u8 red_balance; /* split balance */
50 u8 blue_balance;
51 u8 global_gain; /* aka gain */
Jean-François Moinecd8955b2010-06-04 07:22:57 -030052 u8 awb; /* set default r/g/b and activate */
Jean-Francois Moine82e25492009-01-22 07:18:48 -030053 u8 mirror;
54 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030055
Jean-Francois Moine82e25492009-01-22 07:18:48 -030056 u8 sensor;
Jean-François Moinecd8955b2010-06-04 07:22:57 -030057enum {
58 SENSOR_OM6802,
59 SENSOR_OTHER,
60 SENSOR_TAS5130A,
61 SENSOR_LT168G, /* must verify if this is the actual model */
62} sensors;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
79static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030080
Jean-François Moinecd8955b2010-06-04 07:22:57 -030081static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030083static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val);
89
Jean-François Moinecd8955b2010-06-04 07:22:57 -030090static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030092static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_querymenu(struct gspca_dev *gspca_dev,
95 struct v4l2_querymenu *menu);
96
Marton Nemeth7e64dc42009-12-30 09:12:41 -030097static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 {
99 {
100 .id = V4L2_CID_BRIGHTNESS,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Brightness",
103 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300104 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300106#define BRIGHTNESS_DEF 8
107 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108 },
109 .set = sd_setbrightness,
110 .get = sd_getbrightness,
111 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300112 {
113 {
114 .id = V4L2_CID_CONTRAST,
115 .type = V4L2_CTRL_TYPE_INTEGER,
116 .name = "Contrast",
117 .minimum = 0,
118 .maximum = 0x0d,
119 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300120#define CONTRAST_DEF 0x07
121 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300122 },
123 .set = sd_setcontrast,
124 .get = sd_getcontrast,
125 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126 {
127 {
128 .id = V4L2_CID_SATURATION,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Color",
131 .minimum = 0,
132 .maximum = 0x0f,
133 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300134#define COLORS_DEF 0x05
135 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300136 },
137 .set = sd_setcolors,
138 .get = sd_getcolors,
139 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300140#define GAMMA_MAX 16
141#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300142 {
143 {
144 .id = V4L2_CID_GAMMA, /* (gamma on win) */
145 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300146 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300148 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300149 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300150 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151 },
152 .set = sd_setgamma,
153 .get = sd_getgamma,
154 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155 {
156 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300157 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158 * some apps dont bring up the
159 * backligth_compensation control) */
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Low Light",
162 .minimum = 0,
163 .maximum = 1,
164 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300165#define AUTOGAIN_DEF 0x01
166 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167 },
168 .set = sd_setlowlight,
169 .get = sd_getlowlight,
170 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171 {
172 {
173 .id = V4L2_CID_HFLIP,
174 .type = V4L2_CTRL_TYPE_BOOLEAN,
175 .name = "Mirror Image",
176 .minimum = 0,
177 .maximum = 1,
178 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300179#define MIRROR_DEF 0
180 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300182 .set = sd_setmirror,
183 .get = sd_getmirror
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300185 {
186 {
187 .id = V4L2_CID_POWER_LINE_FREQUENCY,
188 .type = V4L2_CTRL_TYPE_MENU,
189 .name = "Light Frequency Filter",
190 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
191 .maximum = 2,
192 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300193#define FREQ_DEF 1
194 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300195 },
196 .set = sd_setfreq,
197 .get = sd_getfreq},
198
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300199 {
200 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300201 .id = V4L2_CID_AUTO_WHITE_BALANCE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300202 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300203 .name = "Auto White Balance",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300207#define AWB_DEF 0
208 .default_value = AWB_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300209 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300210 .set = sd_setawb,
211 .get = sd_getawb
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300213 {
214 {
215 .id = V4L2_CID_SHARPNESS,
216 .type = V4L2_CTRL_TYPE_INTEGER,
217 .name = "Sharpness",
218 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300219 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300220 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300221#define SHARPNESS_DEF 0x06
222 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300223 },
224 .set = sd_setsharpness,
225 .get = sd_getsharpness,
226 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300227 {
228 {
229 .id = V4L2_CID_EFFECTS,
230 .type = V4L2_CTRL_TYPE_MENU,
231 .name = "Webcam Effects",
232 .minimum = 0,
233 .maximum = 4,
234 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300235#define EFFECTS_DEF 0
236 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300237 },
238 .set = sd_seteffect,
239 .get = sd_geteffect
240 },
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300241 {
242 {
243 .id = V4L2_CID_BLUE_BALANCE,
244 .type = V4L2_CTRL_TYPE_INTEGER,
245 .name = "Blue Balance",
246 .minimum = 0x10,
247 .maximum = 0x40,
248 .step = 1,
249#define BLUE_BALANCE_DEF 0x20
250 .default_value = BLUE_BALANCE_DEF,
251 },
252 .set = sd_setblue_balance,
253 .get = sd_getblue_balance,
254 },
255 {
256 {
257 .id = V4L2_CID_RED_BALANCE,
258 .type = V4L2_CTRL_TYPE_INTEGER,
259 .name = "Red Balance",
260 .minimum = 0x10,
261 .maximum = 0x40,
262 .step = 1,
263#define RED_BALANCE_DEF 0x20
264 .default_value = RED_BALANCE_DEF,
265 },
266 .set = sd_setred_balance,
267 .get = sd_getred_balance,
268 },
269 {
270 {
271 .id = V4L2_CID_GAIN,
272 .type = V4L2_CTRL_TYPE_INTEGER,
273 .name = "Gain",
274 .minimum = 0x10,
275 .maximum = 0x40,
276 .step = 1,
277#define global_gain_DEF 0x20
278 .default_value = global_gain_DEF,
279 },
280 .set = sd_setglobal_gain,
281 .get = sd_getglobal_gain,
282 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283};
284
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300285static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300286 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
287 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300288 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300289 .colorspace = V4L2_COLORSPACE_JPEG,
290 .priv = 4},
291 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
292 .bytesperline = 176,
293 .sizeimage = 176 * 144 * 3 / 8 + 590,
294 .colorspace = V4L2_COLORSPACE_JPEG,
295 .priv = 3},
296 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
297 .bytesperline = 320,
298 .sizeimage = 320 * 240 * 3 / 8 + 590,
299 .colorspace = V4L2_COLORSPACE_JPEG,
300 .priv = 2},
301 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
302 .bytesperline = 352,
303 .sizeimage = 352 * 288 * 3 / 8 + 590,
304 .colorspace = V4L2_COLORSPACE_JPEG,
305 .priv = 1},
306 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
307 .bytesperline = 640,
308 .sizeimage = 640 * 480 * 3 / 8 + 590,
309 .colorspace = V4L2_COLORSPACE_JPEG,
310 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300311};
312
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300313/* sensor specific data */
314struct additional_sensor_data {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300315 const u8 n3[6];
316 const u8 *n4, n4sz;
317 const u8 reg80, reg8e;
318 const u8 nset8[6];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300319 const u8 data1[10];
320 const u8 data2[9];
321 const u8 data3[9];
322 const u8 data4[4];
323 const u8 data5[6];
324 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300325};
326
Jean-Francois Moine78a6d742009-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 Moine78a6d742009-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 Moine78a6d742009-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 Moine78a6d742009-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 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
388 {0x66, 0xca, 0xa8, 0xf0},
389 .data5 = /* this could be removed later */
390 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
391 .stream =
392 {0x0b, 0x04, 0x0a, 0x78},
393 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300394[SENSOR_OTHER] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300395 .n3 =
396 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
397 .n4 = n4_other,
398 .n4sz = sizeof n4_other,
399 .reg80 = 0xac,
400 .reg8e = 0xb8,
401 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300402 .data1 =
403 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
404 0xe8, 0xfc},
405 .data2 =
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
407 0xd9},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300408 .data3 =
409 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
410 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300411 .data4 =
412 {0x66, 0x00, 0xa8, 0xa8},
413 .data5 =
414 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
415 .stream =
416 {0x0b, 0x04, 0x0a, 0x00},
417 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300418[SENSOR_TAS5130A] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300419 .n3 =
420 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
421 .n4 = n4_tas5130a,
422 .n4sz = sizeof n4_tas5130a,
423 .reg80 = 0x3c,
424 .reg8e = 0xb4,
425 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300426 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300427 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
428 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300429 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300430 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
431 0xe0},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300432 .data3 =
433 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
434 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300435 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
436 {0x66, 0x00, 0xa8, 0xe8},
437 .data5 =
438 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
439 .stream =
440 {0x0b, 0x04, 0x0a, 0x40},
441 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300442[SENSOR_LT168G] = {
Nicolau Werneck00e80062010-01-30 16:00:15 -0300443 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
444 .n4 = n4_lt168g,
445 .n4sz = sizeof n4_lt168g,
446 .reg80 = 0x7c,
447 .reg8e = 0xb3,
448 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
449 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
450 0xb0, 0xf4},
451 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
452 0xff},
453 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
454 0xff},
455 .data4 = {0x66, 0x41, 0xa8, 0xf0},
456 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
457 .stream = {0x0b, 0x04, 0x0a, 0x28},
458 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300459};
460
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461#define MAX_EFFECTS 7
462/* easily done by soft, this table could be removed,
463 * i keep it here just in case */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300464static char *effects_control[MAX_EFFECTS] = {
465 "Normal",
466 "Emboss", /* disabled */
467 "Monochrome",
468 "Sepia",
469 "Sketch",
470 "Sun Effect", /* disabled */
471 "Negative",
472};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300473static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300474 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
475 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
476 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
477 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
478 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
479 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
480 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
481};
482
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300483static const u8 gamma_table[GAMMA_MAX][17] = {
484 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
485 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
486 0xff},
487 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
488 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
489 0xff},
490 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
491 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
492 0xff},
493 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
494 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
495 0xff},
496 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
497 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
498 0xff},
499 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
500 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
501 0xff},
502 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
503 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
504 0xff},
505 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
506 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
507 0xff},
508 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
509 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
510 0xff},
511 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
512 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
513 0xff},
514 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
515 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
516 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300517 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300518 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
519 0xff},
520 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
521 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
522 0xff},
523 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
524 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
525 0xff},
526 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
527 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
528 0xff},
529 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
530 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
531 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532};
533
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300534static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
536 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
537 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538};
539
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300540static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300541
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300543static u8 reg_r(struct gspca_dev *gspca_dev,
544 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300546 usb_control_msg(gspca_dev->dev,
547 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 0, /* request */
549 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
550 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300551 index,
552 gspca_dev->usb_buf, 1, 500);
553 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554}
555
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300556static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300557 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300558{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300559 usb_control_msg(gspca_dev->dev,
560 usb_sndctrlpipe(gspca_dev->dev, 0),
561 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300562 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300563 0, index,
564 NULL, 0, 500);
565}
566
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300567static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300568 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300569{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300570 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300571 memcpy(gspca_dev->usb_buf, buffer, len);
572 usb_control_msg(gspca_dev->dev,
573 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300574 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300575 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300576 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300577 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300578 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300579 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300580
581 tmpbuf = kmalloc(len, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300582 if (!tmpbuf) {
583 err("Out of memory");
584 return;
585 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300586 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300587 usb_control_msg(gspca_dev->dev,
588 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300589 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300590 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300591 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300592 tmpbuf, len, 500);
593 kfree(tmpbuf);
594 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595}
596
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300597/* write values to consecutive registers */
598static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
599 u8 reg,
600 const u8 *buffer, u16 len)
601{
602 int i;
603 u8 *p, *tmpbuf;
604
Jean-François Moine24f222e2010-03-07 05:58:55 -0300605 if (len * 2 <= USB_BUF_SZ) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300606 p = tmpbuf = gspca_dev->usb_buf;
Jean-François Moine24f222e2010-03-07 05:58:55 -0300607 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300608 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300609 if (!tmpbuf) {
610 err("Out of memory");
611 return;
612 }
613 }
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300614 i = len;
615 while (--i >= 0) {
616 *p++ = reg++;
617 *p++ = *buffer++;
618 }
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
621 0,
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
623 0x01, 0,
624 tmpbuf, len * 2, 500);
625 if (len * 2 > USB_BUF_SZ)
626 kfree(tmpbuf);
627}
628
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300629static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300630{
631 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300632 const u8 *p;
633 u8 byte;
634 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
635 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300636 0xdf, 0x6d,
637 0xdd, 0x18,
638 0x5a, 0xe0,
639 0x5c, 0x07,
640 0x5d, 0xb0,
641 0x5e, 0x1e,
642 0x60, 0x71,
643 0xef, 0x00,
644 0xe9, 0x00,
645 0xea, 0x00,
646 0x90, 0x24,
647 0x91, 0xb2,
648 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300649 0xfd, 0x41,
650 0x00 /* table end */
651 };
652
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300653 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300654 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300655 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300656 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300657 byte = reg_r(gspca_dev, 0x0060);
658 if (!(byte & 0x01))
659 break;
660 msleep(100);
661 }
662 byte = reg_r(gspca_dev, 0x0063);
663 if (byte != 0x17) {
664 err("Bad sensor reset %02x", byte);
665 /* continue? */
666 }
667
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300668 p = sensor_init;
669 while (*p != 0) {
670 val[1] = *p++;
671 val[3] = *p++;
672 if (*p == 0)
673 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300674 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300675 i = 4;
676 while (--i >= 0) {
677 msleep(15);
678 byte = reg_r(gspca_dev, 0x60);
679 if (!(byte & 0x01))
680 break;
681 }
682 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300683 msleep(15);
684 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300685}
686
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687/* this function is called at probe time */
688static int sd_config(struct gspca_dev *gspca_dev,
689 const struct usb_device_id *id)
690{
691 struct sd *sd = (struct sd *) gspca_dev;
692 struct cam *cam;
693
694 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695
696 cam->cam_mode = vga_mode_t16;
697 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
698
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300699 sd->brightness = BRIGHTNESS_DEF;
700 sd->contrast = CONTRAST_DEF;
701 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300702 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300703 sd->autogain = AUTOGAIN_DEF;
704 sd->mirror = MIRROR_DEF;
705 sd->freq = FREQ_DEF;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300706 sd->awb = AWB_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300707 sd->sharpness = SHARPNESS_DEF;
708 sd->effect = EFFECTS_DEF;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300709 sd->red_balance = RED_BALANCE_DEF;
710 sd->blue_balance = BLUE_BALANCE_DEF;
711 sd->global_gain = global_gain_DEF;
712
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 return 0;
714}
715
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300716static void setbrightness(struct gspca_dev *gspca_dev)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300720 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300721
722 brightness = sd->brightness;
723 if (brightness < 7) {
724 set6[1] = 0x26;
725 set6[3] = 0x70 - brightness * 0x10;
726 } else {
727 set6[3] = 0x00 + ((brightness - 7) * 0x10);
728 }
729
730 reg_w_buf(gspca_dev, set6, sizeof set6);
731}
732
733static void setcontrast(struct gspca_dev *gspca_dev)
734{
735 struct sd *sd = (struct sd *) gspca_dev;
736 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300737 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300738
739 if (contrast < 7)
740 reg_to_write = 0x8ea9 - contrast * 0x200;
741 else
742 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
743
744 reg_w(gspca_dev, reg_to_write);
745}
746
747static void setcolors(struct gspca_dev *gspca_dev)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300750 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300751
752 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
753 reg_w(gspca_dev, reg_to_write);
754}
755
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300756static void setgamma(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759
760 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300761 reg_w_ixbuf(gspca_dev, 0x90,
762 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300763}
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300764static void setglobalgain(struct gspca_dev *gspca_dev)
765{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300766
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300767 struct sd *sd = (struct sd *) gspca_dev;
768 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
769 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
770 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
771}
772
773/* Generic fnc for r/b balance, exposure and whitebalance */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300774static void setawb(struct gspca_dev *gspca_dev)
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300778 /* on awb leave defaults values */
779 if (sd->awb) {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300780 reg_w(gspca_dev, 0x3c80);
781 } else {
782 reg_w(gspca_dev, 0x3880);
783 /* shoud we wait here.. */
784 /* update and reset 'global gain' with webcam parameters */
785 sd->red_balance = reg_r(gspca_dev, 0x0087);
786 sd->blue_balance = reg_r(gspca_dev, 0x0088);
787 sd->global_gain = reg_r(gspca_dev, 0x0089);
788 setglobalgain(gspca_dev);
789 }
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300790
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300791}
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300792
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300793static void setsharpness(struct gspca_dev *gspca_dev)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300796 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300797
798 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
799
800 reg_w(gspca_dev, reg_to_write);
801}
802
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300803/* this function is called at probe and resume time */
804static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300805{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806 /* some of this registers are not really neded, because
807 * they are overriden by setbrigthness, setcontrast, etc,
808 * but wont hurt anyway, and can help someone with similar webcam
809 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300810 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300811 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300812 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300813 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300814 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300815
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300816 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300817 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300818 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
819 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300821 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300823
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300824 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
825 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300826 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300827 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300828 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300829 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300830 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300831 case 0x0802:
832 PDEBUG(D_PROBE, "sensor lt168g");
833 sd->sensor = SENSOR_LT168G;
834 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300835 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300836 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300837 sd->sensor = SENSOR_OTHER;
838 break;
839 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300840 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300841 sd->sensor = SENSOR_OM6802;
842 break;
843 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300844 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300845 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300846 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300848 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300849 reg_w_buf(gspca_dev, n1, sizeof n1);
850 i = 5;
851 while (--i >= 0) {
852 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
853 test_byte = reg_r(gspca_dev, 0x0063);
854 msleep(100);
855 if (test_byte == 0x17)
856 break; /* OK */
857 }
858 if (i < 0) {
859 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300860 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300861 }
862 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300863 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300864
865 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300867 test_byte = reg_r(gspca_dev, read_indexs[i]);
868 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869 test_byte);
870 i++;
871 }
872
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300873 sensor = &sensor_data[sd->sensor];
874 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
875 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300876
Nicolau Werneck00e80062010-01-30 16:00:15 -0300877 if (sd->sensor == SENSOR_LT168G) {
878 test_byte = reg_r(gspca_dev, 0x80);
879 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
880 test_byte);
881 reg_w(gspca_dev, 0x6c80);
882 }
883
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300884 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
885 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
886 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300887
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300888 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
889 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
890 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300891
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300892 setbrightness(gspca_dev);
893 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300894 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300895 setcolors(gspca_dev);
896 setsharpness(gspca_dev);
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300897 setawb(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300899 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300900 reg_w(gspca_dev, 0x2088);
901 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300903 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
904 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
905 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
906 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300907
Nicolau Werneck00e80062010-01-30 16:00:15 -0300908 if (sd->sensor == SENSOR_LT168G) {
909 test_byte = reg_r(gspca_dev, 0x80);
910 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
911 test_byte);
912 reg_w(gspca_dev, 0x6c80);
913 }
914
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300915 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
916 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
917 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918
919 return 0;
920}
921
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300922static void setmirror(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923{
924 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300925 u8 hflipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300926 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300928 if (sd->mirror)
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300929 hflipcmd[3] = 0x01;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300931 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932}
933
934static void seteffect(struct gspca_dev *gspca_dev)
935{
936 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300938 reg_w_buf(gspca_dev, effects_table[sd->effect],
939 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 if (sd->effect == 1 || sd->effect == 5) {
941 PDEBUG(D_CONF,
942 "This effect have been disabled for webcam \"safety\"");
943 return;
944 }
945
946 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300947 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300949 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950}
951
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952static void setlightfreq(struct gspca_dev *gspca_dev)
953{
954 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300955 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956
957 if (sd->freq == 2) /* 60hz */
958 freq[1] = 0x00;
959
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300960 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961}
962
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300963/* Is this really needed?
964 * i added some module parameters for test with some users */
965static void poll_sensor(struct gspca_dev *gspca_dev)
966{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300967 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300968 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
969 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
970 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
971 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300972 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300973 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
974 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300975 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300976 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300977 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300978 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
979 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
980 0xc2, 0x80, 0xc3, 0x10};
981
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300982 PDEBUG(D_STREAM, "[Sensor requires polling]");
983 reg_w_buf(gspca_dev, poll1, sizeof poll1);
984 reg_w_buf(gspca_dev, poll2, sizeof poll2);
985 reg_w_buf(gspca_dev, poll3, sizeof poll3);
986 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300987}
988
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300989static int sd_start(struct gspca_dev *gspca_dev)
990{
991 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300992 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300993 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300994 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
995 static const u8 t3[] =
996 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300997
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300998 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300999 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001000 case 0: /* 640x480 (0x00) */
1001 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001002 case 1: /* 352x288 */
1003 t2[1] = 0x40;
1004 break;
1005 case 2: /* 320x240 */
1006 t2[1] = 0x10;
1007 break;
1008 case 3: /* 176x144 */
1009 t2[1] = 0x50;
1010 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001011 default:
1012/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001013 t2[1] = 0x20;
1014 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001015 }
1016
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001017 switch (sd->sensor) {
1018 case SENSOR_OM6802:
1019 om6802_sensor_init(gspca_dev);
1020 break;
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001021 case SENSOR_TAS5130A:
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001022 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001023 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -03001024 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001025 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001026 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1027 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001028 i++;
1029 }
1030 reg_w(gspca_dev, 0x3c80);
1031 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001032 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001033 sizeof tas5130a_sensor_init[0]);
1034 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001035 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001036 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001037 sensor = &sensor_data[sd->sensor];
1038 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001039 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001040 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001041 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001042 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001043 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001044 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1045 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001046
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001047 if (sd->sensor == SENSOR_OM6802)
1048 poll_sensor(gspca_dev);
1049
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001050 return 0;
1051}
1052
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001053static void sd_stopN(struct gspca_dev *gspca_dev)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
1056
1057 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1058 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001059 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1060 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001061 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001062 msleep(20);
1063 reg_w(gspca_dev, 0x0309);
1064 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001065}
1066
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001067static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001068 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001069 int len) /* iso packet length */
1070{
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001071 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001072
1073 if (data[0] == 0x5a) {
1074 /* Control Packet, after this came the header again,
1075 * but extra bytes came in the packet before this,
1076 * sometimes an EOF arrives, sometimes not... */
1077 return;
1078 }
1079 data += 2;
1080 len -= 2;
1081 if (data[0] == 0xff && data[1] == 0xd8) {
1082 /* extra bytes....., could be processed too but would be
1083 * a waste of time, right now leave the application and
1084 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001085 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001086 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001087 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001088 return;
1089 }
1090
1091 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1092 /* Just in case, i have seen packets with the marker,
1093 * other's do not include it... */
1094 len -= 2;
1095 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001096 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001097}
1098
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001099
1100static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 sd->blue_balance = val;
1105 if (gspca_dev->streaming)
1106 reg_w(gspca_dev, (val << 8) + 0x88);
1107 return 0;
1108}
1109
1110static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1111{
1112 struct sd *sd = (struct sd *) gspca_dev;
1113
1114 *val = sd->blue_balance;
1115 return 0;
1116}
1117
1118static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1119{
1120 struct sd *sd = (struct sd *) gspca_dev;
1121
1122 sd->red_balance = val;
1123 if (gspca_dev->streaming)
1124 reg_w(gspca_dev, (val << 8) + 0x87);
1125
1126 return 0;
1127}
1128
1129static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132
1133 *val = sd->red_balance;
1134 return 0;
1135}
1136
1137
1138
1139static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142
1143 sd->global_gain = val;
1144 if (gspca_dev->streaming)
1145 setglobalgain(gspca_dev);
1146
1147 return 0;
1148}
1149
1150static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153
1154 *val = sd->global_gain;
1155 return 0;
1156}
1157
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161
1162 sd->brightness = val;
1163 if (gspca_dev->streaming)
1164 setbrightness(gspca_dev);
1165 return 0;
1166}
1167
1168static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1169{
1170 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001171
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001172 *val = sd->brightness;
1173 return *val;
1174}
1175
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001176static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001177{
1178 struct sd *sd = (struct sd *) gspca_dev;
1179
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001180 sd->awb = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001182 setawb(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001183 return 0;
1184}
1185
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001186static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001187{
1188 struct sd *sd = (struct sd *) gspca_dev;
1189
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001190 *val = sd->awb;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 return *val;
1192}
1193
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001194static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197
1198 sd->mirror = val;
1199 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001200 setmirror(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201 return 0;
1202}
1203
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001204static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205{
1206 struct sd *sd = (struct sd *) gspca_dev;
1207
1208 *val = sd->mirror;
1209 return *val;
1210}
1211
1212static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1213{
1214 struct sd *sd = (struct sd *) gspca_dev;
1215
1216 sd->effect = val;
1217 if (gspca_dev->streaming)
1218 seteffect(gspca_dev);
1219 return 0;
1220}
1221
1222static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1223{
1224 struct sd *sd = (struct sd *) gspca_dev;
1225
1226 *val = sd->effect;
1227 return *val;
1228}
1229
1230static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1231{
1232 struct sd *sd = (struct sd *) gspca_dev;
1233
1234 sd->contrast = val;
1235 if (gspca_dev->streaming)
1236 setcontrast(gspca_dev);
1237 return 0;
1238}
1239
1240static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1241{
1242 struct sd *sd = (struct sd *) gspca_dev;
1243
1244 *val = sd->contrast;
1245 return *val;
1246}
1247
1248static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1249{
1250 struct sd *sd = (struct sd *) gspca_dev;
1251
1252 sd->colors = val;
1253 if (gspca_dev->streaming)
1254 setcolors(gspca_dev);
1255 return 0;
1256}
1257
1258static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1259{
1260 struct sd *sd = (struct sd *) gspca_dev;
1261
1262 *val = sd->colors;
1263 return 0;
1264}
1265
1266static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1267{
1268 struct sd *sd = (struct sd *) gspca_dev;
1269
1270 sd->gamma = val;
1271 if (gspca_dev->streaming)
1272 setgamma(gspca_dev);
1273 return 0;
1274}
1275
1276static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1277{
1278 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001279
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001280 *val = sd->gamma;
1281 return 0;
1282}
1283
1284static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 sd->freq = val;
1289 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001290 setfreq(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001291 return 0;
1292}
1293
1294static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297
1298 *val = sd->freq;
1299 return 0;
1300}
1301
1302static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1303{
1304 struct sd *sd = (struct sd *) gspca_dev;
1305
1306 sd->sharpness = val;
1307 if (gspca_dev->streaming)
1308 setsharpness(gspca_dev);
1309 return 0;
1310}
1311
1312static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1313{
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 *val = sd->sharpness;
1317 return 0;
1318}
1319
1320/* Low Light set here......*/
1321static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1322{
1323 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001324
1325 sd->autogain = val;
1326 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001327 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001329 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001330 return 0;
1331}
1332
1333static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1334{
1335 struct sd *sd = (struct sd *) gspca_dev;
1336
1337 *val = sd->autogain;
1338 return 0;
1339}
1340
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001341static int sd_querymenu(struct gspca_dev *gspca_dev,
1342 struct v4l2_querymenu *menu)
1343{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 switch (menu->id) {
1345 case V4L2_CID_POWER_LINE_FREQUENCY:
1346 switch (menu->index) {
1347 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001348 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001349 return 0;
1350 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001351 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001352 return 0;
1353 }
1354 break;
1355 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001356 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1357 strncpy((char *) menu->name,
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001358 effects_control[menu->index],
1359 sizeof menu->name);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001360 return 0;
1361 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001362 break;
1363 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001364 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001365}
1366
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001367/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001368static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001369 .name = MODULE_NAME,
1370 .ctrls = sd_ctrls,
1371 .nctrls = ARRAY_SIZE(sd_ctrls),
1372 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001373 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001374 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001375 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001376 .pkt_scan = sd_pkt_scan,
1377 .querymenu = sd_querymenu,
1378};
1379
1380/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001381static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001382 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001383 {}
1384};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001385MODULE_DEVICE_TABLE(usb, device_table);
1386
1387/* -- device connect -- */
1388static int sd_probe(struct usb_interface *intf,
1389 const struct usb_device_id *id)
1390{
1391 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1392 THIS_MODULE);
1393}
1394
1395static struct usb_driver sd_driver = {
1396 .name = MODULE_NAME,
1397 .id_table = device_table,
1398 .probe = sd_probe,
1399 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001400#ifdef CONFIG_PM
1401 .suspend = gspca_suspend,
1402 .resume = gspca_resume,
1403#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001404};
1405
1406/* -- module insert / remove -- */
1407static int __init sd_mod_init(void)
1408{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001409 int ret;
1410 ret = usb_register(&sd_driver);
1411 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001412 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001413 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001414 return 0;
1415}
1416static void __exit sd_mod_exit(void)
1417{
1418 usb_deregister(&sd_driver);
1419 PDEBUG(D_PROBE, "deregistered");
1420}
1421
1422module_init(sd_mod_init);
1423module_exit(sd_mod_exit);