2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "sonixj"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
36 unsigned int exposure;
38 unsigned short brightness;
39 unsigned char contrast;
41 unsigned char autogain;
44 #define AG_CNT_START 13
48 #define BRIDGE_SN9C102P 0
49 #define BRIDGE_SN9C105 1
50 #define BRIDGE_SN9C110 2
51 #define BRIDGE_SN9C120 3
52 #define BRIDGE_SN9C325 4
53 char sensor; /* Type of image sensor chip */
54 #define SENSOR_HV7131R 0
55 #define SENSOR_MI0360 1
56 #define SENSOR_MO4000 2
57 #define SENSOR_OM6802 3
58 #define SENSOR_OV7648 4
59 #define SENSOR_OV7660 5
60 unsigned char i2c_base;
63 /* V4L2 controls supported by the driver */
64 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
71 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
73 static struct ctrl sd_ctrls[] = {
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
82 #define BRIGHTNESS_DEF 0x7fff
83 .default_value = BRIGHTNESS_DEF,
85 .set = sd_setbrightness,
86 .get = sd_getbrightness,
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
96 #define CONTRAST_DEF 63
97 .default_value = CONTRAST_DEF,
99 .set = sd_setcontrast,
100 .get = sd_getcontrast,
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
110 #define COLOR_DEF 127
111 .default_value = COLOR_DEF,
118 .id = V4L2_CID_AUTOGAIN,
119 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 #define AUTOGAIN_DEF 1
125 .default_value = AUTOGAIN_DEF,
127 .set = sd_setautogain,
128 .get = sd_getautogain,
132 static struct v4l2_pix_format vga_mode[] = {
133 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
135 .sizeimage = 160 * 120 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
138 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
140 .sizeimage = 320 * 240 * 3 / 8 + 590,
141 .colorspace = V4L2_COLORSPACE_JPEG,
143 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
145 .sizeimage = 640 * 480 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
150 /*Data from sn9c102p+hv71331r */
151 static const __u8 sn_hv7131[] = {
152 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
153 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
154 /* reg8 reg9 rega regb regc regd rege regf */
155 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
156 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
157 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
158 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
159 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
162 static const __u8 sn_mi0360[] = {
163 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
164 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
165 /* reg8 reg9 rega regb regc regd rege regf */
166 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
167 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
168 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
169 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
170 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
173 static const __u8 sn_mo4000[] = {
174 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
175 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
176 /* reg8 reg9 rega regb regc regd rege regf */
177 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
179 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
180 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
181 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
184 static const __u8 sn_om6802[] = {
185 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
186 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
187 /* reg8 reg9 rega regb regc regd rege regf */
188 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
190 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
191 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
192 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
194 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
198 static const __u8 sn_ov7648[] = {
199 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
200 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
201 /* reg8 reg9 rega regb regc regd rege regf */
202 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
203 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
204 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
205 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
206 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
209 static const __u8 sn_ov7660[] = {
210 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
211 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
212 /* reg8 reg9 rega regb regc regd rege regf */
213 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
214 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
215 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
216 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
217 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 /* sequence specific to the sensors - !! index = SENSOR_xxx */
221 static const __u8 *sn_tb[] = {
230 static const __u8 regsn20[] = {
231 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
232 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
234 static const __u8 regsn20_sn9c325[] = {
235 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
236 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
239 static const __u8 reg84[] = {
240 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
241 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
242 /* 0x00, 0x00, 0x00, 0x00, 0x00 */
243 0xf7, 0x0f, 0x0a, 0x00, 0x00
245 static const __u8 reg84_sn9c325[] = {
246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
248 0xf8, 0x0f, 0x00, 0x00, 0x00
251 static const __u8 hv7131r_sensor_init[][8] = {
252 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
253 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
254 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
255 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
258 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
262 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
263 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
264 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
267 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
269 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
270 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
272 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
282 static const __u8 mi0360_sensor_init[][8] = {
283 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
287 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
288 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
305 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
306 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
308 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
310 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
312 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
315 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
317 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
318 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
319 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
321 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
323 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
324 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
325 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
326 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
328 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
329 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
330 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
331 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
332 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
333 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
336 static const __u8 mo4000_sensor_init[][8] = {
337 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
359 static __u8 om6802_sensor_init[][8] = {
360 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
361 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
362 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
363 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
364 /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
365 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
366 /* white balance & auto-exposure */
367 /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
369 /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
370 * max AGC value in AE */
371 /* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
373 /* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
374 * preset brightness */
375 /* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
377 /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
379 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
380 /* luminance mode (0x4f = AE) */
381 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
383 /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
385 /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
387 /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
388 /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
389 /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
390 /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
393 static const __u8 ov7660_sensor_init[][8] = {
394 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
396 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
397 /* Outformat = rawRGB */
398 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
399 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
400 /* GAIN BLUE RED VREF */
401 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
402 /* COM 1 BAVE GEAVE AECHH */
403 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
404 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
405 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
406 /* AECH CLKRC COM7 COM8 */
407 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
408 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
409 /* HSTART HSTOP VSTRT VSTOP */
410 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
411 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
412 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
413 /* BOS GBOS GROS ROS (BGGR offset) */
414 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
415 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
416 /* AEW AEB VPT BBIAS */
417 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
418 /* GbBIAS RSVD EXHCH EXHCL */
419 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
420 /* RBIAS ADVFL ASDVFH YAVE */
421 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
422 /* HSYST HSYEN HREF */
423 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
424 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
425 /* ADC ACOM OFON TSLB */
426 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
427 /* COM11 COM12 COM13 COM14 */
428 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
429 /* EDGE COM15 COM16 COM17 */
430 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
431 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
432 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
433 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
434 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
435 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
436 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
437 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
438 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
439 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
440 /* LCC1 LCC2 LCC3 LCC4 */
441 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
442 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
443 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
444 /* band gap reference [0:3] DBLV */
445 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
446 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
447 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
448 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
449 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
450 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
451 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
452 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
453 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
454 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
455 /****** (some exchanges in the win trace) ******/
456 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
457 /* bits[3..0]reserved */
458 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
459 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
460 /* VREF vertical frame ctrl */
461 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
462 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
463 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
464 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
465 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
466 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
467 /****** (some exchanges in the win trace) ******/
468 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
469 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
470 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
471 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
472 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
473 /****** (some exchanges in the win trace) ******/
474 /******!! startsensor KO if changed !!****/
475 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
477 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
478 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
481 /* reg 0x04 reg 0x07 reg 0x10 */
482 /* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
484 static const __u8 ov7648_sensor_init[][8] = {
485 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
486 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
487 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
488 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
489 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
492 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
493 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
494 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
495 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
496 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
497 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
498 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
499 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
500 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
501 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
502 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
503 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
504 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
505 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
506 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
507 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
508 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
509 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
510 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
511 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
512 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
513 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
514 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
515 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
516 * This is currently setting a
517 * blue tint, and some things more , i leave it here for future test if
518 * somene is having problems with color on this sensor
519 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
520 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
521 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
522 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
523 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
524 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
525 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
526 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
527 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
528 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
529 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
530 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
531 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
532 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
533 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
534 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
535 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
536 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
540 static const __u8 qtable4[] = {
541 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
542 0x06, 0x08, 0x0A, 0x11,
543 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
544 0x19, 0x19, 0x17, 0x15,
545 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
546 0x21, 0x2E, 0x21, 0x23,
547 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
548 0x25, 0x29, 0x2C, 0x29,
549 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
550 0x17, 0x1B, 0x29, 0x29,
551 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
552 0x29, 0x29, 0x29, 0x29,
553 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
554 0x29, 0x29, 0x29, 0x29,
555 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
556 0x29, 0x29, 0x29, 0x29
559 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
560 static void reg_r(struct gspca_dev *gspca_dev,
561 __u16 value, int len)
563 usb_control_msg(gspca_dev->dev,
564 usb_rcvctrlpipe(gspca_dev->dev, 0),
566 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
568 gspca_dev->usb_buf, len,
570 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
573 static void reg_w1(struct gspca_dev *gspca_dev,
577 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
578 gspca_dev->usb_buf[0] = data;
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
585 gspca_dev->usb_buf, 1,
588 static void reg_w(struct gspca_dev *gspca_dev,
593 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
594 value, buffer[0], buffer[1]);
595 if (len <= sizeof gspca_dev->usb_buf) {
596 memcpy(gspca_dev->usb_buf, buffer, len);
597 usb_control_msg(gspca_dev->dev,
598 usb_sndctrlpipe(gspca_dev->dev, 0),
600 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
602 gspca_dev->usb_buf, len,
607 tmpbuf = kmalloc(len, GFP_KERNEL);
608 memcpy(tmpbuf, buffer, len);
609 usb_control_msg(gspca_dev->dev,
610 usb_sndctrlpipe(gspca_dev->dev, 0),
612 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
620 /* I2C write 1 byte */
621 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
623 struct sd *sd = (struct sd *) gspca_dev;
625 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
626 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
627 gspca_dev->usb_buf[1] = sd->i2c_base;
628 gspca_dev->usb_buf[2] = reg;
629 gspca_dev->usb_buf[3] = val;
630 gspca_dev->usb_buf[4] = 0;
631 gspca_dev->usb_buf[5] = 0;
632 gspca_dev->usb_buf[6] = 0;
633 gspca_dev->usb_buf[7] = 0x10;
634 usb_control_msg(gspca_dev->dev,
635 usb_sndctrlpipe(gspca_dev->dev, 0),
637 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
638 0x08, /* value = i2c */
640 gspca_dev->usb_buf, 8,
644 /* I2C write 8 bytes */
645 static void i2c_w8(struct gspca_dev *gspca_dev,
648 memcpy(gspca_dev->usb_buf, buffer, 8);
649 usb_control_msg(gspca_dev->dev,
650 usb_sndctrlpipe(gspca_dev->dev, 0),
652 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
653 0x08, 0, /* value, index */
654 gspca_dev->usb_buf, 8,
658 /* read 5 bytes in gspca_dev->usb_buf */
659 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
661 struct sd *sd = (struct sd *) gspca_dev;
664 mode[0] = 0x81 | 0x10;
665 mode[1] = sd->i2c_base;
672 i2c_w8(gspca_dev, mode);
674 mode[0] = 0x81 | (5 << 4) | 0x02;
676 i2c_w8(gspca_dev, mode);
678 reg_r(gspca_dev, 0x0a, 5);
681 static int probesensor(struct gspca_dev *gspca_dev)
683 struct sd *sd = (struct sd *) gspca_dev;
685 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
687 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
689 i2c_r5(gspca_dev, 0); /* read sensor id */
690 if (gspca_dev->usb_buf[0] == 0x02
691 && gspca_dev->usb_buf[1] == 0x09
692 && gspca_dev->usb_buf[2] == 0x01
693 && gspca_dev->usb_buf[3] == 0x00
694 && gspca_dev->usb_buf[4] == 0x00) {
695 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
696 sd->sensor = SENSOR_HV7131R;
697 return SENSOR_HV7131R;
699 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
700 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
701 gspca_dev->usb_buf[2]);
702 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
706 static int configure_gpio(struct gspca_dev *gspca_dev,
709 struct sd *sd = (struct sd *) gspca_dev;
711 static const __u8 reg9a_def[] =
712 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
713 static const __u8 reg9a_sn9c325[] =
714 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
715 static const __u8 regd4[] = {0x60, 0x00, 0x00};
717 reg_w1(gspca_dev, 0xf1, 0x00);
718 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
721 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
722 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
723 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
724 switch (sd->bridge) {
726 reg9a = reg9a_sn9c325;
732 reg_w(gspca_dev, 0x9a, reg9a, 6);
734 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
736 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
738 switch (sd->sensor) {
740 reg_w1(gspca_dev, 0x02, 0x71);
741 reg_w1(gspca_dev, 0x01, 0x42);
742 reg_w1(gspca_dev, 0x17, 0x64);
743 reg_w1(gspca_dev, 0x01, 0x42);
746 reg_w1(gspca_dev, 0x01, 0x43);
747 reg_w1(gspca_dev, 0x17, 0xae);
748 reg_w1(gspca_dev, 0x01, 0x42);
751 reg_w1(gspca_dev, 0x01, 0x43);
752 reg_w1(gspca_dev, 0x17, 0x61);
753 reg_w1(gspca_dev, 0x01, 0x42);
754 if (sd->sensor == SENSOR_HV7131R) {
755 if (probesensor(gspca_dev) < 0)
763 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
766 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
767 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
769 while (hv7131r_sensor_init[i][0]) {
770 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
773 i2c_w8(gspca_dev, SetSensorClk);
776 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
780 while (mi0360_sensor_init[i][0]) {
781 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
786 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
790 while (mo4000_sensor_init[i][0]) {
791 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
796 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
800 while (om6802_sensor_init[i][0]) {
801 i2c_w8(gspca_dev, om6802_sensor_init[i]);
806 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
810 while (ov7648_sensor_init[i][0]) {
811 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
816 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
820 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
823 while (ov7660_sensor_init[i][0]) {
824 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
829 /* this function is called at probe time */
830 static int sd_config(struct gspca_dev *gspca_dev,
831 const struct usb_device_id *id)
833 struct sd *sd = (struct sd *) gspca_dev;
836 cam = &gspca_dev->cam;
838 cam->cam_mode = vga_mode;
839 cam->nmodes = ARRAY_SIZE(vga_mode);
841 sd->bridge = id->driver_info >> 16;
842 sd->sensor = id->driver_info >> 8;
843 sd->i2c_base = id->driver_info;
845 sd->qindex = 4; /* set the quantization table */
846 sd->brightness = BRIGHTNESS_DEF;
847 sd->contrast = CONTRAST_DEF;
848 sd->colors = COLOR_DEF;
849 sd->autogain = AUTOGAIN_DEF;
855 /* this function is called at open time */
856 static int sd_open(struct gspca_dev *gspca_dev)
858 struct sd *sd = (struct sd *) gspca_dev;
859 /* const __u8 *sn9c1xx; */
860 __u8 regGpio[] = { 0x29, 0x74 };
863 /* setup a selector by bridge */
864 reg_w1(gspca_dev, 0xf1, 0x01);
865 reg_r(gspca_dev, 0x00, 1);
866 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
867 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
868 regF1 = gspca_dev->usb_buf[0];
869 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
870 switch (sd->bridge) {
871 case BRIDGE_SN9C102P:
874 reg_w1(gspca_dev, 0x02, regGpio[1]);
879 reg_w(gspca_dev, 0x02, regGpio, 2);
885 reg_w(gspca_dev, 0x02, regGpio, 2);
888 /* case BRIDGE_SN9C110: */
889 /* case BRIDGE_SN9C325: */
892 reg_w1(gspca_dev, 0x02, 0x62);
896 reg_w1(gspca_dev, 0xf1, 0x01);
901 static unsigned int setexposure(struct gspca_dev *gspca_dev,
904 struct sd *sd = (struct sd *) gspca_dev;
905 static const __u8 doit[] = /* update sensor */
906 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
907 static const __u8 sensorgo[] = /* sensor on */
908 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
909 static const __u8 gainMo[] =
910 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
912 switch (sd->sensor) {
913 case SENSOR_HV7131R: {
915 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
917 Expodoit[3] = expo >> 16;
918 Expodoit[4] = expo >> 8;
920 i2c_w8(gspca_dev, Expodoit);
923 case SENSOR_MI0360: {
924 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
925 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
929 else if (expo < 0x0001)
931 expoMi[3] = expo >> 8;
933 i2c_w8(gspca_dev, expoMi);
934 i2c_w8(gspca_dev, doit);
935 i2c_w8(gspca_dev, sensorgo);
938 case SENSOR_MO4000: {
940 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
942 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
946 else if (expo < 0x0001)
948 expoMof[3] = (expo & 0x03fc) >> 2;
949 i2c_w8(gspca_dev, expoMof);
950 expoMo10[3] = ((expo & 0x1c00) >> 10)
951 | ((expo & 0x0003) << 4);
952 i2c_w8(gspca_dev, expoMo10);
953 i2c_w8(gspca_dev, gainMo);
954 PDEBUG(D_CONF, "set exposure %d",
955 ((expoMo10[3] & 0x07) << 10)
957 | ((expoMo10[3] & 0x30) >> 4));
960 case SENSOR_OM6802: {
962 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
968 gainOm[3] = expo >> 2;
969 i2c_w8(gspca_dev, gainOm);
970 reg_w1(gspca_dev, 0x96, expo >> 5);
971 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
978 static void setbrightness(struct gspca_dev *gspca_dev)
980 struct sd *sd = (struct sd *) gspca_dev;
984 k2 = sd->brightness >> 10;
985 switch (sd->sensor) {
987 expo = sd->brightness << 4;
988 if (expo > 0x002dc6c0)
990 else if (expo < 0x02a0)
992 sd->exposure = setexposure(gspca_dev, expo);
996 expo = sd->brightness >> 4;
997 sd->exposure = setexposure(gspca_dev, expo);
1000 expo = sd->brightness >> 6;
1001 sd->exposure = setexposure(gspca_dev, expo);
1002 k2 = sd->brightness >> 11;
1006 reg_w1(gspca_dev, 0x96, k2);
1009 static void setcontrast(struct gspca_dev *gspca_dev)
1011 struct sd *sd = (struct sd *) gspca_dev;
1013 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1017 contrast[0] = (k2 + 1) >> 1;
1018 contrast[4] = (k2 + 1) / 5;
1019 reg_w(gspca_dev, 0x84, contrast, 6);
1022 static void setcolors(struct gspca_dev *gspca_dev)
1024 struct sd *sd = (struct sd *) gspca_dev;
1028 colour = sd->colors - 128;
1030 data = (colour + 32) & 0x7f; /* blue */
1032 data = (-colour + 32) & 0x7f; /* red */
1033 reg_w1(gspca_dev, 0x05, data);
1036 static void setautogain(struct gspca_dev *gspca_dev)
1038 struct sd *sd = (struct sd *) gspca_dev;
1040 switch (sd->sensor) {
1041 case SENSOR_HV7131R:
1045 sd->ag_cnt = AG_CNT_START;
1052 /* -- start the camera -- */
1053 static void sd_start(struct gspca_dev *gspca_dev)
1055 struct sd *sd = (struct sd *) gspca_dev;
1057 __u8 reg1, reg17, reg18;
1058 const __u8 *sn9c1xx;
1060 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1061 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1062 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1063 static const __u8 CE_sn9c325[] =
1064 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1066 sn9c1xx = sn_tb[(int) sd->sensor];
1067 configure_gpio(gspca_dev, sn9c1xx);
1069 /* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
1070 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1071 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1072 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1073 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1074 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1075 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1076 reg_w1(gspca_dev, 0xd3, 0x50);
1077 reg_w1(gspca_dev, 0xc6, 0x00);
1078 reg_w1(gspca_dev, 0xc7, 0x00);
1079 reg_w1(gspca_dev, 0xc8, 0x50);
1080 reg_w1(gspca_dev, 0xc9, 0x3c);
1081 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1082 switch (sd->bridge) {
1083 case BRIDGE_SN9C325:
1090 reg_w1(gspca_dev, 0x17, reg17);
1091 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1092 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1093 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1094 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1095 switch (sd->bridge) {
1096 case BRIDGE_SN9C325:
1097 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1098 sizeof regsn20_sn9c325);
1099 for (i = 0; i < 8; i++)
1100 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1101 sizeof reg84_sn9c325);
1102 reg_w1(gspca_dev, 0x9a, 0x0a);
1103 reg_w1(gspca_dev, 0x99, 0x60);
1106 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1107 for (i = 0; i < 8; i++)
1108 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1109 reg_w1(gspca_dev, 0x9a, 0x08);
1110 reg_w1(gspca_dev, 0x99, 0x59);
1114 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1116 reg1 = 0x46; /* 320 clk 48Mhz */
1118 reg1 = 0x06; /* 640 clk 24Mz */
1120 switch (sd->sensor) {
1121 case SENSOR_HV7131R:
1122 hv7131R_InitSensor(gspca_dev);
1125 mi0360_InitSensor(gspca_dev);
1128 mo4000_InitSensor(gspca_dev);
1130 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1131 reg1 = 0x06; /* clk 24Mz */
1133 reg17 = 0x22; /* 640 MCKSIZE */
1134 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1138 om6802_InitSensor(gspca_dev);
1139 reg17 = 0x64; /* 640 MCKSIZE */
1142 ov7648_InitSensor(gspca_dev);
1151 /* case SENSOR_OV7660: */
1152 ov7660_InitSensor(gspca_dev);
1154 /* reg17 = 0x21; * 320 */
1156 /* reg1 = 0x46; (done) */
1158 reg17 = 0x22; /* 640 MCKSIZE */
1163 reg_w(gspca_dev, 0xc0, C0, 6);
1164 reg_w(gspca_dev, 0xca, CA, 4);
1165 switch (sd->bridge) {
1166 case BRIDGE_SN9C325:
1167 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1170 reg_w(gspca_dev, 0xce, CE, 4);
1171 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1175 /* here change size mode 0 -> VGA; 1 -> CIF */
1176 reg18 = sn9c1xx[0x18] | (mode << 4);
1177 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1179 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1180 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1182 reg_w1(gspca_dev, 0x18, reg18);
1184 reg_w1(gspca_dev, 0x17, reg17);
1185 reg_w1(gspca_dev, 0x01, reg1);
1186 setbrightness(gspca_dev);
1187 setcontrast(gspca_dev);
1188 setautogain(gspca_dev);
1191 static void sd_stopN(struct gspca_dev *gspca_dev)
1193 struct sd *sd = (struct sd *) gspca_dev;
1194 static const __u8 stophv7131[] =
1195 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1196 static const __u8 stopmi0360[] =
1197 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1199 const __u8 *sn9c1xx;
1202 switch (sd->sensor) {
1203 case SENSOR_HV7131R:
1204 i2c_w8(gspca_dev, stophv7131);
1208 i2c_w8(gspca_dev, stopmi0360);
1215 /* case SENSOR_MO4000: */
1216 /* case SENSOR_OV7660: */
1219 sn9c1xx = sn_tb[(int) sd->sensor];
1220 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1221 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1222 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1223 reg_w1(gspca_dev, 0x01, data);
1224 reg_w1(gspca_dev, 0xf1, 0x01);
1227 static void sd_stop0(struct gspca_dev *gspca_dev)
1231 static void sd_close(struct gspca_dev *gspca_dev)
1235 static void do_autogain(struct gspca_dev *gspca_dev)
1237 struct sd *sd = (struct sd *) gspca_dev;
1240 __u8 luma_mean = 130;
1241 __u8 luma_delta = 20;
1243 /* Thanks S., without your advice, autobright should not work :) */
1246 if (--sd->ag_cnt >= 0)
1248 sd->ag_cnt = AG_CNT_START;
1250 delta = atomic_read(&sd->avg_lum);
1251 PDEBUG(D_FRAM, "mean lum %d", delta);
1252 if (delta < luma_mean - luma_delta ||
1253 delta > luma_mean + luma_delta) {
1254 switch (sd->sensor) {
1255 case SENSOR_HV7131R:
1256 expotimes = sd->exposure >> 8;
1257 expotimes += (luma_mean - delta) >> 4;
1260 sd->exposure = setexposure(gspca_dev,
1261 (unsigned int) (expotimes << 8));
1264 /* case SENSOR_MO4000: */
1265 /* case SENSOR_MI0360: */
1266 /* case SENSOR_OM6802: */
1267 expotimes = sd->exposure;
1268 expotimes += (luma_mean - delta) >> 6;
1271 sd->exposure = setexposure(gspca_dev,
1272 (unsigned int) expotimes);
1273 setcolors(gspca_dev);
1279 /* scan the URB packets */
1280 /* This function is run at interrupt level. */
1281 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1282 struct gspca_frame *frame, /* target */
1283 __u8 *data, /* isoc packet */
1284 int len) /* iso packet length */
1286 struct sd *sd = (struct sd *) gspca_dev;
1290 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1293 gspca_frame_add(gspca_dev, LAST_PACKET,
1294 frame, data, sof + 2);
1301 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1303 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1305 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1307 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1309 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1311 atomic_set(&sd->avg_lum, avg_lum);
1314 if (gspca_dev->last_packet_type == LAST_PACKET) {
1316 /* put the JPEG 422 header */
1317 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1319 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1322 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1324 struct sd *sd = (struct sd *) gspca_dev;
1325 __u8 hexpo, mexpo, lexpo;
1327 switch (sd->sensor) {
1328 case SENSOR_HV7131R:
1329 /* read sensor exposure */
1330 i2c_r5(gspca_dev, 0x25);
1331 return (gspca_dev->usb_buf[0] << 16)
1332 | (gspca_dev->usb_buf[1] << 8)
1333 | gspca_dev->usb_buf[2];
1335 /* read sensor exposure */
1336 i2c_r5(gspca_dev, 0x09);
1337 return (gspca_dev->usb_buf[0] << 8)
1338 | gspca_dev->usb_buf[1];
1340 /* case SENSOR_MO4000: */
1341 i2c_r5(gspca_dev, 0x0e);
1342 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1343 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1344 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1345 PDEBUG(D_CONF, "exposure %d",
1346 (hexpo << 10) | (mexpo << 2) | lexpo);
1347 return (hexpo << 10) | (mexpo << 2) | lexpo;
1350 /* case SENSOR_OV7648: * jfm: is it ok for 7648? */
1351 /* case SENSOR_OV7660: */
1352 /* read sensor exposure */
1353 i2c_r5(gspca_dev, 0x04);
1354 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1355 lexpo = gspca_dev->usb_buf[0] & 0x02;
1356 i2c_r5(gspca_dev, 0x08);
1357 mexpo = gspca_dev->usb_buf[2];
1358 return (hexpo << 10) | (mexpo << 2) | lexpo;
1364 static void getbrightness(struct gspca_dev *gspca_dev)
1366 struct sd *sd = (struct sd *) gspca_dev;
1368 /* hardcoded registers seem not readable */
1369 switch (sd->sensor) {
1370 case SENSOR_HV7131R:
1371 sd->brightness = getexposure(gspca_dev) >> 4;
1376 sd->brightness = getexposure(gspca_dev) << 4;
1381 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1383 struct sd *sd = (struct sd *) gspca_dev;
1385 sd->brightness = val;
1386 if (gspca_dev->streaming)
1387 setbrightness(gspca_dev);
1391 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1393 struct sd *sd = (struct sd *) gspca_dev;
1395 getbrightness(gspca_dev);
1396 *val = sd->brightness;
1400 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1402 struct sd *sd = (struct sd *) gspca_dev;
1405 if (gspca_dev->streaming)
1406 setcontrast(gspca_dev);
1410 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1412 struct sd *sd = (struct sd *) gspca_dev;
1414 *val = sd->contrast;
1418 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1420 struct sd *sd = (struct sd *) gspca_dev;
1423 if (gspca_dev->streaming)
1424 setcolors(gspca_dev);
1428 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1430 struct sd *sd = (struct sd *) gspca_dev;
1436 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1438 struct sd *sd = (struct sd *) gspca_dev;
1441 if (gspca_dev->streaming)
1442 setautogain(gspca_dev);
1446 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1448 struct sd *sd = (struct sd *) gspca_dev;
1450 *val = sd->autogain;
1454 /* sub-driver description */
1455 static const struct sd_desc sd_desc = {
1456 .name = MODULE_NAME,
1458 .nctrls = ARRAY_SIZE(sd_ctrls),
1459 .config = sd_config,
1465 .pkt_scan = sd_pkt_scan,
1466 .dq_callback = do_autogain,
1469 /* -- module initialisation -- */
1470 #define BSI(bridge, sensor, i2c_addr) \
1471 .driver_info = (BRIDGE_ ## bridge << 16) \
1472 | (SENSOR_ ## sensor << 8) \
1474 static const __devinitdata struct usb_device_id device_table[] = {
1475 #ifndef CONFIG_USB_SN9C102
1476 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1477 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1478 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1479 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1480 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1482 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1483 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1485 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1486 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1487 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1488 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1489 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1490 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1491 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1492 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1493 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1494 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1495 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1496 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1497 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1498 /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1499 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1500 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1501 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1502 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1504 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
1505 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1506 /* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1507 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1508 #ifndef CONFIG_USB_SN9C102
1509 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1510 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1511 /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1512 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1513 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1514 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1516 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1519 MODULE_DEVICE_TABLE(usb, device_table);
1521 /* -- device connect -- */
1522 static int sd_probe(struct usb_interface *intf,
1523 const struct usb_device_id *id)
1525 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1529 static struct usb_driver sd_driver = {
1530 .name = MODULE_NAME,
1531 .id_table = device_table,
1533 .disconnect = gspca_disconnect,
1536 /* -- module insert / remove -- */
1537 static int __init sd_mod_init(void)
1539 if (usb_register(&sd_driver) < 0)
1544 static void __exit sd_mod_exit(void)
1546 usb_deregister(&sd_driver);
1547 info("deregistered");
1550 module_init(sd_mod_init);
1551 module_exit(sd_mod_exit);