blob: 63014372adbc513c485b821fe4b05a08a7befe7a [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030017 *
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
24 * Costantino Leandro
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030025 */
26
27#define MODULE_NAME "t613"
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030028
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030031#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
Jean-Francois Moine82e25492009-01-22 07:18:48 -030040 u8 brightness;
41 u8 contrast;
42 u8 colors;
43 u8 autogain;
44 u8 gamma;
45 u8 sharpness;
46 u8 freq;
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030047 u8 red_balance; /* split balance */
48 u8 blue_balance;
49 u8 global_gain; /* aka gain */
50 u8 whitebalance; /* set default r/g/b and activate */
Jean-Francois Moine82e25492009-01-22 07:18:48 -030051 u8 mirror;
52 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030053
Jean-Francois Moine82e25492009-01-22 07:18:48 -030054 u8 sensor;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -030055#define SENSOR_OM6802 0
56#define SENSOR_OTHER 1
57#define SENSOR_TAS5130A 2
Nicolau Werneck00e80062010-01-30 16:00:15 -030058#define SENSOR_LT168G 3 /* must verify if this is the actual model */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059};
60
61/* V4L2 controls supported by the driver */
62static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030076
77
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030078static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
79static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030080static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
81static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
82static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val);
86
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
91static int sd_querymenu(struct gspca_dev *gspca_dev,
92 struct v4l2_querymenu *menu);
93
Costantino Leandrobe1da9e2010-03-23 12:31:16 -030094
Marton Nemeth7e64dc42009-12-30 09:12:41 -030095static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030096 {
97 {
98 .id = V4L2_CID_BRIGHTNESS,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Brightness",
101 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300102 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300103 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300104#define BRIGHTNESS_DEF 8
105 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300106 },
107 .set = sd_setbrightness,
108 .get = sd_getbrightness,
109 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 {
111 {
112 .id = V4L2_CID_CONTRAST,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Contrast",
115 .minimum = 0,
116 .maximum = 0x0d,
117 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300118#define CONTRAST_DEF 0x07
119 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300120 },
121 .set = sd_setcontrast,
122 .get = sd_getcontrast,
123 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300124 {
125 {
126 .id = V4L2_CID_SATURATION,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Color",
129 .minimum = 0,
130 .maximum = 0x0f,
131 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300132#define COLORS_DEF 0x05
133 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 },
135 .set = sd_setcolors,
136 .get = sd_getcolors,
137 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300138#define GAMMA_MAX 16
139#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140 {
141 {
142 .id = V4L2_CID_GAMMA, /* (gamma on win) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300144 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300145 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300146 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300148 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300149 },
150 .set = sd_setgamma,
151 .get = sd_getgamma,
152 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300153 {
154 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300155 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156 * some apps dont bring up the
157 * backligth_compensation control) */
158 .type = V4L2_CTRL_TYPE_INTEGER,
159 .name = "Low Light",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300163#define AUTOGAIN_DEF 0x01
164 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 },
166 .set = sd_setlowlight,
167 .get = sd_getlowlight,
168 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169 {
170 {
171 .id = V4L2_CID_HFLIP,
172 .type = V4L2_CTRL_TYPE_BOOLEAN,
173 .name = "Mirror Image",
174 .minimum = 0,
175 .maximum = 1,
176 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300177#define MIRROR_DEF 0
178 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179 },
180 .set = sd_setflip,
181 .get = sd_getflip
182 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183 {
184 {
185 .id = V4L2_CID_POWER_LINE_FREQUENCY,
186 .type = V4L2_CTRL_TYPE_MENU,
187 .name = "Light Frequency Filter",
188 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
189 .maximum = 2,
190 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300191#define FREQ_DEF 1
192 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300193 },
194 .set = sd_setfreq,
195 .get = sd_getfreq},
196
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300197 {
198 {
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300199 .id = V4L2_CID_AUTO_WHITE_BALANCE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "White Balance",
202 .minimum = 0,
203 .maximum = 1,
204 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300205#define WHITE_BALANCE_DEF 0
206 .default_value = WHITE_BALANCE_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207 },
208 .set = sd_setwhitebalance,
209 .get = sd_getwhitebalance
210 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300211 {
212 {
213 .id = V4L2_CID_SHARPNESS,
214 .type = V4L2_CTRL_TYPE_INTEGER,
215 .name = "Sharpness",
216 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300217 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300218 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300219#define SHARPNESS_DEF 0x06
220 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300221 },
222 .set = sd_setsharpness,
223 .get = sd_getsharpness,
224 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300225 {
226 {
227 .id = V4L2_CID_EFFECTS,
228 .type = V4L2_CTRL_TYPE_MENU,
229 .name = "Webcam Effects",
230 .minimum = 0,
231 .maximum = 4,
232 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300233#define EFFECTS_DEF 0
234 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235 },
236 .set = sd_seteffect,
237 .get = sd_geteffect
238 },
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300239 {
240 {
241 .id = V4L2_CID_BLUE_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Blue Balance",
244 .minimum = 0x10,
245 .maximum = 0x40,
246 .step = 1,
247#define BLUE_BALANCE_DEF 0x20
248 .default_value = BLUE_BALANCE_DEF,
249 },
250 .set = sd_setblue_balance,
251 .get = sd_getblue_balance,
252 },
253 {
254 {
255 .id = V4L2_CID_RED_BALANCE,
256 .type = V4L2_CTRL_TYPE_INTEGER,
257 .name = "Red Balance",
258 .minimum = 0x10,
259 .maximum = 0x40,
260 .step = 1,
261#define RED_BALANCE_DEF 0x20
262 .default_value = RED_BALANCE_DEF,
263 },
264 .set = sd_setred_balance,
265 .get = sd_getred_balance,
266 },
267 {
268 {
269 .id = V4L2_CID_GAIN,
270 .type = V4L2_CTRL_TYPE_INTEGER,
271 .name = "Gain",
272 .minimum = 0x10,
273 .maximum = 0x40,
274 .step = 1,
275#define global_gain_DEF 0x20
276 .default_value = global_gain_DEF,
277 },
278 .set = sd_setglobal_gain,
279 .get = sd_getglobal_gain,
280 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281};
282
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300283static char *effects_control[] = {
284 "Normal",
285 "Emboss", /* disabled */
286 "Monochrome",
287 "Sepia",
288 "Sketch",
289 "Sun Effect", /* disabled */
290 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300291};
292
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300293static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300294 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
295 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300296 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300297 .colorspace = V4L2_COLORSPACE_JPEG,
298 .priv = 4},
299 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
300 .bytesperline = 176,
301 .sizeimage = 176 * 144 * 3 / 8 + 590,
302 .colorspace = V4L2_COLORSPACE_JPEG,
303 .priv = 3},
304 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
305 .bytesperline = 320,
306 .sizeimage = 320 * 240 * 3 / 8 + 590,
307 .colorspace = V4L2_COLORSPACE_JPEG,
308 .priv = 2},
309 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
310 .bytesperline = 352,
311 .sizeimage = 352 * 288 * 3 / 8 + 590,
312 .colorspace = V4L2_COLORSPACE_JPEG,
313 .priv = 1},
314 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
315 .bytesperline = 640,
316 .sizeimage = 640 * 480 * 3 / 8 + 590,
317 .colorspace = V4L2_COLORSPACE_JPEG,
318 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300319};
320
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300321/* sensor specific data */
322struct additional_sensor_data {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300323 const u8 n3[6];
324 const u8 *n4, n4sz;
325 const u8 reg80, reg8e;
326 const u8 nset8[6];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300327 const u8 data1[10];
328 const u8 data2[9];
329 const u8 data3[9];
330 const u8 data4[4];
331 const u8 data5[6];
332 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300333};
334
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300335static const u8 n4_om6802[] = {
336 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
337 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
338 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
339 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
340 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
341 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
342 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
343 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
344 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
345};
346static const u8 n4_other[] = {
347 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
348 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
349 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
350 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
351 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
352 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
353 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
354 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
355};
356static const u8 n4_tas5130a[] = {
357 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
358 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
359 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
360 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
361 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
362 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
363 0xc6, 0xda
364};
Nicolau Werneck00e80062010-01-30 16:00:15 -0300365static const u8 n4_lt168g[] = {
366 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
367 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
368 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
369 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
370 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
371 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
372 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
373 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
374 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
375};
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300376
Tobias Klausere23b2902009-02-09 18:06:49 -0300377static const struct additional_sensor_data sensor_data[] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300378 { /* 0: OM6802 */
379 .n3 =
380 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
381 .n4 = n4_om6802,
382 .n4sz = sizeof n4_om6802,
383 .reg80 = 0x3c,
384 .reg8e = 0x33,
385 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300386 .data1 =
387 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
388 0xb3, 0xfc},
389 .data2 =
390 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
391 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300392 .data3 =
393 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
394 0xff},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300395 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
396 {0x66, 0xca, 0xa8, 0xf0},
397 .data5 = /* this could be removed later */
398 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
399 .stream =
400 {0x0b, 0x04, 0x0a, 0x78},
401 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300402 { /* 1: OTHER */
403 .n3 =
404 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
405 .n4 = n4_other,
406 .n4sz = sizeof n4_other,
407 .reg80 = 0xac,
408 .reg8e = 0xb8,
409 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300410 .data1 =
411 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
412 0xe8, 0xfc},
413 .data2 =
414 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
415 0xd9},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300416 .data3 =
417 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
418 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300419 .data4 =
420 {0x66, 0x00, 0xa8, 0xa8},
421 .data5 =
422 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
423 .stream =
424 {0x0b, 0x04, 0x0a, 0x00},
425 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300426 { /* 2: TAS5130A */
427 .n3 =
428 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
429 .n4 = n4_tas5130a,
430 .n4sz = sizeof n4_tas5130a,
431 .reg80 = 0x3c,
432 .reg8e = 0xb4,
433 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300434 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300435 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
436 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300437 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300438 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
439 0xe0},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300440 .data3 =
441 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
442 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300443 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
444 {0x66, 0x00, 0xa8, 0xe8},
445 .data5 =
446 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
447 .stream =
448 {0x0b, 0x04, 0x0a, 0x40},
449 },
Nicolau Werneck00e80062010-01-30 16:00:15 -0300450 { /* 3: LT168G */
451 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
452 .n4 = n4_lt168g,
453 .n4sz = sizeof n4_lt168g,
454 .reg80 = 0x7c,
455 .reg8e = 0xb3,
456 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
457 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
458 0xb0, 0xf4},
459 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
460 0xff},
461 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
462 0xff},
463 .data4 = {0x66, 0x41, 0xa8, 0xf0},
464 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
465 .stream = {0x0b, 0x04, 0x0a, 0x28},
466 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300467};
468
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469#define MAX_EFFECTS 7
470/* easily done by soft, this table could be removed,
471 * i keep it here just in case */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300472static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
474 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
475 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
476 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
477 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
478 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
479 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
480};
481
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300482static const u8 gamma_table[GAMMA_MAX][17] = {
483 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
484 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
485 0xff},
486 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
487 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
488 0xff},
489 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
490 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
491 0xff},
492 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
493 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
494 0xff},
495 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
496 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
497 0xff},
498 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
499 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
500 0xff},
501 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
502 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
503 0xff},
504 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
505 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
506 0xff},
507 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
508 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
509 0xff},
510 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
511 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
512 0xff},
513 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
514 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
515 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300516 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300517 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
518 0xff},
519 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
520 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
521 0xff},
522 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
523 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
524 0xff},
525 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
526 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
527 0xff},
528 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
529 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
530 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300531};
532
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300533static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300534 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
535 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
536 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537};
538
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300539static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300540
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300541/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300542static u8 reg_r(struct gspca_dev *gspca_dev,
543 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 usb_control_msg(gspca_dev->dev,
546 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547 0, /* request */
548 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
549 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 index,
551 gspca_dev->usb_buf, 1, 500);
552 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300553}
554
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300555static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300556 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300558 usb_control_msg(gspca_dev->dev,
559 usb_sndctrlpipe(gspca_dev->dev, 0),
560 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300561 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300562 0, index,
563 NULL, 0, 500);
564}
565
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300566static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300567 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300568{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300569 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300570 memcpy(gspca_dev->usb_buf, buffer, len);
571 usb_control_msg(gspca_dev->dev,
572 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300573 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300574 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300575 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300577 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300578 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300579
580 tmpbuf = kmalloc(len, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300581 if (!tmpbuf) {
582 err("Out of memory");
583 return;
584 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300585 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300586 usb_control_msg(gspca_dev->dev,
587 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300588 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300589 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300590 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300591 tmpbuf, len, 500);
592 kfree(tmpbuf);
593 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594}
595
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300596/* write values to consecutive registers */
597static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
598 u8 reg,
599 const u8 *buffer, u16 len)
600{
601 int i;
602 u8 *p, *tmpbuf;
603
Jean-François Moine24f222e2010-03-07 05:58:55 -0300604 if (len * 2 <= USB_BUF_SZ) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300605 p = tmpbuf = gspca_dev->usb_buf;
Jean-François Moine24f222e2010-03-07 05:58:55 -0300606 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300607 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
Jean-François Moine24f222e2010-03-07 05:58:55 -0300608 if (!tmpbuf) {
609 err("Out of memory");
610 return;
611 }
612 }
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300613 i = len;
614 while (--i >= 0) {
615 *p++ = reg++;
616 *p++ = *buffer++;
617 }
618 usb_control_msg(gspca_dev->dev,
619 usb_sndctrlpipe(gspca_dev->dev, 0),
620 0,
621 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
622 0x01, 0,
623 tmpbuf, len * 2, 500);
624 if (len * 2 > USB_BUF_SZ)
625 kfree(tmpbuf);
626}
627
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300628/* Reported as OM6802*/
629static 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;
706 sd->whitebalance = WHITE_BALANCE_DEF;
707 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 Moine35480b6b2008-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 Moine35480b6b2008-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 Moine35480b6b2008-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 Moine35480b6b2008-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 */
774static void setbalance(struct gspca_dev *gspca_dev)
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300778 /* on whitebalance leave defaults values */
779 if (sd->whitebalance) {
780 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 Moine35480b6b2008-10-17 05:19:46 -0300790
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300791}
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300792
Costantino Leandrobe1da9e2010-03-23 12:31:16 -0300793
794
795static void setwhitebalance(struct gspca_dev *gspca_dev)
796{
797 setbalance(gspca_dev);
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300798}
799
800static void setsharpness(struct gspca_dev *gspca_dev)
801{
802 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300803 u16 reg_to_write;
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300804
805 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
806
807 reg_w(gspca_dev, reg_to_write);
808}
809
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300810/* this function is called at probe and resume time */
811static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813 /* some of this registers are not really neded, because
814 * they are overriden by setbrigthness, setcontrast, etc,
815 * but wont hurt anyway, and can help someone with similar webcam
816 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300817 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300818 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300819 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300820 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300821 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300823 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300824 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300825 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
826 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300828 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300831 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
832 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300833 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300834 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300835 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300836 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300837 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -0300838 case 0x0802:
839 PDEBUG(D_PROBE, "sensor lt168g");
840 sd->sensor = SENSOR_LT168G;
841 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300842 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300843 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300844 sd->sensor = SENSOR_OTHER;
845 break;
846 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300847 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300848 sd->sensor = SENSOR_OM6802;
849 break;
850 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300851 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300852 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300853 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300855 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300856 reg_w_buf(gspca_dev, n1, sizeof n1);
857 i = 5;
858 while (--i >= 0) {
859 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
860 test_byte = reg_r(gspca_dev, 0x0063);
861 msleep(100);
862 if (test_byte == 0x17)
863 break; /* OK */
864 }
865 if (i < 0) {
866 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300867 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300868 }
869 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300870 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300871
872 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300874 test_byte = reg_r(gspca_dev, read_indexs[i]);
875 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876 test_byte);
877 i++;
878 }
879
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300880 sensor = &sensor_data[sd->sensor];
881 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
882 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300883
Nicolau Werneck00e80062010-01-30 16:00:15 -0300884 if (sd->sensor == SENSOR_LT168G) {
885 test_byte = reg_r(gspca_dev, 0x80);
886 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
887 test_byte);
888 reg_w(gspca_dev, 0x6c80);
889 }
890
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300891 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
892 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
893 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300894
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300895 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
896 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
897 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300898
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300899 setbrightness(gspca_dev);
900 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300901 setgamma(gspca_dev);
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300902 setcolors(gspca_dev);
903 setsharpness(gspca_dev);
904 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905
Jean-Francois Moine35480b6b2008-10-17 05:19:46 -0300906 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300907 reg_w(gspca_dev, 0x2088);
908 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300910 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
911 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
912 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
913 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300914
Nicolau Werneck00e80062010-01-30 16:00:15 -0300915 if (sd->sensor == SENSOR_LT168G) {
916 test_byte = reg_r(gspca_dev, 0x80);
917 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
918 test_byte);
919 reg_w(gspca_dev, 0x6c80);
920 }
921
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300922 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
923 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
924 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300925
926 return 0;
927}
928
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929static void setflip(struct gspca_dev *gspca_dev)
930{
931 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300932 u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300933 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300935 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 flipcmd[3] = 0x01;
937
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300938 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939}
940
941static void seteffect(struct gspca_dev *gspca_dev)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300945 reg_w_buf(gspca_dev, effects_table[sd->effect],
946 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300947 if (sd->effect == 1 || sd->effect == 5) {
948 PDEBUG(D_CONF,
949 "This effect have been disabled for webcam \"safety\"");
950 return;
951 }
952
953 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300954 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300956 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957}
958
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959static void setlightfreq(struct gspca_dev *gspca_dev)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300962 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963
964 if (sd->freq == 2) /* 60hz */
965 freq[1] = 0x00;
966
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300967 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968}
969
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300970/* Is this really needed?
971 * i added some module parameters for test with some users */
972static void poll_sensor(struct gspca_dev *gspca_dev)
973{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300974 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300975 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
976 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
977 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
978 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300979 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300980 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
981 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300982 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300983 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300984 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300985 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
986 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
987 0xc2, 0x80, 0xc3, 0x10};
988
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300989 PDEBUG(D_STREAM, "[Sensor requires polling]");
990 reg_w_buf(gspca_dev, poll1, sizeof poll1);
991 reg_w_buf(gspca_dev, poll2, sizeof poll2);
992 reg_w_buf(gspca_dev, poll3, sizeof poll3);
993 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300994}
995
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300996static int sd_start(struct gspca_dev *gspca_dev)
997{
998 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300999 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001000 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001001 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1002 static const u8 t3[] =
1003 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001004
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001005 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001006 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001007 case 0: /* 640x480 (0x00) */
1008 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001009 case 1: /* 352x288 */
1010 t2[1] = 0x40;
1011 break;
1012 case 2: /* 320x240 */
1013 t2[1] = 0x10;
1014 break;
1015 case 3: /* 176x144 */
1016 t2[1] = 0x50;
1017 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001018 default:
1019/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001020 t2[1] = 0x20;
1021 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001022 }
1023
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001024 switch (sd->sensor) {
1025 case SENSOR_OM6802:
1026 om6802_sensor_init(gspca_dev);
1027 break;
Nicolau Werneck00e80062010-01-30 16:00:15 -03001028 case SENSOR_LT168G:
1029 break;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001030 case SENSOR_OTHER:
1031 break;
1032 default:
1033/* case SENSOR_TAS5130A: */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001034 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001035 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -03001036 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001037 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001038 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1039 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001040 i++;
1041 }
1042 reg_w(gspca_dev, 0x3c80);
1043 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001044 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001045 sizeof tas5130a_sensor_init[0]);
1046 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001047 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001048 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001049 sensor = &sensor_data[sd->sensor];
1050 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001051 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001052 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001053 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001054 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001055 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001056 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1057 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -03001058
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001059 if (sd->sensor == SENSOR_OM6802)
1060 poll_sensor(gspca_dev);
1061
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001062 return 0;
1063}
1064
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001065static void sd_stopN(struct gspca_dev *gspca_dev)
1066{
1067 struct sd *sd = (struct sd *) gspca_dev;
1068
1069 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1070 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001071 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1072 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -03001073 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -03001074 msleep(20);
1075 reg_w(gspca_dev, 0x0309);
1076 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001077}
1078
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001079static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001080 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001081 int len) /* iso packet length */
1082{
Jean-Francois Moine82e25492009-01-22 07:18:48 -03001083 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001084
1085 if (data[0] == 0x5a) {
1086 /* Control Packet, after this came the header again,
1087 * but extra bytes came in the packet before this,
1088 * sometimes an EOF arrives, sometimes not... */
1089 return;
1090 }
1091 data += 2;
1092 len -= 2;
1093 if (data[0] == 0xff && data[1] == 0xd8) {
1094 /* extra bytes....., could be processed too but would be
1095 * a waste of time, right now leave the application and
1096 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001097 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001098 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001099 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001100 return;
1101 }
1102
1103 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
1104 /* Just in case, i have seen packets with the marker,
1105 * other's do not include it... */
1106 len -= 2;
1107 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001108 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001109}
1110
Costantino Leandrobe1da9e2010-03-23 12:31:16 -03001111
1112static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 sd->blue_balance = val;
1117 if (gspca_dev->streaming)
1118 reg_w(gspca_dev, (val << 8) + 0x88);
1119 return 0;
1120}
1121
1122static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1123{
1124 struct sd *sd = (struct sd *) gspca_dev;
1125
1126 *val = sd->blue_balance;
1127 return 0;
1128}
1129
1130static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1131{
1132 struct sd *sd = (struct sd *) gspca_dev;
1133
1134 sd->red_balance = val;
1135 if (gspca_dev->streaming)
1136 reg_w(gspca_dev, (val << 8) + 0x87);
1137
1138 return 0;
1139}
1140
1141static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
1145 *val = sd->red_balance;
1146 return 0;
1147}
1148
1149
1150
1151static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val)
1152{
1153 struct sd *sd = (struct sd *) gspca_dev;
1154
1155 sd->global_gain = val;
1156 if (gspca_dev->streaming)
1157 setglobalgain(gspca_dev);
1158
1159 return 0;
1160}
1161
1162static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val)
1163{
1164 struct sd *sd = (struct sd *) gspca_dev;
1165
1166 *val = sd->global_gain;
1167 return 0;
1168}
1169
1170
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001171static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1172{
1173 struct sd *sd = (struct sd *) gspca_dev;
1174
1175 sd->brightness = val;
1176 if (gspca_dev->streaming)
1177 setbrightness(gspca_dev);
1178 return 0;
1179}
1180
1181static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1182{
1183 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001184
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001185 *val = sd->brightness;
1186 return *val;
1187}
1188
1189static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
1190{
1191 struct sd *sd = (struct sd *) gspca_dev;
1192
1193 sd->whitebalance = val;
1194 if (gspca_dev->streaming)
1195 setwhitebalance(gspca_dev);
1196 return 0;
1197}
1198
1199static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1200{
1201 struct sd *sd = (struct sd *) gspca_dev;
1202
1203 *val = sd->whitebalance;
1204 return *val;
1205}
1206
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001207static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1208{
1209 struct sd *sd = (struct sd *) gspca_dev;
1210
1211 sd->mirror = val;
1212 if (gspca_dev->streaming)
1213 setflip(gspca_dev);
1214 return 0;
1215}
1216
1217static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1218{
1219 struct sd *sd = (struct sd *) gspca_dev;
1220
1221 *val = sd->mirror;
1222 return *val;
1223}
1224
1225static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1226{
1227 struct sd *sd = (struct sd *) gspca_dev;
1228
1229 sd->effect = val;
1230 if (gspca_dev->streaming)
1231 seteffect(gspca_dev);
1232 return 0;
1233}
1234
1235static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1236{
1237 struct sd *sd = (struct sd *) gspca_dev;
1238
1239 *val = sd->effect;
1240 return *val;
1241}
1242
1243static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1244{
1245 struct sd *sd = (struct sd *) gspca_dev;
1246
1247 sd->contrast = val;
1248 if (gspca_dev->streaming)
1249 setcontrast(gspca_dev);
1250 return 0;
1251}
1252
1253static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1254{
1255 struct sd *sd = (struct sd *) gspca_dev;
1256
1257 *val = sd->contrast;
1258 return *val;
1259}
1260
1261static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1262{
1263 struct sd *sd = (struct sd *) gspca_dev;
1264
1265 sd->colors = val;
1266 if (gspca_dev->streaming)
1267 setcolors(gspca_dev);
1268 return 0;
1269}
1270
1271static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1272{
1273 struct sd *sd = (struct sd *) gspca_dev;
1274
1275 *val = sd->colors;
1276 return 0;
1277}
1278
1279static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1280{
1281 struct sd *sd = (struct sd *) gspca_dev;
1282
1283 sd->gamma = val;
1284 if (gspca_dev->streaming)
1285 setgamma(gspca_dev);
1286 return 0;
1287}
1288
1289static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1290{
1291 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001292
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001293 *val = sd->gamma;
1294 return 0;
1295}
1296
1297static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1298{
1299 struct sd *sd = (struct sd *) gspca_dev;
1300
1301 sd->freq = val;
1302 if (gspca_dev->streaming)
1303 setlightfreq(gspca_dev);
1304 return 0;
1305}
1306
1307static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1308{
1309 struct sd *sd = (struct sd *) gspca_dev;
1310
1311 *val = sd->freq;
1312 return 0;
1313}
1314
1315static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1316{
1317 struct sd *sd = (struct sd *) gspca_dev;
1318
1319 sd->sharpness = val;
1320 if (gspca_dev->streaming)
1321 setsharpness(gspca_dev);
1322 return 0;
1323}
1324
1325static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1326{
1327 struct sd *sd = (struct sd *) gspca_dev;
1328
1329 *val = sd->sharpness;
1330 return 0;
1331}
1332
1333/* Low Light set here......*/
1334static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1335{
1336 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001337
1338 sd->autogain = val;
1339 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001340 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001341 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001342 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001343 return 0;
1344}
1345
1346static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1347{
1348 struct sd *sd = (struct sd *) gspca_dev;
1349
1350 *val = sd->autogain;
1351 return 0;
1352}
1353
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001354static int sd_querymenu(struct gspca_dev *gspca_dev,
1355 struct v4l2_querymenu *menu)
1356{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001357 switch (menu->id) {
1358 case V4L2_CID_POWER_LINE_FREQUENCY:
1359 switch (menu->index) {
1360 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001361 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001362 return 0;
1363 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001364 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001365 return 0;
1366 }
1367 break;
1368 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001369 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1370 strncpy((char *) menu->name,
1371 effects_control[menu->index], 32);
1372 return 0;
1373 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001374 break;
1375 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001376 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001377}
1378
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001379/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001380static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001381 .name = MODULE_NAME,
1382 .ctrls = sd_ctrls,
1383 .nctrls = ARRAY_SIZE(sd_ctrls),
1384 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001385 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001386 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001387 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001388 .pkt_scan = sd_pkt_scan,
1389 .querymenu = sd_querymenu,
1390};
1391
1392/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001393static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001394 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001395 {}
1396};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001397MODULE_DEVICE_TABLE(usb, device_table);
1398
1399/* -- device connect -- */
1400static int sd_probe(struct usb_interface *intf,
1401 const struct usb_device_id *id)
1402{
1403 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1404 THIS_MODULE);
1405}
1406
1407static struct usb_driver sd_driver = {
1408 .name = MODULE_NAME,
1409 .id_table = device_table,
1410 .probe = sd_probe,
1411 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001412#ifdef CONFIG_PM
1413 .suspend = gspca_suspend,
1414 .resume = gspca_resume,
1415#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001416};
1417
1418/* -- module insert / remove -- */
1419static int __init sd_mod_init(void)
1420{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001421 int ret;
1422 ret = usb_register(&sd_driver);
1423 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001424 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001425 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001426 return 0;
1427}
1428static void __exit sd_mod_exit(void)
1429{
1430 usb_deregister(&sd_driver);
1431 PDEBUG(D_PROBE, "deregistered");
1432}
1433
1434module_init(sd_mod_init);
1435module_exit(sd_mod_exit);