blob: b84c66b7fdccd8d8b8519a8ed5dfd89eb627c4b9 [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];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300322 const u8 data5[6];
323 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300324};
325
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300326static const u8 n4_om6802[] = {
327 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
328 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
329 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
330 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
331 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
332 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
333 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
334 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
335 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
336};
337static const u8 n4_other[] = {
338 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
339 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
340 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
341 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
342 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
343 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
344 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
345 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
346};
347static const u8 n4_tas5130a[] = {
348 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
349 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
350 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
351 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
352 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
353 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
354 0xc6, 0xda
355};
Nicolau Werneck00e80062010-01-30 16:00:15 -0300356static const u8 n4_lt168g[] = {
357 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
358 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
359 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
360 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
361 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
362 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
363 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
364 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
365 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
366};
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300367
Tobias Klausere23b2902009-02-09 18:06:49 -0300368static const struct additional_sensor_data sensor_data[] = {
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300369[SENSOR_OM6802] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300370 .n3 =
371 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
372 .n4 = n4_om6802,
373 .n4sz = sizeof n4_om6802,
374 .reg80 = 0x3c,
375 .reg8e = 0x33,
376 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300377 .data1 =
378 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
379 0xb3, 0xfc},
380 .data2 =
381 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
382 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300383 .data3 =
384 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
385 0xff},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300386 .data5 = /* this could be removed later */
387 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
388 .stream =
389 {0x0b, 0x04, 0x0a, 0x78},
390 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300391[SENSOR_OTHER] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300392 .n3 =
393 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
394 .n4 = n4_other,
395 .n4sz = sizeof n4_other,
396 .reg80 = 0xac,
397 .reg8e = 0xb8,
398 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300399 .data1 =
400 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
401 0xe8, 0xfc},
402 .data2 =
403 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
404 0xd9},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300405 .data3 =
406 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
407 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300408 .data5 =
409 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
410 .stream =
411 {0x0b, 0x04, 0x0a, 0x00},
412 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300413[SENSOR_TAS5130A] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300414 .n3 =
415 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
416 .n4 = n4_tas5130a,
417 .n4sz = sizeof n4_tas5130a,
418 .reg80 = 0x3c,
419 .reg8e = 0xb4,
420 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300421 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300422 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
423 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300424 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300425 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
426 0xe0},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300427 .data3 =
428 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
429 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300430 .data5 =
431 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
432 .stream =
433 {0x0b, 0x04, 0x0a, 0x40},
434 },
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300435[SENSOR_LT168G] = {
Nicolau Werneck00e80062010-01-30 16:00:15 -0300436 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
437 .n4 = n4_lt168g,
438 .n4sz = sizeof n4_lt168g,
439 .reg80 = 0x7c,
440 .reg8e = 0xb3,
441 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
442 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
443 0xb0, 0xf4},
444 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
445 0xff},
446 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
447 0xff},
Nicolau Werneck00e80062010-01-30 16:00:15 -0300448 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
449 .stream = {0x0b, 0x04, 0x0a, 0x28},
450 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300451};
452
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453#define MAX_EFFECTS 7
454/* easily done by soft, this table could be removed,
455 * i keep it here just in case */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300456static char *effects_control[MAX_EFFECTS] = {
457 "Normal",
458 "Emboss", /* disabled */
459 "Monochrome",
460 "Sepia",
461 "Sketch",
462 "Sun Effect", /* disabled */
463 "Negative",
464};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300465static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
467 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
468 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
470 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
471 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
473};
474
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300475static const u8 gamma_table[GAMMA_MAX][17] = {
476 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
477 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
478 0xff},
479 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
480 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
481 0xff},
482 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
483 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
484 0xff},
485 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
486 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
487 0xff},
488 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
489 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
490 0xff},
491 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
492 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
493 0xff},
494 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
495 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
496 0xff},
497 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
498 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
499 0xff},
500 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
501 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
502 0xff},
503 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
504 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
505 0xff},
506 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
507 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
508 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300509 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300510 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
511 0xff},
512 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
513 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
514 0xff},
515 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
516 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
517 0xff},
518 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
519 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
520 0xff},
521 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
522 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
523 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524};
525
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300526static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300527 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
528 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
529 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530};
531
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300532static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300533
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300535static u8 reg_r(struct gspca_dev *gspca_dev,
536 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 usb_control_msg(gspca_dev->dev,
539 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540 0, /* request */
541 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
542 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543 index,
544 gspca_dev->usb_buf, 1, 500);
545 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546}
547
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300548static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300549 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300555 0, index,
556 NULL, 0, 500);
557}
558
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300559static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300560 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300561{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300562 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300563 memcpy(gspca_dev->usb_buf, buffer, len);
564 usb_control_msg(gspca_dev->dev,
565 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300566 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300567 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300568 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300569 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300570 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300571 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300572
573 tmpbuf = kmalloc(len, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300574 if (!tmpbuf) {
575 err("Out of memory");
576 return;
577 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300578 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300581 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300583 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300584 tmpbuf, len, 500);
585 kfree(tmpbuf);
586 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587}
588
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300589/* write values to consecutive registers */
590static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
591 u8 reg,
592 const u8 *buffer, u16 len)
593{
594 int i;
595 u8 *p, *tmpbuf;
596
Jean-François Moine24f222e2010-03-07 05:58:55 -0300597 if (len * 2 <= USB_BUF_SZ) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300598 p = tmpbuf = gspca_dev->usb_buf;
Jean-François Moine24f222e2010-03-07 05:58:55 -0300599 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300600 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300601 if (!tmpbuf) {
602 err("Out of memory");
603 return;
604 }
605 }
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300606 i = len;
607 while (--i >= 0) {
608 *p++ = reg++;
609 *p++ = *buffer++;
610 }
611 usb_control_msg(gspca_dev->dev,
612 usb_sndctrlpipe(gspca_dev->dev, 0),
613 0,
614 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
615 0x01, 0,
616 tmpbuf, len * 2, 500);
617 if (len * 2 > USB_BUF_SZ)
618 kfree(tmpbuf);
619}
620
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300621static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300622{
623 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300624 const u8 *p;
625 u8 byte;
626 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
627 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300628 0xdf, 0x6d,
629 0xdd, 0x18,
630 0x5a, 0xe0,
631 0x5c, 0x07,
632 0x5d, 0xb0,
633 0x5e, 0x1e,
634 0x60, 0x71,
635 0xef, 0x00,
636 0xe9, 0x00,
637 0xea, 0x00,
638 0x90, 0x24,
639 0x91, 0xb2,
640 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300641 0xfd, 0x41,
642 0x00 /* table end */
643 };
644
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300645 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300646 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300647 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300648 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300649 byte = reg_r(gspca_dev, 0x0060);
650 if (!(byte & 0x01))
651 break;
652 msleep(100);
653 }
654 byte = reg_r(gspca_dev, 0x0063);
655 if (byte != 0x17) {
656 err("Bad sensor reset %02x", byte);
657 /* continue? */
658 }
659
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300660 p = sensor_init;
661 while (*p != 0) {
662 val[1] = *p++;
663 val[3] = *p++;
664 if (*p == 0)
665 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300666 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300667 i = 4;
668 while (--i >= 0) {
669 msleep(15);
670 byte = reg_r(gspca_dev, 0x60);
671 if (!(byte & 0x01))
672 break;
673 }
674 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300675 msleep(15);
676 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300677}
678
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679/* this function is called at probe time */
680static int sd_config(struct gspca_dev *gspca_dev,
681 const struct usb_device_id *id)
682{
683 struct sd *sd = (struct sd *) gspca_dev;
684 struct cam *cam;
685
686 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687
688 cam->cam_mode = vga_mode_t16;
689 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
690
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300691 sd->brightness = BRIGHTNESS_DEF;
692 sd->contrast = CONTRAST_DEF;
693 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300694 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300695 sd->autogain = AUTOGAIN_DEF;
696 sd->mirror = MIRROR_DEF;
697 sd->freq = FREQ_DEF;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300698 sd->awb = AWB_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300699 sd->sharpness = SHARPNESS_DEF;
700 sd->effect = EFFECTS_DEF;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300701 sd->red_balance = RED_BALANCE_DEF;
702 sd->blue_balance = BLUE_BALANCE_DEF;
703 sd->global_gain = global_gain_DEF;
704
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300705 return 0;
706}
707
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300708static void setbrightness(struct gspca_dev *gspca_dev)
709{
710 struct sd *sd = (struct sd *) gspca_dev;
711 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300712 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300713
714 brightness = sd->brightness;
715 if (brightness < 7) {
716 set6[1] = 0x26;
717 set6[3] = 0x70 - brightness * 0x10;
718 } else {
719 set6[3] = 0x00 + ((brightness - 7) * 0x10);
720 }
721
722 reg_w_buf(gspca_dev, set6, sizeof set6);
723}
724
725static void setcontrast(struct gspca_dev *gspca_dev)
726{
727 struct sd *sd = (struct sd *) gspca_dev;
728 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300729 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300730
731 if (contrast < 7)
732 reg_to_write = 0x8ea9 - contrast * 0x200;
733 else
734 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
735
736 reg_w(gspca_dev, reg_to_write);
737}
738
739static void setcolors(struct gspca_dev *gspca_dev)
740{
741 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300742 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300743
744 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
745 reg_w(gspca_dev, reg_to_write);
746}
747
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300748static void setgamma(struct gspca_dev *gspca_dev)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300753 reg_w_ixbuf(gspca_dev, 0x90,
754 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300755}
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300756static void setglobalgain(struct gspca_dev *gspca_dev)
757{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300758
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300759 struct sd *sd = (struct sd *) gspca_dev;
760 reg_w(gspca_dev, (sd->red_balance << 8) + 0x87);
761 reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88);
762 reg_w(gspca_dev, (sd->global_gain << 8) + 0x89);
763}
764
765/* Generic fnc for r/b balance, exposure and whitebalance */
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300766static void setawb(struct gspca_dev *gspca_dev)
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300767{
768 struct sd *sd = (struct sd *) gspca_dev;
769
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300770 /* on awb leave defaults values */
771 if (sd->awb) {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300772 reg_w(gspca_dev, 0x3c80);
773 } else {
774 reg_w(gspca_dev, 0x3880);
775 /* shoud we wait here.. */
776 /* update and reset 'global gain' with webcam parameters */
777 sd->red_balance = reg_r(gspca_dev, 0x0087);
778 sd->blue_balance = reg_r(gspca_dev, 0x0088);
779 sd->global_gain = reg_r(gspca_dev, 0x0089);
780 setglobalgain(gspca_dev);
781 }
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300782
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300783}
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300784
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300785static void setsharpness(struct gspca_dev *gspca_dev)
786{
787 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300788 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300789
790 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
791
792 reg_w(gspca_dev, reg_to_write);
793}
794
Jean-François Moine78b98cb2010-06-05 07:01:46 -0300795static void setfreq(struct gspca_dev *gspca_dev)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798 u8 reg66;
799 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
800
801 switch (sd->sensor) {
802 case SENSOR_LT168G:
803 if (sd->freq != 0)
804 freq[3] = 0xa8;
805 reg66 = 0x41;
806 break;
807 case SENSOR_OM6802:
808 reg66 = 0xca;
809 break;
810 default:
811 reg66 = 0x40;
812 break;
813 }
814 switch (sd->freq) {
815 case 0: /* no flicker */
816 freq[3] = 0xf0;
817 break;
818 case 2: /* 60Hz */
819 reg66 &= ~0x40;
820 break;
821 }
822 freq[1] = reg66;
823
824 reg_w_buf(gspca_dev, freq, sizeof freq);
825}
826
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300827/* this function is called at probe and resume time */
828static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830 /* some of this registers are not really neded, because
831 * they are overriden by setbrigthness, setcontrast, etc,
832 * but wont hurt anyway, and can help someone with similar webcam
833 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300834 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300835 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300836 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300837 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300838 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300840 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300841 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300842 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
843 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300845 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300848 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
849 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300850 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300851 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300852 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300853 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300854 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300855 case 0x0802:
856 PDEBUG(D_PROBE, "sensor lt168g");
857 sd->sensor = SENSOR_LT168G;
858 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300859 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300860 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300861 sd->sensor = SENSOR_OTHER;
862 break;
863 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300864 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300865 sd->sensor = SENSOR_OM6802;
866 break;
867 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300868 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300869 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300870 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300871
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300872 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300873 reg_w_buf(gspca_dev, n1, sizeof n1);
874 i = 5;
875 while (--i >= 0) {
876 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
877 test_byte = reg_r(gspca_dev, 0x0063);
878 msleep(100);
879 if (test_byte == 0x17)
880 break; /* OK */
881 }
882 if (i < 0) {
883 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300884 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300885 }
886 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300887 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300888
889 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300891 test_byte = reg_r(gspca_dev, read_indexs[i]);
892 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 test_byte);
894 i++;
895 }
896
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300897 sensor = &sensor_data[sd->sensor];
898 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
899 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300900
Nicolau Werneck00e80062010-01-30 16:00:15 -0300901 if (sd->sensor == SENSOR_LT168G) {
902 test_byte = reg_r(gspca_dev, 0x80);
903 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
904 test_byte);
905 reg_w(gspca_dev, 0x6c80);
906 }
907
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300908 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
909 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
910 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300911
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300912 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
913 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
914 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300915
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300916 setbrightness(gspca_dev);
917 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300918 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300919 setcolors(gspca_dev);
920 setsharpness(gspca_dev);
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300921 setawb(gspca_dev);
Jean-François Moine78b98cb2010-06-05 07:01:46 -0300922 setfreq(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300924 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300925 reg_w(gspca_dev, 0x2088);
926 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300928 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
929 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
930 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
931 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300932
Nicolau Werneck00e80062010-01-30 16:00:15 -0300933 if (sd->sensor == SENSOR_LT168G) {
934 test_byte = reg_r(gspca_dev, 0x80);
935 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
936 test_byte);
937 reg_w(gspca_dev, 0x6c80);
938 }
939
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300940 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
941 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
942 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300943
944 return 0;
945}
946
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300947static void setmirror(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948{
949 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300950 u8 hflipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300951 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300953 if (sd->mirror)
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300954 hflipcmd[3] = 0x01;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955
Jean-François Moinecd8955b2010-06-04 07:22:57 -0300956 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957}
958
959static void seteffect(struct gspca_dev *gspca_dev)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300963 reg_w_buf(gspca_dev, effects_table[sd->effect],
964 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965 if (sd->effect == 1 || sd->effect == 5) {
966 PDEBUG(D_CONF,
967 "This effect have been disabled for webcam \"safety\"");
968 return;
969 }
970
971 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300972 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300974 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975}
976
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300977/* Is this really needed?
978 * i added some module parameters for test with some users */
979static void poll_sensor(struct gspca_dev *gspca_dev)
980{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300981 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300982 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
983 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
984 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
985 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300986 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300987 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
988 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300989 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300990 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300991 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300992 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
993 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
994 0xc2, 0x80, 0xc3, 0x10};
995
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300996 PDEBUG(D_STREAM, "[Sensor requires polling]");
997 reg_w_buf(gspca_dev, poll1, sizeof poll1);
998 reg_w_buf(gspca_dev, poll2, sizeof poll2);
999 reg_w_buf(gspca_dev, poll3, sizeof poll3);
1000 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001001}
1002
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001003static int sd_start(struct gspca_dev *gspca_dev)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001006 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001007 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001008 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1009 static const u8 t3[] =
1010 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001011
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001012 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001013 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001014 case 0: /* 640x480 (0x00) */
1015 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001016 case 1: /* 352x288 */
1017 t2[1] = 0x40;
1018 break;
1019 case 2: /* 320x240 */
1020 t2[1] = 0x10;
1021 break;
1022 case 3: /* 176x144 */
1023 t2[1] = 0x50;
1024 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001025 default:
1026/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001027 t2[1] = 0x20;
1028 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001029 }
1030
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001031 switch (sd->sensor) {
1032 case SENSOR_OM6802:
1033 om6802_sensor_init(gspca_dev);
1034 break;
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001035 case SENSOR_TAS5130A:
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001036 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001037 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -03001038 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001039 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001040 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1041 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001042 i++;
1043 }
1044 reg_w(gspca_dev, 0x3c80);
1045 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001046 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001047 sizeof tas5130a_sensor_init[0]);
1048 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001049 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001050 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001051 sensor = &sensor_data[sd->sensor];
Jean-François Moine78b98cb2010-06-05 07:01:46 -03001052 setfreq(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001053 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001054 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001055 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001056 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001057 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001058 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1059 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001060
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001061 if (sd->sensor == SENSOR_OM6802)
1062 poll_sensor(gspca_dev);
1063
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001064 return 0;
1065}
1066
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001067static void sd_stopN(struct gspca_dev *gspca_dev)
1068{
1069 struct sd *sd = (struct sd *) gspca_dev;
1070
1071 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1072 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001073 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1074 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001075 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001076 msleep(20);
1077 reg_w(gspca_dev, 0x0309);
1078 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001079}
1080
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001081static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001082 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001083 int len) /* iso packet length */
1084{
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001085 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001086
1087 if (data[0] == 0x5a) {
1088 /* Control Packet, after this came the header again,
1089 * but extra bytes came in the packet before this,
1090 * sometimes an EOF arrives, sometimes not... */
1091 return;
1092 }
1093 data += 2;
1094 len -= 2;
1095 if (data[0] == 0xff && data[1] == 0xd8) {
1096 /* extra bytes....., could be processed too but would be
1097 * a waste of time, right now leave the application and
1098 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001099 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001100 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001101 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001102 return;
1103 }
1104
1105 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1106 /* Just in case, i have seen packets with the marker,
1107 * other's do not include it... */
1108 len -= 2;
1109 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001110 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001111}
1112
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001113
1114static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1115{
1116 struct sd *sd = (struct sd *) gspca_dev;
1117
1118 sd->blue_balance = val;
1119 if (gspca_dev->streaming)
1120 reg_w(gspca_dev, (val << 8) + 0x88);
1121 return 0;
1122}
1123
1124static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1125{
1126 struct sd *sd = (struct sd *) gspca_dev;
1127
1128 *val = sd->blue_balance;
1129 return 0;
1130}
1131
1132static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1133{
1134 struct sd *sd = (struct sd *) gspca_dev;
1135
1136 sd->red_balance = val;
1137 if (gspca_dev->streaming)
1138 reg_w(gspca_dev, (val << 8) + 0x87);
1139
1140 return 0;
1141}
1142
1143static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1144{
1145 struct sd *sd = (struct sd *) gspca_dev;
1146
1147 *val = sd->red_balance;
1148 return 0;
1149}
1150
1151
1152
1153static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1154{
1155 struct sd *sd = (struct sd *) gspca_dev;
1156
1157 sd->global_gain = val;
1158 if (gspca_dev->streaming)
1159 setglobalgain(gspca_dev);
1160
1161 return 0;
1162}
1163
1164static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1165{
1166 struct sd *sd = (struct sd *) gspca_dev;
1167
1168 *val = sd->global_gain;
1169 return 0;
1170}
1171
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001172static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1173{
1174 struct sd *sd = (struct sd *) gspca_dev;
1175
1176 sd->brightness = val;
1177 if (gspca_dev->streaming)
1178 setbrightness(gspca_dev);
1179 return 0;
1180}
1181
1182static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1183{
1184 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001185
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186 *val = sd->brightness;
1187 return *val;
1188}
1189
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001190static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191{
1192 struct sd *sd = (struct sd *) gspca_dev;
1193
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001194 sd->awb = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001196 setawb(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001197 return 0;
1198}
1199
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001200static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201{
1202 struct sd *sd = (struct sd *) gspca_dev;
1203
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001204 *val = sd->awb;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 return *val;
1206}
1207
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001208static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001209{
1210 struct sd *sd = (struct sd *) gspca_dev;
1211
1212 sd->mirror = val;
1213 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001214 setmirror(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001215 return 0;
1216}
1217
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001218static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219{
1220 struct sd *sd = (struct sd *) gspca_dev;
1221
1222 *val = sd->mirror;
1223 return *val;
1224}
1225
1226static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1227{
1228 struct sd *sd = (struct sd *) gspca_dev;
1229
1230 sd->effect = val;
1231 if (gspca_dev->streaming)
1232 seteffect(gspca_dev);
1233 return 0;
1234}
1235
1236static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1237{
1238 struct sd *sd = (struct sd *) gspca_dev;
1239
1240 *val = sd->effect;
1241 return *val;
1242}
1243
1244static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1245{
1246 struct sd *sd = (struct sd *) gspca_dev;
1247
1248 sd->contrast = val;
1249 if (gspca_dev->streaming)
1250 setcontrast(gspca_dev);
1251 return 0;
1252}
1253
1254static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1255{
1256 struct sd *sd = (struct sd *) gspca_dev;
1257
1258 *val = sd->contrast;
1259 return *val;
1260}
1261
1262static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1263{
1264 struct sd *sd = (struct sd *) gspca_dev;
1265
1266 sd->colors = val;
1267 if (gspca_dev->streaming)
1268 setcolors(gspca_dev);
1269 return 0;
1270}
1271
1272static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1273{
1274 struct sd *sd = (struct sd *) gspca_dev;
1275
1276 *val = sd->colors;
1277 return 0;
1278}
1279
1280static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1281{
1282 struct sd *sd = (struct sd *) gspca_dev;
1283
1284 sd->gamma = val;
1285 if (gspca_dev->streaming)
1286 setgamma(gspca_dev);
1287 return 0;
1288}
1289
1290static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1291{
1292 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001293
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001294 *val = sd->gamma;
1295 return 0;
1296}
1297
1298static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1299{
1300 struct sd *sd = (struct sd *) gspca_dev;
1301
1302 sd->freq = val;
1303 if (gspca_dev->streaming)
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001304 setfreq(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001305 return 0;
1306}
1307
1308static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1309{
1310 struct sd *sd = (struct sd *) gspca_dev;
1311
1312 *val = sd->freq;
1313 return 0;
1314}
1315
1316static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1317{
1318 struct sd *sd = (struct sd *) gspca_dev;
1319
1320 sd->sharpness = val;
1321 if (gspca_dev->streaming)
1322 setsharpness(gspca_dev);
1323 return 0;
1324}
1325
1326static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1327{
1328 struct sd *sd = (struct sd *) gspca_dev;
1329
1330 *val = sd->sharpness;
1331 return 0;
1332}
1333
1334/* Low Light set here......*/
1335static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1336{
1337 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001338
1339 sd->autogain = val;
1340 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001341 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001342 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001343 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 return 0;
1345}
1346
1347static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1348{
1349 struct sd *sd = (struct sd *) gspca_dev;
1350
1351 *val = sd->autogain;
1352 return 0;
1353}
1354
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001355static int sd_querymenu(struct gspca_dev *gspca_dev,
1356 struct v4l2_querymenu *menu)
1357{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001358 switch (menu->id) {
1359 case V4L2_CID_POWER_LINE_FREQUENCY:
1360 switch (menu->index) {
1361 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001362 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001363 return 0;
1364 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001365 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001366 return 0;
1367 }
1368 break;
1369 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001370 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1371 strncpy((char *) menu->name,
Jean-François Moinecd8955b2010-06-04 07:22:57 -03001372 effects_control[menu->index],
1373 sizeof menu->name);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001374 return 0;
1375 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001376 break;
1377 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001378 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001379}
1380
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001381/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001382static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001383 .name = MODULE_NAME,
1384 .ctrls = sd_ctrls,
1385 .nctrls = ARRAY_SIZE(sd_ctrls),
1386 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001387 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001388 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001389 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001390 .pkt_scan = sd_pkt_scan,
1391 .querymenu = sd_querymenu,
1392};
1393
1394/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001395static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001396 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001397 {}
1398};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001399MODULE_DEVICE_TABLE(usb, device_table);
1400
1401/* -- device connect -- */
1402static int sd_probe(struct usb_interface *intf,
1403 const struct usb_device_id *id)
1404{
1405 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1406 THIS_MODULE);
1407}
1408
1409static struct usb_driver sd_driver = {
1410 .name = MODULE_NAME,
1411 .id_table = device_table,
1412 .probe = sd_probe,
1413 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001414#ifdef CONFIG_PM
1415 .suspend = gspca_suspend,
1416 .resume = gspca_resume,
1417#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001418};
1419
1420/* -- module insert / remove -- */
1421static int __init sd_mod_init(void)
1422{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001423 int ret;
1424 ret = usb_register(&sd_driver);
1425 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001426 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001427 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001428 return 0;
1429}
1430static void __exit sd_mod_exit(void)
1431{
1432 usb_deregister(&sd_driver);
1433 PDEBUG(D_PROBE, "deregistered");
1434}
1435
1436module_init(sd_mod_init);
1437module_exit(sd_mod_exit);