blob: d0c208c6a69062537c5b322150e41067dd13fa2e [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030017 *
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
24 * Costantino Leandro
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030025 */
26
27#define MODULE_NAME "t613"
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030028
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030031#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
Jean-Francois Moine82e25492009-01-22 07:18:48 -030040 u8 brightness;
41 u8 contrast;
42 u8 colors;
43 u8 autogain;
44 u8 gamma;
45 u8 sharpness;
46 u8 freq;
47 u8 whitebalance;
48 u8 mirror;
49 u8 effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030050
Jean-Francois Moine82e25492009-01-22 07:18:48 -030051 u8 sensor;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -030052#define SENSOR_OM6802 0
53#define SENSOR_OTHER 1
54#define SENSOR_TAS5130A 2
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055};
56
57/* V4L2 controls supported by the driver */
58static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_querymenu(struct gspca_dev *gspca_dev,
79 struct v4l2_querymenu *menu);
80
Marton Nemeth7e64dc42009-12-30 09:12:41 -030081static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030082 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030088 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -030090#define BRIGHTNESS_DEF 8
91 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030092 },
93 .set = sd_setbrightness,
94 .get = sd_getbrightness,
95 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030096 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300104#define CONTRAST_DEF 0x07
105 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300106 },
107 .set = sd_setcontrast,
108 .get = sd_getcontrast,
109 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300118#define COLORS_DEF 0x05
119 .default_value = COLORS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300120 },
121 .set = sd_setcolors,
122 .get = sd_getcolors,
123 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300124#define GAMMA_MAX 16
125#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126 {
127 {
128 .id = V4L2_CID_GAMMA, /* (gamma on win) */
129 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300130 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300131 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300132 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300133 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300134 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300135 },
136 .set = sd_setgamma,
137 .get = sd_getgamma,
138 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300139 {
140 {
141 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
142 * some apps dont bring up the
143 * backligth_compensation control) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Low Light",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300149#define AUTOGAIN_DEF 0x01
150 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151 },
152 .set = sd_setlowlight,
153 .get = sd_getlowlight,
154 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155 {
156 {
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300163#define MIRROR_DEF 0
164 .default_value = MIRROR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 },
166 .set = sd_setflip,
167 .get = sd_getflip
168 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169 {
170 {
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
175 .maximum = 2,
176 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300177#define FREQ_DEF 1
178 .default_value = FREQ_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179 },
180 .set = sd_setfreq,
181 .get = sd_getfreq},
182
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183 {
184 {
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
188 .minimum = 0,
189 .maximum = 1,
190 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300191#define WHITE_BALANCE_DEF 0
192 .default_value = WHITE_BALANCE_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300193 },
194 .set = sd_setwhitebalance,
195 .get = sd_getwhitebalance
196 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300197 {
198 {
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Sharpness",
202 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300203 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300205#define SHARPNESS_DEF 0x06
206 .default_value = SHARPNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207 },
208 .set = sd_setsharpness,
209 .get = sd_getsharpness,
210 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300211 {
212 {
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
216 .minimum = 0,
217 .maximum = 4,
218 .step = 1,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300219#define EFFECTS_DEF 0
220 .default_value = EFFECTS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300221 },
222 .set = sd_seteffect,
223 .get = sd_geteffect
224 },
225};
226
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300227static char *effects_control[] = {
228 "Normal",
229 "Emboss", /* disabled */
230 "Monochrome",
231 "Sepia",
232 "Sketch",
233 "Sun Effect", /* disabled */
234 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235};
236
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300237static const struct v4l2_pix_format vga_mode_t16[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300238 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
239 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300240 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300241 .colorspace = V4L2_COLORSPACE_JPEG,
242 .priv = 4},
243 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
244 .bytesperline = 176,
245 .sizeimage = 176 * 144 * 3 / 8 + 590,
246 .colorspace = V4L2_COLORSPACE_JPEG,
247 .priv = 3},
248 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
249 .bytesperline = 320,
250 .sizeimage = 320 * 240 * 3 / 8 + 590,
251 .colorspace = V4L2_COLORSPACE_JPEG,
252 .priv = 2},
253 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
254 .bytesperline = 352,
255 .sizeimage = 352 * 288 * 3 / 8 + 590,
256 .colorspace = V4L2_COLORSPACE_JPEG,
257 .priv = 1},
258 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
259 .bytesperline = 640,
260 .sizeimage = 640 * 480 * 3 / 8 + 590,
261 .colorspace = V4L2_COLORSPACE_JPEG,
262 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300263};
264
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300265/* sensor specific data */
266struct additional_sensor_data {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300267 const u8 n3[6];
268 const u8 *n4, n4sz;
269 const u8 reg80, reg8e;
270 const u8 nset8[6];
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300271 const u8 data1[10];
272 const u8 data2[9];
273 const u8 data3[9];
274 const u8 data4[4];
275 const u8 data5[6];
276 const u8 stream[4];
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300277};
278
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300279static const u8 n4_om6802[] = {
280 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
281 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
282 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
283 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
284 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
285 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
286 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
287 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
288 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
289};
290static const u8 n4_other[] = {
291 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
292 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
293 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
294 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
295 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
296 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
297 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
298 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
299};
300static const u8 n4_tas5130a[] = {
301 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
302 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
303 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
304 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
305 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
306 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
307 0xc6, 0xda
308};
309
Tobias Klausere23b2902009-02-09 18:06:49 -0300310static const struct additional_sensor_data sensor_data[] = {
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300311 { /* 0: OM6802 */
312 .n3 =
313 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
314 .n4 = n4_om6802,
315 .n4sz = sizeof n4_om6802,
316 .reg80 = 0x3c,
317 .reg8e = 0x33,
318 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300319 .data1 =
320 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
321 0xb3, 0xfc},
322 .data2 =
323 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
324 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300325 .data3 =
326 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
327 0xff},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300328 .data4 = /*Freq (50/60Hz). Splitted for test purpose */
329 {0x66, 0xca, 0xa8, 0xf0},
330 .data5 = /* this could be removed later */
331 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
332 .stream =
333 {0x0b, 0x04, 0x0a, 0x78},
334 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300335 { /* 1: OTHER */
336 .n3 =
337 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
338 .n4 = n4_other,
339 .n4sz = sizeof n4_other,
340 .reg80 = 0xac,
341 .reg8e = 0xb8,
342 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300343 .data1 =
344 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
345 0xe8, 0xfc},
346 .data2 =
347 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
348 0xd9},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300349 .data3 =
350 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
351 0xd9},
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300352 .data4 =
353 {0x66, 0x00, 0xa8, 0xa8},
354 .data5 =
355 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
356 .stream =
357 {0x0b, 0x04, 0x0a, 0x00},
358 },
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300359 { /* 2: TAS5130A */
360 .n3 =
361 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
362 .n4 = n4_tas5130a,
363 .n4sz = sizeof n4_tas5130a,
364 .reg80 = 0x3c,
365 .reg8e = 0xb4,
366 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300367 .data1 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300368 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
369 0xc8, 0xfc},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300370 .data2 =
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300371 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
372 0xe0},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300373 .data3 =
374 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
375 0xe0},
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300376 .data4 = /* Freq (50/60Hz). Splitted for test purpose */
377 {0x66, 0x00, 0xa8, 0xe8},
378 .data5 =
379 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
380 .stream =
381 {0x0b, 0x04, 0x0a, 0x40},
382 },
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300383};
384
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385#define MAX_EFFECTS 7
386/* easily done by soft, this table could be removed,
387 * i keep it here just in case */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300388static const u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300389 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
390 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
391 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
392 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
393 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
394 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
395 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
396};
397
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300398static const u8 gamma_table[GAMMA_MAX][17] = {
399 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */
400 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
401 0xff},
402 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */
403 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
404 0xff},
405 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */
406 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
407 0xff},
408 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */
409 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
410 0xff},
411 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */
412 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
413 0xff},
414 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */
415 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
416 0xff},
417 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */
418 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
419 0xff},
420 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */
421 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
422 0xff},
423 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */
424 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
425 0xff},
426 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */
427 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
428 0xff},
429 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */
430 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
431 0xff},
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300432 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300433 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
434 0xff},
435 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
436 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
437 0xff},
438 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
439 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
440 0xff},
441 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
442 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
443 0xff},
444 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
445 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
446 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447};
448
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300449static const u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
451 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
452 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453};
454
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300455static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300456
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300457/* read 1 byte */
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300458static u8 reg_r(struct gspca_dev *gspca_dev,
459 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300460{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300461 usb_control_msg(gspca_dev->dev,
462 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 0, /* request */
464 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
465 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300466 index,
467 gspca_dev->usb_buf, 1, 500);
468 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469}
470
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300471static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300472 u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300474 usb_control_msg(gspca_dev->dev,
475 usb_sndctrlpipe(gspca_dev->dev, 0),
476 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300477 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300478 0, index,
479 NULL, 0, 500);
480}
481
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300482static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300483 const u8 *buffer, u16 len)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300484{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300485 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300486 memcpy(gspca_dev->usb_buf, buffer, len);
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300489 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300491 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300492 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300493 } else {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300494 u8 *tmpbuf;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300495
496 tmpbuf = kmalloc(len, GFP_KERNEL);
497 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300498 usb_control_msg(gspca_dev->dev,
499 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300500 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300501 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300502 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300503 tmpbuf, len, 500);
504 kfree(tmpbuf);
505 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506}
507
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300508/* write values to consecutive registers */
509static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
510 u8 reg,
511 const u8 *buffer, u16 len)
512{
513 int i;
514 u8 *p, *tmpbuf;
515
516 if (len * 2 <= USB_BUF_SZ)
517 p = tmpbuf = gspca_dev->usb_buf;
518 else
519 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
520 i = len;
521 while (--i >= 0) {
522 *p++ = reg++;
523 *p++ = *buffer++;
524 }
525 usb_control_msg(gspca_dev->dev,
526 usb_sndctrlpipe(gspca_dev->dev, 0),
527 0,
528 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
529 0x01, 0,
530 tmpbuf, len * 2, 500);
531 if (len * 2 > USB_BUF_SZ)
532 kfree(tmpbuf);
533}
534
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300535/* Reported as OM6802*/
536static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300537{
538 int i;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300539 const u8 *p;
540 u8 byte;
541 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
542 static const u8 sensor_init[] = {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300543 0xdf, 0x6d,
544 0xdd, 0x18,
545 0x5a, 0xe0,
546 0x5c, 0x07,
547 0x5d, 0xb0,
548 0x5e, 0x1e,
549 0x60, 0x71,
550 0xef, 0x00,
551 0xe9, 0x00,
552 0xea, 0x00,
553 0x90, 0x24,
554 0x91, 0xb2,
555 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300556 0xfd, 0x41,
557 0x00 /* table end */
558 };
559
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300560 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinee30bdc62009-03-22 16:31:32 -0300561 msleep(100);
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300562 i = 4;
Roel Kluin97a53a02008-12-21 11:58:05 -0300563 while (--i > 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300564 byte = reg_r(gspca_dev, 0x0060);
565 if (!(byte & 0x01))
566 break;
567 msleep(100);
568 }
569 byte = reg_r(gspca_dev, 0x0063);
570 if (byte != 0x17) {
571 err("Bad sensor reset %02x", byte);
572 /* continue? */
573 }
574
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300575 p = sensor_init;
576 while (*p != 0) {
577 val[1] = *p++;
578 val[3] = *p++;
579 if (*p == 0)
580 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300581 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300582 i = 4;
583 while (--i >= 0) {
584 msleep(15);
585 byte = reg_r(gspca_dev, 0x60);
586 if (!(byte & 0x01))
587 break;
588 }
589 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300590 msleep(15);
591 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300592}
593
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594/* this function is called at probe time */
595static int sd_config(struct gspca_dev *gspca_dev,
596 const struct usb_device_id *id)
597{
598 struct sd *sd = (struct sd *) gspca_dev;
599 struct cam *cam;
600
601 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300602
603 cam->cam_mode = vga_mode_t16;
604 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
605
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300606 sd->brightness = BRIGHTNESS_DEF;
607 sd->contrast = CONTRAST_DEF;
608 sd->colors = COLORS_DEF;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300609 sd->gamma = GAMMA_DEF;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300610 sd->autogain = AUTOGAIN_DEF;
611 sd->mirror = MIRROR_DEF;
612 sd->freq = FREQ_DEF;
613 sd->whitebalance = WHITE_BALANCE_DEF;
614 sd->sharpness = SHARPNESS_DEF;
615 sd->effect = EFFECTS_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300616 return 0;
617}
618
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300619static void setbrightness(struct gspca_dev *gspca_dev)
620{
621 struct sd *sd = (struct sd *) gspca_dev;
622 unsigned int brightness;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300623 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300624
625 brightness = sd->brightness;
626 if (brightness < 7) {
627 set6[1] = 0x26;
628 set6[3] = 0x70 - brightness * 0x10;
629 } else {
630 set6[3] = 0x00 + ((brightness - 7) * 0x10);
631 }
632
633 reg_w_buf(gspca_dev, set6, sizeof set6);
634}
635
636static void setcontrast(struct gspca_dev *gspca_dev)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 unsigned int contrast = sd->contrast;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300640 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300641
642 if (contrast < 7)
643 reg_to_write = 0x8ea9 - contrast * 0x200;
644 else
645 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
646
647 reg_w(gspca_dev, reg_to_write);
648}
649
650static void setcolors(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300653 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300654
655 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
656 reg_w(gspca_dev, reg_to_write);
657}
658
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300659static void setgamma(struct gspca_dev *gspca_dev)
660{
661 struct sd *sd = (struct sd *) gspca_dev;
662
663 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300664 reg_w_ixbuf(gspca_dev, 0x90,
665 gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300666}
667
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300668static void setwhitebalance(struct gspca_dev *gspca_dev)
669{
670 struct sd *sd = (struct sd *) gspca_dev;
671
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300672 u8 white_balance[8] =
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300673 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
674
675 if (sd->whitebalance)
676 white_balance[7] = 0x3c;
677
678 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
679}
680
681static void setsharpness(struct gspca_dev *gspca_dev)
682{
683 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300684 u16 reg_to_write;
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300685
686 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
687
688 reg_w(gspca_dev, reg_to_write);
689}
690
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300691/* this function is called at probe and resume time */
692static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 /* some of this registers are not really neded, because
695 * they are overriden by setbrigthness, setcontrast, etc,
696 * but wont hurt anyway, and can help someone with similar webcam
697 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300698 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300699 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300700 int i;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300701 u16 sensor_id;
Hans Verkuild9ddd3b2009-01-29 06:23:18 -0300702 u8 test_byte = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300704 static const u8 read_indexs[] =
Jean-Francois Moine249fe882009-03-22 16:30:42 -0300705 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300706 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
707 static const u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300709 static const u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710 {0x08, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300712 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
713 | reg_r(gspca_dev, 0x07);
Jean-Francois Moine3da37e42009-03-22 16:29:36 -0300714 switch (sensor_id & 0xff0f) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300715 case 0x0801:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300716 PDEBUG(D_PROBE, "sensor tas5130a");
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300717 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300718 break;
719 case 0x0803:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300720 PDEBUG(D_PROBE, "sensor 'other'");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300721 sd->sensor = SENSOR_OTHER;
722 break;
723 case 0x0807:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300724 PDEBUG(D_PROBE, "sensor om6802");
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300725 sd->sensor = SENSOR_OM6802;
726 break;
727 default:
Jean-Francois Moine748c0142009-02-06 14:11:58 -0300728 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
Jean-Francois Moine409b11d2009-01-22 12:53:56 -0300729 return -EINVAL;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300730 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731
Jean-Francois Moinedd72cb32009-03-12 04:40:19 -0300732 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300733 reg_w_buf(gspca_dev, n1, sizeof n1);
734 i = 5;
735 while (--i >= 0) {
736 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
737 test_byte = reg_r(gspca_dev, 0x0063);
738 msleep(100);
739 if (test_byte == 0x17)
740 break; /* OK */
741 }
742 if (i < 0) {
743 err("Bad sensor reset %02x", test_byte);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300744 return -EIO;
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300745 }
746 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300747 }
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300748
749 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300751 test_byte = reg_r(gspca_dev, read_indexs[i]);
752 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753 test_byte);
754 i++;
755 }
756
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300757 sensor = &sensor_data[sd->sensor];
758 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
759 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300760
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300761 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
762 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
763 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300764
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300765 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
766 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
767 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300768
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300769 setbrightness(gspca_dev);
770 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300771 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300772 setcolors(gspca_dev);
773 setsharpness(gspca_dev);
774 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300776 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300777 reg_w(gspca_dev, 0x2088);
778 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300780 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
781 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
782 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
783 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300784
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300785 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
786 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
787 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300788
789 return 0;
790}
791
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792static void setflip(struct gspca_dev *gspca_dev)
793{
794 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300795 u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300796 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300797
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300798 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799 flipcmd[3] = 0x01;
800
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300801 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300802}
803
804static void seteffect(struct gspca_dev *gspca_dev)
805{
806 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300808 reg_w_buf(gspca_dev, effects_table[sd->effect],
809 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810 if (sd->effect == 1 || sd->effect == 5) {
811 PDEBUG(D_CONF,
812 "This effect have been disabled for webcam \"safety\"");
813 return;
814 }
815
816 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300817 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300819 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820}
821
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822static void setlightfreq(struct gspca_dev *gspca_dev)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300825 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826
827 if (sd->freq == 2) /* 60hz */
828 freq[1] = 0x00;
829
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300830 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831}
832
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300833/* Is this really needed?
834 * i added some module parameters for test with some users */
835static void poll_sensor(struct gspca_dev *gspca_dev)
836{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300837 static const u8 poll1[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300838 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
839 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
840 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
841 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300842 static const u8 poll2[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300843 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
844 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300845 static const u8 poll3[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300846 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300847 static const u8 poll4[] =
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300848 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
849 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
850 0xc2, 0x80, 0xc3, 0x10};
851
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300852 PDEBUG(D_STREAM, "[Sensor requires polling]");
853 reg_w_buf(gspca_dev, poll1, sizeof poll1);
854 reg_w_buf(gspca_dev, poll2, sizeof poll2);
855 reg_w_buf(gspca_dev, poll3, sizeof poll3);
856 reg_w_buf(gspca_dev, poll4, sizeof poll4);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300857}
858
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300859static int sd_start(struct gspca_dev *gspca_dev)
860{
861 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300862 const struct additional_sensor_data *sensor;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300863 int i, mode;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300864 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
865 static const u8 t3[] =
866 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300867
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300868 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300869 switch (mode) {
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300870 case 0: /* 640x480 (0x00) */
871 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300872 case 1: /* 352x288 */
873 t2[1] = 0x40;
874 break;
875 case 2: /* 320x240 */
876 t2[1] = 0x10;
877 break;
878 case 3: /* 176x144 */
879 t2[1] = 0x50;
880 break;
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300881 default:
882/* case 4: * 160x120 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300883 t2[1] = 0x20;
884 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300885 }
886
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300887 switch (sd->sensor) {
888 case SENSOR_OM6802:
889 om6802_sensor_init(gspca_dev);
890 break;
891 case SENSOR_OTHER:
892 break;
893 default:
894/* case SENSOR_TAS5130A: */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300895 i = 0;
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300896 for (;;) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300897 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300898 sizeof tas5130a_sensor_init[0]);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300899 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
900 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300901 i++;
902 }
903 reg_w(gspca_dev, 0x3c80);
904 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300905 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300906 sizeof tas5130a_sensor_init[0]);
907 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300908 break;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300909 }
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300910 sensor = &sensor_data[sd->sensor];
911 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300912 reg_r(gspca_dev, 0x0012);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300913 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300914 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300915 reg_w(gspca_dev, 0x0013);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300916 msleep(15);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300917 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
918 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
Leandro Costantinoad62fb02008-10-17 05:27:04 -0300919
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300920 if (sd->sensor == SENSOR_OM6802)
921 poll_sensor(gspca_dev);
922
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300923 return 0;
924}
925
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300926static void sd_stopN(struct gspca_dev *gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929
930 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
931 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300932 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
933 sizeof sensor_data[sd->sensor].stream);
Jean-Francois Moine78a6d742009-07-07 04:03:24 -0300934 if (sd->sensor == SENSOR_OM6802) {
Jean-Francois Moine2d56f3b2009-01-22 08:25:16 -0300935 msleep(20);
936 reg_w(gspca_dev, 0x0309);
937 }
Jean-Francois Moineeb229b22008-10-17 05:28:40 -0300938}
939
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300940static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300941 u8 *data, /* isoc packet */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300942 int len) /* iso packet length */
943{
Jean-Francois Moine82e25492009-01-22 07:18:48 -0300944 static u8 ffd9[] = { 0xff, 0xd9 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300945
946 if (data[0] == 0x5a) {
947 /* Control Packet, after this came the header again,
948 * but extra bytes came in the packet before this,
949 * sometimes an EOF arrives, sometimes not... */
950 return;
951 }
952 data += 2;
953 len -= 2;
954 if (data[0] == 0xff && data[1] == 0xd8) {
955 /* extra bytes....., could be processed too but would be
956 * a waste of time, right now leave the application and
957 * libjpeg do it for ourserlves.. */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300958 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300959 ffd9, 2);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300960 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300961 return;
962 }
963
964 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
965 /* Just in case, i have seen packets with the marker,
966 * other's do not include it... */
967 len -= 2;
968 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300969 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970}
971
972static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975
976 sd->brightness = val;
977 if (gspca_dev->streaming)
978 setbrightness(gspca_dev);
979 return 0;
980}
981
982static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 *val = sd->brightness;
987 return *val;
988}
989
990static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
991{
992 struct sd *sd = (struct sd *) gspca_dev;
993
994 sd->whitebalance = val;
995 if (gspca_dev->streaming)
996 setwhitebalance(gspca_dev);
997 return 0;
998}
999
1000static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1001{
1002 struct sd *sd = (struct sd *) gspca_dev;
1003
1004 *val = sd->whitebalance;
1005 return *val;
1006}
1007
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001008static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1009{
1010 struct sd *sd = (struct sd *) gspca_dev;
1011
1012 sd->mirror = val;
1013 if (gspca_dev->streaming)
1014 setflip(gspca_dev);
1015 return 0;
1016}
1017
1018static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1019{
1020 struct sd *sd = (struct sd *) gspca_dev;
1021
1022 *val = sd->mirror;
1023 return *val;
1024}
1025
1026static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1027{
1028 struct sd *sd = (struct sd *) gspca_dev;
1029
1030 sd->effect = val;
1031 if (gspca_dev->streaming)
1032 seteffect(gspca_dev);
1033 return 0;
1034}
1035
1036static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039
1040 *val = sd->effect;
1041 return *val;
1042}
1043
1044static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
1048 sd->contrast = val;
1049 if (gspca_dev->streaming)
1050 setcontrast(gspca_dev);
1051 return 0;
1052}
1053
1054static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1055{
1056 struct sd *sd = (struct sd *) gspca_dev;
1057
1058 *val = sd->contrast;
1059 return *val;
1060}
1061
1062static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1063{
1064 struct sd *sd = (struct sd *) gspca_dev;
1065
1066 sd->colors = val;
1067 if (gspca_dev->streaming)
1068 setcolors(gspca_dev);
1069 return 0;
1070}
1071
1072static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1073{
1074 struct sd *sd = (struct sd *) gspca_dev;
1075
1076 *val = sd->colors;
1077 return 0;
1078}
1079
1080static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083
1084 sd->gamma = val;
1085 if (gspca_dev->streaming)
1086 setgamma(gspca_dev);
1087 return 0;
1088}
1089
1090static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1091{
1092 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001093
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001094 *val = sd->gamma;
1095 return 0;
1096}
1097
1098static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101
1102 sd->freq = val;
1103 if (gspca_dev->streaming)
1104 setlightfreq(gspca_dev);
1105 return 0;
1106}
1107
1108static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1109{
1110 struct sd *sd = (struct sd *) gspca_dev;
1111
1112 *val = sd->freq;
1113 return 0;
1114}
1115
1116static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1117{
1118 struct sd *sd = (struct sd *) gspca_dev;
1119
1120 sd->sharpness = val;
1121 if (gspca_dev->streaming)
1122 setsharpness(gspca_dev);
1123 return 0;
1124}
1125
1126static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1127{
1128 struct sd *sd = (struct sd *) gspca_dev;
1129
1130 *val = sd->sharpness;
1131 return 0;
1132}
1133
1134/* Low Light set here......*/
1135static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1136{
1137 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001138
1139 sd->autogain = val;
1140 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001141 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001143 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144 return 0;
1145}
1146
1147static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1148{
1149 struct sd *sd = (struct sd *) gspca_dev;
1150
1151 *val = sd->autogain;
1152 return 0;
1153}
1154
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001155static int sd_querymenu(struct gspca_dev *gspca_dev,
1156 struct v4l2_querymenu *menu)
1157{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 switch (menu->id) {
1159 case V4L2_CID_POWER_LINE_FREQUENCY:
1160 switch (menu->index) {
1161 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001162 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001163 return 0;
1164 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001165 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001166 return 0;
1167 }
1168 break;
1169 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001170 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1171 strncpy((char *) menu->name,
1172 effects_control[menu->index], 32);
1173 return 0;
1174 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175 break;
1176 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001177 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001178}
1179
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001181static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 .name = MODULE_NAME,
1183 .ctrls = sd_ctrls,
1184 .nctrls = ARRAY_SIZE(sd_ctrls),
1185 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001186 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001187 .start = sd_start,
Jean-Francois Moineeb229b22008-10-17 05:28:40 -03001188 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001189 .pkt_scan = sd_pkt_scan,
1190 .querymenu = sd_querymenu,
1191};
1192
1193/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001194static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001195 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001196 {}
1197};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001198MODULE_DEVICE_TABLE(usb, device_table);
1199
1200/* -- device connect -- */
1201static int sd_probe(struct usb_interface *intf,
1202 const struct usb_device_id *id)
1203{
1204 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1205 THIS_MODULE);
1206}
1207
1208static struct usb_driver sd_driver = {
1209 .name = MODULE_NAME,
1210 .id_table = device_table,
1211 .probe = sd_probe,
1212 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001213#ifdef CONFIG_PM
1214 .suspend = gspca_suspend,
1215 .resume = gspca_resume,
1216#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217};
1218
1219/* -- module insert / remove -- */
1220static int __init sd_mod_init(void)
1221{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001222 int ret;
1223 ret = usb_register(&sd_driver);
1224 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001225 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001226 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227 return 0;
1228}
1229static void __exit sd_mod_exit(void)
1230{
1231 usb_deregister(&sd_driver);
1232 PDEBUG(D_PROBE, "deregistered");
1233}
1234
1235module_init(sd_mod_init);
1236module_exit(sd_mod_exit);