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 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28 static const char version[] = "2.1.7";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
39 unsigned int exposure;
41 unsigned short brightness;
42 unsigned char contrast;
44 unsigned char autogain;
47 #define AG_CNT_START 13
51 #define BRIDGE_SN9C102P 0
52 #define BRIDGE_SN9C105 1
53 #define BRIDGE_SN9C110 2
54 #define BRIDGE_SN9C120 3
55 #define BRIDGE_SN9C325 4
56 char sensor; /* Type of image sensor chip */
57 #define SENSOR_HV7131R 0
58 #define SENSOR_MI0360 1
59 #define SENSOR_MO4000 2
60 #define SENSOR_OV7648 3
61 #define SENSOR_OV7660 4
62 unsigned char i2c_base;
65 /* V4L2 controls supported by the driver */
66 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
73 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
75 static struct ctrl sd_ctrls[] = {
78 .id = V4L2_CID_BRIGHTNESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
84 #define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
98 #define CONTRAST_DEF 63
99 .default_value = CONTRAST_DEF,
101 .set = sd_setcontrast,
102 .get = sd_getcontrast,
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
112 #define COLOR_DEF 127
113 .default_value = COLOR_DEF,
120 .id = V4L2_CID_AUTOGAIN,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
126 #define AUTOGAIN_DEF 1
127 .default_value = AUTOGAIN_DEF,
129 .set = sd_setautogain,
130 .get = sd_getautogain,
134 static struct v4l2_pix_format vga_mode[] = {
135 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .sizeimage = 160 * 120 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
145 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
147 .sizeimage = 640 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
152 /*Data from sn9c102p+hv71331r */
153 static const __u8 sn_hv7131[] = {
154 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
155 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
156 /* rega regb regc regd rege regf reg10 reg11 */
157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
158 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
160 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
164 static const __u8 sn_mi0360[] = {
165 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
167 /* rega regb regc regd rege regf reg10 reg11 */
168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
169 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
171 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
175 static const __u8 sn_mo4000[] = {
176 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
178 /* reg9 rega regb regc regd rege regf reg10 reg11*/
179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
180 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
182 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
184 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
185 0xd3, 0xdf, 0xea, 0xf5
188 static const __u8 sn_ov7648[] = {
189 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
190 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
194 static const __u8 sn_ov7660[] = {
195 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
197 /* reg9 rega regb regc regd rege regf reg10 reg11*/
198 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
199 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
200 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
201 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
205 /* sequence specific to the sensors - !! index = SENSOR_xxx */
206 static const __u8 *sn_tb[] = {
214 static const __u8 regsn20[] = {
215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
218 static const __u8 regsn20_sn9c120[] = {
219 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
220 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
222 static const __u8 regsn20_sn9c325[] = {
223 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
224 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
227 static const __u8 reg84[] = {
228 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
229 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
230 /* 0x00, 0x00, 0x00, 0x00, 0x00 */
231 0xf7, 0x0f, 0x0a, 0x00, 0x00
233 static const __u8 reg84_sn9c120_1[] = {
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x0c, 0x00, 0x00
238 static const __u8 reg84_sn9c120_2[] = {
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x0c, 0x02, 0x3b
243 static const __u8 reg84_sn9c120_3[] = {
244 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
245 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
246 0xf5, 0x0f, 0x0c, 0x02, 0x3b
248 static const __u8 reg84_sn9c325[] = {
249 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
250 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
251 0xf8, 0x0f, 0x00, 0x00, 0x00
254 static const __u8 hv7131r_sensor_init[][8] = {
255 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
256 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
258 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
263 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
268 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
269 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
270 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
272 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
285 static const __u8 mi0360_sensor_init[][8] = {
286 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
287 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
290 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
291 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
292 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
308 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
309 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
311 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
313 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
315 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
318 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
320 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
323 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
324 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
326 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
327 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
328 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
331 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
332 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
333 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
334 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
335 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
336 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
339 static const __u8 mo4000_sensor_init[][8] = {
340 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
362 static const __u8 ov7660_sensor_init[][8] = {
363 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
365 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
366 /* Outformat ?? rawRGB */
367 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
368 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
369 /* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
370 /* GAIN BLUE RED VREF */
371 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
372 /* COM 1 BAVE GEAVE AECHH */
373 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
374 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
375 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
376 /* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
377 /* AECH CLKRC COM7 COM8 */
378 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
379 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
380 /* HSTART HSTOP VSTRT VSTOP */
381 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
382 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
383 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
384 /* BOS GBOS GROS ROS (BGGR offset) */
385 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
386 /* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
387 /* AEW AEB VPT BBIAS */
388 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
389 /* GbBIAS RSVD EXHCH EXHCL */
390 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
391 /* RBIAS ADVFL ASDVFH YAVE */
392 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
393 /* HSYST HSYEN HREF */
394 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
395 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
396 /* ADC ACOM OFON TSLB */
397 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
398 /* COM11 COM12 COM13 COM14 */
399 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
400 /* EDGE COM15 COM16 COM17 */
401 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
402 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
404 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
405 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
406 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
407 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
408 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
409 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
410 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
411 /* LCC1 LCC2 LCC3 LCC4 */
412 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
413 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
414 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
415 /* band gap reference [0..3] DBLV */
416 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
420 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
421 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
422 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
423 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
424 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
425 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
426 /****** (some exchanges in the win trace) ******/
427 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
428 /* bits[3..0]reserved */
429 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
431 /* VREF vertical frame ctrl */
432 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
433 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
434 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
436 /* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
437 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
438 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
439 /****** (some exchanges in the win trace) ******/
440 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
441 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
442 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
445 /****** (some exchanges in the win trace) ******/
446 /**********startsensor KO if changed !!****/
447 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
450 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
451 /* here may start the isoc exchanges */
454 /* reg0x04 reg0x07 reg 0x10 */
455 /* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
457 static const __u8 ov7648_sensor_init[][8] = {
458 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
459 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
460 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
461 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
462 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
464 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
465 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
466 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
467 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
468 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
469 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
471 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
472 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
473 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
474 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
475 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
476 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
477 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
478 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
479 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
480 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
481 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
482 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
483 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
484 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
485 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
486 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
487 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
488 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
489 * This is currently setting a
490 * blue tint, and some things more , i leave it here for future test if
491 * somene is having problems with color on this sensor
492 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
493 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
497 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
498 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
502 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
503 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
504 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
505 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
506 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
507 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
508 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
509 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
513 static const __u8 qtable4[] = {
514 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
515 0x06, 0x08, 0x0A, 0x11,
516 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
517 0x19, 0x19, 0x17, 0x15,
518 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
519 0x21, 0x2E, 0x21, 0x23,
520 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
521 0x25, 0x29, 0x2C, 0x29,
522 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
523 0x17, 0x1B, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
527 0x29, 0x29, 0x29, 0x29,
528 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
529 0x29, 0x29, 0x29, 0x29
532 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
533 static void reg_r(struct gspca_dev *gspca_dev,
534 __u16 value, int len)
536 usb_control_msg(gspca_dev->dev,
537 usb_rcvctrlpipe(gspca_dev->dev, 0),
539 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
541 gspca_dev->usb_buf, len,
543 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
546 static void reg_w1(struct gspca_dev *gspca_dev,
550 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
551 gspca_dev->usb_buf[0] = data;
552 usb_control_msg(gspca_dev->dev,
553 usb_sndctrlpipe(gspca_dev->dev, 0),
555 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
558 gspca_dev->usb_buf, 1,
561 static void reg_w(struct gspca_dev *gspca_dev,
566 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
567 value, buffer[0], buffer[1]);
568 if (len <= sizeof gspca_dev->usb_buf) {
569 memcpy(gspca_dev->usb_buf, buffer, len);
570 usb_control_msg(gspca_dev->dev,
571 usb_sndctrlpipe(gspca_dev->dev, 0),
573 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
575 gspca_dev->usb_buf, len,
580 tmpbuf = kmalloc(len, GFP_KERNEL);
581 memcpy(tmpbuf, buffer, len);
582 usb_control_msg(gspca_dev->dev,
583 usb_sndctrlpipe(gspca_dev->dev, 0),
585 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
593 /* I2C write 1 byte */
594 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
596 struct sd *sd = (struct sd *) gspca_dev;
598 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
599 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
600 gspca_dev->usb_buf[1] = sd->i2c_base;
601 gspca_dev->usb_buf[2] = reg;
602 gspca_dev->usb_buf[3] = val;
603 gspca_dev->usb_buf[4] = 0;
604 gspca_dev->usb_buf[5] = 0;
605 gspca_dev->usb_buf[6] = 0;
606 gspca_dev->usb_buf[7] = 0x10;
607 usb_control_msg(gspca_dev->dev,
608 usb_sndctrlpipe(gspca_dev->dev, 0),
610 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
611 0x08, /* value = i2c */
613 gspca_dev->usb_buf, 8,
617 /* I2C write 8 bytes */
618 static void i2c_w8(struct gspca_dev *gspca_dev,
621 memcpy(gspca_dev->usb_buf, buffer, 8);
622 usb_control_msg(gspca_dev->dev,
623 usb_sndctrlpipe(gspca_dev->dev, 0),
625 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
626 0x08, 0, /* value, index */
627 gspca_dev->usb_buf, 8,
631 /* read 5 bytes in gspca_dev->usb_buf */
632 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
634 struct sd *sd = (struct sd *) gspca_dev;
637 mode[0] = 0x81 | 0x10;
638 mode[1] = sd->i2c_base;
645 i2c_w8(gspca_dev, mode);
647 mode[0] = 0x81 | (5 << 4) | 0x02;
649 i2c_w8(gspca_dev, mode);
651 reg_r(gspca_dev, 0x0a, 5);
654 static int probesensor(struct gspca_dev *gspca_dev)
656 struct sd *sd = (struct sd *) gspca_dev;
658 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
660 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
662 i2c_r5(gspca_dev, 0); /* read sensor id */
663 if (gspca_dev->usb_buf[0] == 0x02
664 && gspca_dev->usb_buf[1] == 0x09
665 && gspca_dev->usb_buf[2] == 0x01
666 && gspca_dev->usb_buf[3] == 0x00
667 && gspca_dev->usb_buf[4] == 0x00) {
668 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
669 sd->sensor = SENSOR_HV7131R;
670 return SENSOR_HV7131R;
672 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
673 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
674 gspca_dev->usb_buf[2]);
675 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
679 static int configure_gpio(struct gspca_dev *gspca_dev,
682 struct sd *sd = (struct sd *) gspca_dev;
684 static const __u8 reg9a_def[] =
685 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
686 static const __u8 reg9a_sn9c120[] = /* from win trace */
687 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
688 static const __u8 reg9a_sn9c325[] =
689 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
691 reg_w1(gspca_dev, 0xf1, 0x00);
692 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
695 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
696 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
697 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
698 switch (sd->bridge) {
700 reg9a = reg9a_sn9c325;
703 reg9a = reg9a_sn9c120;
709 reg_w(gspca_dev, 0x9a, reg9a, 6);
711 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
713 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
715 switch (sd->bridge) {
716 case BRIDGE_SN9C120: /* from win trace */
717 reg_w1(gspca_dev, 0x01, 0x61);
718 reg_w1(gspca_dev, 0x17, 0x20);
719 reg_w1(gspca_dev, 0x01, 0x60);
722 reg_w1(gspca_dev, 0x01, 0x43);
723 reg_w1(gspca_dev, 0x17, 0xae);
724 reg_w1(gspca_dev, 0x01, 0x42);
727 reg_w1(gspca_dev, 0x01, 0x43);
728 reg_w1(gspca_dev, 0x17, 0x61);
729 reg_w1(gspca_dev, 0x01, 0x42);
732 if (sd->sensor == SENSOR_HV7131R) {
733 if (probesensor(gspca_dev) < 0)
739 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
742 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
743 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
745 while (hv7131r_sensor_init[i][0]) {
746 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
749 i2c_w8(gspca_dev, SetSensorClk);
752 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
756 while (mi0360_sensor_init[i][0]) {
757 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
762 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
766 while (mo4000_sensor_init[i][0]) {
767 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
772 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
776 while (ov7648_sensor_init[i][0]) {
777 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
782 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
786 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
789 while (ov7660_sensor_init[i][0]) {
790 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
795 /* this function is called at probe time */
796 static int sd_config(struct gspca_dev *gspca_dev,
797 const struct usb_device_id *id)
799 struct sd *sd = (struct sd *) gspca_dev;
803 product = id->idProduct;
805 switch (id->idVendor) {
806 case 0x0458: /* Genius */
807 /* switch (product) {
809 sd->bridge = BRIDGE_SN9C120;
810 sd->sensor = SENSOR_MI0360;
816 /* switch (product) {
819 sd->bridge = BRIDGE_SN9C105;
820 sd->sensor = SENSOR_OV7660;
825 case 0x0471: /* Philips */
826 /* switch (product) {
830 sd->bridge = BRIDGE_SN9C105;
831 sd->sensor = SENSOR_MI0360;
836 case 0x0c45: /* Sonix */
839 sd->bridge = BRIDGE_SN9C102P;
840 /* sd->sensor = SENSOR_MI0360; * from BW600.inf */
841 /*fixme: MI0360 base=5d ? */
842 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
845 /* case 0x607a: * from BW600.inf
846 sd->bridge = BRIDGE_SN9C102P;
847 sd->sensor = SENSOR_OV7648;
851 sd->bridge = BRIDGE_SN9C102P;
852 sd->sensor = SENSOR_HV7131R;
855 /* case 0x607e: * from BW600.inf
856 sd->bridge = BRIDGE_SN9C102P;
857 sd->sensor = SENSOR_OV7630;
861 sd->bridge = BRIDGE_SN9C105;
862 sd->sensor = SENSOR_MI0360;
865 /* case 0x60c8: * from BW600.inf
866 sd->bridge = BRIDGE_SN9C105;
867 sd->sensor = SENSOR_OM6801;
870 /* case 0x60cc: * from BW600.inf
871 sd->bridge = BRIDGE_SN9C105;
872 sd->sensor = SENSOR_HV7131GP;
876 sd->bridge = BRIDGE_SN9C105;
877 sd->sensor = SENSOR_MO4000;
880 /* case 0x60ef: * from BW600.inf
881 sd->bridge = BRIDGE_SN9C105;
882 sd->sensor = SENSOR_ICM105C;
885 /* case 0x60fa: * from BW600.inf
886 sd->bridge = BRIDGE_SN9C105;
887 sd->sensor = SENSOR_OV7648;
891 sd->bridge = BRIDGE_SN9C105;
892 sd->sensor = SENSOR_OV7660;
896 sd->bridge = BRIDGE_SN9C105;
897 sd->sensor = SENSOR_HV7131R;
900 /* case 0x60fe: * from BW600.inf
901 sd->bridge = BRIDGE_SN9C105;
902 sd->sensor = SENSOR_OV7630;
905 /* case 0x6108: * from BW600.inf
906 sd->bridge = BRIDGE_SN9C120;
907 sd->sensor = SENSOR_OM6801;
910 /* case 0x6122: * from BW600.inf
911 sd->bridge = BRIDGE_SN9C110;
912 sd->sensor = SENSOR_ICM105C;
916 /* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
917 sd->bridge = BRIDGE_SN9C325;
918 sd->sensor = SENSOR_OV7648;
920 /*fixme: sensor_init has base = 00 et 6e!*/
922 /* case 0x6123: * from BW600.inf
923 sd->bridge = BRIDGE_SN9C110;
924 sd->sensor = SENSOR_SanyoCCD;
928 sd->bridge = BRIDGE_SN9C110;
929 sd->sensor = SENSOR_MO4000;
932 /* case 0x612e: * from BW600.inf
933 sd->bridge = BRIDGE_SN9C110;
934 sd->sensor = SENSOR_OV7630;
937 /* case 0x612f: * from BW600.inf
938 sd->bridge = BRIDGE_SN9C110;
939 sd->sensor = SENSOR_ICM105C;
943 sd->bridge = BRIDGE_SN9C120;
944 sd->sensor = SENSOR_MI0360;
948 sd->bridge = BRIDGE_SN9C120;
949 sd->sensor = SENSOR_MO4000;
952 /* case 0x613a: * from BW600.inf
953 sd->bridge = BRIDGE_SN9C120;
954 sd->sensor = SENSOR_OV7648;
958 sd->bridge = BRIDGE_SN9C120;
959 sd->sensor = SENSOR_OV7660;
963 sd->bridge = BRIDGE_SN9C120;
964 sd->sensor = SENSOR_HV7131R;
967 /* case 0x613e: * from BW600.inf
968 sd->bridge = BRIDGE_SN9C120;
969 sd->sensor = SENSOR_OV7630;
975 if (sd->sensor < 0) {
976 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
977 id->idVendor, product);
981 cam = &gspca_dev->cam;
982 cam->dev_name = (char *) id->driver_info;
984 cam->cam_mode = vga_mode;
985 cam->nmodes = ARRAY_SIZE(vga_mode);
987 sd->qindex = 4; /* set the quantization table */
988 sd->brightness = BRIGHTNESS_DEF;
989 sd->contrast = CONTRAST_DEF;
990 sd->colors = COLOR_DEF;
991 sd->autogain = AUTOGAIN_DEF;
995 /* this function is called at open time */
996 static int sd_open(struct gspca_dev *gspca_dev)
998 struct sd *sd = (struct sd *) gspca_dev;
999 /* const __u8 *sn9c1xx; */
1000 __u8 regGpio[] = { 0x29, 0x74 };
1003 /* setup a selector by bridge */
1004 reg_w1(gspca_dev, 0xf1, 0x01);
1005 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
1006 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1007 reg_r(gspca_dev, 0x00, 1);
1008 regF1 = gspca_dev->usb_buf[0];
1009 switch (sd->bridge) {
1010 case BRIDGE_SN9C102P:
1013 reg_w1(gspca_dev, 0x02, regGpio[1]);
1015 case BRIDGE_SN9C105:
1018 reg_w(gspca_dev, 0x02, regGpio, 2);
1020 case BRIDGE_SN9C120:
1024 reg_w(gspca_dev, 0x02, regGpio, 2);
1027 /* case BRIDGE_SN9C110: */
1028 /* case BRIDGE_SN9C325: */
1031 reg_w1(gspca_dev, 0x02, 0x62);
1035 reg_w1(gspca_dev, 0xf1, 0x01);
1040 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1043 struct sd *sd = (struct sd *) gspca_dev;
1044 static const __u8 doit[] = /* update sensor */
1045 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1046 static const __u8 sensorgo[] = /* sensor on */
1047 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1048 static const __u8 gainMo[] =
1049 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1051 switch (sd->sensor) {
1052 case SENSOR_HV7131R: {
1054 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1056 Expodoit[3] = expo >> 16;
1057 Expodoit[4] = expo >> 8;
1059 i2c_w8(gspca_dev, Expodoit);
1062 case SENSOR_MI0360: {
1063 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1064 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1068 else if (expo < 0x0001)
1070 expoMi[3] = expo >> 8;
1072 i2c_w8(gspca_dev, expoMi);
1073 i2c_w8(gspca_dev, doit);
1074 i2c_w8(gspca_dev, sensorgo);
1077 case SENSOR_MO4000: {
1079 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1081 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1085 else if (expo < 0x0001)
1087 expoMof[3] = (expo & 0x03fc) >> 2;
1088 i2c_w8(gspca_dev, expoMof);
1089 expoMo10[3] = ((expo & 0x1c00) >> 10)
1090 | ((expo & 0x0003) << 4);
1091 i2c_w8(gspca_dev, expoMo10);
1092 i2c_w8(gspca_dev, gainMo);
1093 PDEBUG(D_CONF, "set exposure %d",
1094 ((expoMo10[3] & 0x07) << 10)
1096 | ((expoMo10[3] & 0x30) >> 4));
1103 static void setbrightness(struct gspca_dev *gspca_dev)
1105 struct sd *sd = (struct sd *) gspca_dev;
1109 switch (sd->sensor) {
1110 case SENSOR_HV7131R:
1111 expo = sd->brightness << 4;
1112 if (expo > 0x002dc6c0)
1114 else if (expo < 0x02a0)
1116 sd->exposure = setexposure(gspca_dev, expo);
1119 expo = sd->brightness >> 4;
1120 sd->exposure = setexposure(gspca_dev, expo);
1123 expo = sd->brightness >> 4;
1124 sd->exposure = setexposure(gspca_dev, expo);
1130 k2 = sd->brightness >> 10;
1131 reg_w1(gspca_dev, 0x96, k2);
1134 static void setcontrast(struct gspca_dev *gspca_dev)
1136 struct sd *sd = (struct sd *) gspca_dev;
1138 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1140 if (sd->sensor == SENSOR_OV7660)
1144 contrast[0] = (k2 + 1) >> 1;
1145 contrast[4] = (k2 + 1) / 5;
1146 reg_w(gspca_dev, 0x84, contrast, 6);
1149 static void setcolors(struct gspca_dev *gspca_dev)
1151 struct sd *sd = (struct sd *) gspca_dev;
1155 colour = sd->colors - 128;
1157 data = (colour + 32) & 0x7f; /* blue */
1159 data = (-colour + 32) & 0x7f; /* red */
1160 reg_w1(gspca_dev, 0x05, data);
1163 /* -- start the camera -- */
1164 static void sd_start(struct gspca_dev *gspca_dev)
1166 struct sd *sd = (struct sd *) gspca_dev;
1171 const __u8 *sn9c1xx;
1173 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1174 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1175 static const __u8 CA_sn9c120[] =
1176 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1177 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1178 static const __u8 CE_sn9c325[] =
1179 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1181 sn9c1xx = sn_tb[(int) sd->sensor];
1182 configure_gpio(gspca_dev, sn9c1xx);
1184 /*fixme:jfm this sequence should appear at end of sd_start */
1186 reg_w1(gspca_dev, 0x01, 0x44); */
1187 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1188 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1189 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1190 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1191 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1192 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1193 reg_w1(gspca_dev, 0xd3, 0x50);
1194 reg_w1(gspca_dev, 0xc6, 0x00);
1195 reg_w1(gspca_dev, 0xc7, 0x00);
1196 reg_w1(gspca_dev, 0xc8, 0x50);
1197 reg_w1(gspca_dev, 0xc9, 0x3c);
1198 /*fixme:jfm end of ending sequence */
1199 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1200 switch (sd->bridge) {
1201 case BRIDGE_SN9C325:
1204 case BRIDGE_SN9C120:
1211 reg_w1(gspca_dev, 0x17, data);
1212 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1213 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1214 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1215 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1216 switch (sd->bridge) {
1217 case BRIDGE_SN9C325:
1218 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1219 sizeof regsn20_sn9c325);
1220 for (i = 0; i < 8; i++)
1221 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1222 sizeof reg84_sn9c325);
1223 reg_w1(gspca_dev, 0x9a, 0x0a);
1224 reg_w1(gspca_dev, 0x99, 0x60);
1226 case BRIDGE_SN9C120:
1227 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1228 sizeof regsn20_sn9c120);
1229 for (i = 0; i < 2; i++)
1230 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1231 sizeof reg84_sn9c120_1);
1232 for (i = 0; i < 6; i++)
1233 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1234 sizeof reg84_sn9c120_2);
1235 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1236 sizeof reg84_sn9c120_3);
1237 reg_w1(gspca_dev, 0x9a, 0x05);
1238 reg_w1(gspca_dev, 0x99, 0x5b);
1241 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1242 for (i = 0; i < 8; i++)
1243 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1244 reg_w1(gspca_dev, 0x9a, 0x08);
1245 reg_w1(gspca_dev, 0x99, 0x59);
1249 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1251 reg1 = 0x46; /* 320 clk 48Mhz */
1253 reg1 = 0x06; /* 640 clk 24Mz */
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 hv7131R_InitSensor(gspca_dev);
1260 mi0360_InitSensor(gspca_dev);
1263 mo4000_InitSensor(gspca_dev);
1265 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1266 reg1 = 0x06; /* clk 24Mz */
1268 reg17 = 0x22; /* 640 MCKSIZE */
1269 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1273 ov7648_InitSensor(gspca_dev);
1282 /* case SENSOR_OV7660: */
1283 ov7660_InitSensor(gspca_dev);
1285 /* reg17 = 0x21; * 320 */
1287 /* reg1 = 0x46; (done) */
1289 reg17 = 0xa2; /* 640 */
1294 reg_w(gspca_dev, 0xc0, C0, 6);
1295 switch (sd->bridge) {
1296 case BRIDGE_SN9C120: /*jfm ?? */
1297 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1300 reg_w(gspca_dev, 0xca, CA, 4);
1303 switch (sd->bridge) {
1304 case BRIDGE_SN9C120: /*jfm ?? */
1305 case BRIDGE_SN9C325:
1306 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1309 reg_w(gspca_dev, 0xce, CE, 4);
1310 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1314 /* here change size mode 0 -> VGA; 1 -> CIF */
1315 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1316 reg_w1(gspca_dev, 0x18, data);
1318 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1319 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1321 data = sn9c1xx[0x18] | (mode << 4);
1322 reg_w1(gspca_dev, 0x18, data);
1324 reg_w1(gspca_dev, 0x17, reg17);
1325 reg_w1(gspca_dev, 0x01, reg1);
1326 setbrightness(gspca_dev);
1327 setcontrast(gspca_dev);
1330 static void sd_stopN(struct gspca_dev *gspca_dev)
1332 struct sd *sd = (struct sd *) gspca_dev;
1333 static const __u8 stophv7131[] =
1334 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1335 static const __u8 stopmi0360[] =
1336 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1338 const __u8 *sn9c1xx;
1341 switch (sd->sensor) {
1342 case SENSOR_HV7131R:
1343 i2c_w8(gspca_dev, stophv7131);
1347 i2c_w8(gspca_dev, stopmi0360);
1356 /* case SENSOR_OV7660: */
1359 sn9c1xx = sn_tb[(int) sd->sensor];
1360 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1361 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1362 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1363 reg_w1(gspca_dev, 0x01, data);
1364 reg_w1(gspca_dev, 0xf1, 0x01);
1367 static void sd_stop0(struct gspca_dev *gspca_dev)
1371 static void sd_close(struct gspca_dev *gspca_dev)
1375 static void setautogain(struct gspca_dev *gspca_dev)
1377 struct sd *sd = (struct sd *) gspca_dev;
1378 /* Thanks S., without your advice, autobright should not work :) */
1381 __u8 luma_mean = 130;
1382 __u8 luma_delta = 20;
1384 delta = sd->avg_lum;
1385 if (delta < luma_mean - luma_delta ||
1386 delta > luma_mean + luma_delta) {
1387 switch (sd->sensor) {
1388 case SENSOR_HV7131R:
1389 expotimes = sd->exposure >> 8;
1390 expotimes += (luma_mean - delta) >> 4;
1393 sd->exposure = setexposure(gspca_dev,
1394 (unsigned int) (expotimes << 8));
1398 expotimes = sd->exposure;
1399 expotimes += (luma_mean - delta) >> 6;
1402 sd->exposure = setexposure(gspca_dev,
1403 (unsigned int) expotimes);
1404 setcolors(gspca_dev);
1410 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1411 struct gspca_frame *frame, /* target */
1412 __u8 *data, /* isoc packet */
1413 int len) /* iso packet length */
1415 struct sd *sd = (struct sd *) gspca_dev;
1419 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1422 gspca_frame_add(gspca_dev, LAST_PACKET,
1423 frame, data, sof + 2);
1426 if (--sd->ag_cnt >= 0)
1428 sd->ag_cnt = AG_CNT_START;
1433 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1435 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1437 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1439 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1441 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1443 sd->avg_lum = avg_lum;
1444 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1445 setautogain(gspca_dev);
1448 if (gspca_dev->last_packet_type == LAST_PACKET) {
1450 /* put the JPEG 422 header */
1451 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1453 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1456 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1458 struct sd *sd = (struct sd *) gspca_dev;
1459 __u8 hexpo, mexpo, lexpo;
1461 switch (sd->sensor) {
1462 case SENSOR_HV7131R:
1463 /* read sensor exposure */
1464 i2c_r5(gspca_dev, 0x25);
1465 return (gspca_dev->usb_buf[0] << 16)
1466 | (gspca_dev->usb_buf[1] << 8)
1467 | gspca_dev->usb_buf[2];
1469 /* read sensor exposure */
1470 i2c_r5(gspca_dev, 0x09);
1471 return (gspca_dev->usb_buf[0] << 8)
1472 | gspca_dev->usb_buf[1];
1474 i2c_r5(gspca_dev, 0x0e);
1475 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1476 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1477 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1478 PDEBUG(D_CONF, "exposure %d",
1479 (hexpo << 10) | (mexpo << 2) | lexpo);
1480 return (hexpo << 10) | (mexpo << 2) | lexpo;
1482 /* case SENSOR_OV7660: */
1483 /* read sensor exposure */
1484 i2c_r5(gspca_dev, 0x04);
1485 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1486 lexpo = gspca_dev->usb_buf[0] & 0x02;
1487 i2c_r5(gspca_dev, 0x08);
1488 mexpo = gspca_dev->usb_buf[2];
1489 return (hexpo << 10) | (mexpo << 2) | lexpo;
1493 static void getbrightness(struct gspca_dev *gspca_dev)
1495 struct sd *sd = (struct sd *) gspca_dev;
1497 /* hardcoded registers seem not readable */
1498 switch (sd->sensor) {
1499 case SENSOR_HV7131R:
1500 /* sd->brightness = 0x7fff; */
1501 sd->brightness = getexposure(gspca_dev) >> 4;
1504 sd->brightness = getexposure(gspca_dev) << 4;
1507 /* sd->brightness = 0x1fff; */
1508 sd->brightness = getexposure(gspca_dev) << 4;
1513 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1515 struct sd *sd = (struct sd *) gspca_dev;
1517 sd->brightness = val;
1518 if (gspca_dev->streaming)
1519 setbrightness(gspca_dev);
1523 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1525 struct sd *sd = (struct sd *) gspca_dev;
1527 getbrightness(gspca_dev);
1528 *val = sd->brightness;
1532 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1534 struct sd *sd = (struct sd *) gspca_dev;
1537 if (gspca_dev->streaming)
1538 setcontrast(gspca_dev);
1542 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1544 struct sd *sd = (struct sd *) gspca_dev;
1546 *val = sd->contrast;
1550 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1552 struct sd *sd = (struct sd *) gspca_dev;
1555 if (gspca_dev->streaming)
1556 setcolors(gspca_dev);
1560 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1562 struct sd *sd = (struct sd *) gspca_dev;
1568 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1570 struct sd *sd = (struct sd *) gspca_dev;
1574 sd->ag_cnt = AG_CNT_START;
1580 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1582 struct sd *sd = (struct sd *) gspca_dev;
1584 *val = sd->autogain;
1588 /* sub-driver description */
1589 static const struct sd_desc sd_desc = {
1590 .name = MODULE_NAME,
1592 .nctrls = ARRAY_SIZE(sd_ctrls),
1593 .config = sd_config,
1599 .pkt_scan = sd_pkt_scan,
1602 /* -- module initialisation -- */
1603 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1604 static const __devinitdata struct usb_device_id device_table[] = {
1605 #ifndef CONFIG_USB_SN9C102
1606 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1607 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1608 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1609 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1610 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1612 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1613 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1614 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1615 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1616 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1617 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1618 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1619 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1620 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1621 #ifndef CONFIG_USB_SN9C102
1622 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1623 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1624 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1625 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1629 MODULE_DEVICE_TABLE(usb, device_table);
1631 /* -- device connect -- */
1632 static int sd_probe(struct usb_interface *intf,
1633 const struct usb_device_id *id)
1635 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1639 static struct usb_driver sd_driver = {
1640 .name = MODULE_NAME,
1641 .id_table = device_table,
1643 .disconnect = gspca_disconnect,
1646 /* -- module insert / remove -- */
1647 static int __init sd_mod_init(void)
1649 if (usb_register(&sd_driver) < 0)
1651 info("v%s registered", version);
1654 static void __exit sd_mod_exit(void)
1656 usb_deregister(&sd_driver);
1657 info("deregistered");
1660 module_init(sd_mod_init);
1661 module_exit(sd_mod_exit);