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_OV7648 3
58 #define SENSOR_OV7660 4
59 unsigned char i2c_base;
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72 static struct ctrl sd_ctrls[] = {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
81 #define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
95 #define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
109 #define COLOR_DEF 127
110 .default_value = COLOR_DEF,
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 #define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
126 .set = sd_setautogain,
127 .get = sd_getautogain,
131 static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
149 /*Data from sn9c102p+hv71331r */
150 static const __u8 sn_hv7131[] = {
151 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
152 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
153 /* rega regb regc regd rege regf reg10 reg11 */
154 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
155 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
156 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
157 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161 static const __u8 sn_mi0360[] = {
162 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
164 /* rega regb regc regd rege regf reg10 reg11 */
165 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
166 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
167 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
168 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
172 static const __u8 sn_mo4000[] = {
173 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
174 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
175 /* reg9 rega regb regc regd rege regf reg10 reg11*/
176 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
177 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
178 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
179 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
181 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
182 0xd3, 0xdf, 0xea, 0xf5
185 static const __u8 sn_ov7648[] = {
186 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
187 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
188 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
191 static const __u8 sn_ov7660[] = {
192 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
193 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
194 /* reg9 rega regb regc regd rege regf reg10 reg11*/
195 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
196 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
197 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
198 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
202 /* sequence specific to the sensors - !! index = SENSOR_xxx */
203 static const __u8 *sn_tb[] = {
211 static const __u8 regsn20[] = {
212 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
213 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
215 static const __u8 regsn20_sn9c120[] = {
216 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
217 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
219 static const __u8 regsn20_sn9c325[] = {
220 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
221 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
224 static const __u8 reg84[] = {
225 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
226 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
227 /* 0x00, 0x00, 0x00, 0x00, 0x00 */
228 0xf7, 0x0f, 0x0a, 0x00, 0x00
230 static const __u8 reg84_sn9c120_1[] = {
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x0c, 0x00, 0x00
235 static const __u8 reg84_sn9c120_2[] = {
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x0c, 0x02, 0x3b
240 static const __u8 reg84_sn9c120_3[] = {
241 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
242 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
243 0xf5, 0x0f, 0x0c, 0x02, 0x3b
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 const __u8 ov7660_sensor_init[][8] = {
360 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
363 /* Outformat ?? rawRGB */
364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
366 /* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
367 /* GAIN BLUE RED VREF */
368 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
369 /* COM 1 BAVE GEAVE AECHH */
370 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
371 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
372 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
373 /* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
374 /* AECH CLKRC COM7 COM8 */
375 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
376 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
377 /* HSTART HSTOP VSTRT VSTOP */
378 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
379 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
380 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
381 /* BOS GBOS GROS ROS (BGGR offset) */
382 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
383 /* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
384 /* AEW AEB VPT BBIAS */
385 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
386 /* GbBIAS RSVD EXHCH EXHCL */
387 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
388 /* RBIAS ADVFL ASDVFH YAVE */
389 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
390 /* HSYST HSYEN HREF */
391 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
392 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
393 /* ADC ACOM OFON TSLB */
394 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
395 /* COM11 COM12 COM13 COM14 */
396 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
397 /* EDGE COM15 COM16 COM17 */
398 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
400 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
402 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
403 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
404 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
406 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
408 /* LCC1 LCC2 LCC3 LCC4 */
409 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
410 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
411 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
412 /* band gap reference [0..3] DBLV */
413 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
420 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
421 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
422 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
423 /****** (some exchanges in the win trace) ******/
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 /* bits[3..0]reserved */
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
428 /* VREF vertical frame ctrl */
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
431 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
433 /* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
434 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
435 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
436 /****** (some exchanges in the win trace) ******/
437 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
438 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
439 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
441 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
442 /****** (some exchanges in the win trace) ******/
443 /**********startsensor KO if changed !!****/
444 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
448 /* here may start the isoc exchanges */
451 /* reg0x04 reg0x07 reg 0x10 */
452 /* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
454 static const __u8 ov7648_sensor_init[][8] = {
455 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
456 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
459 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
460 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
461 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
462 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
464 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
465 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
466 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
467 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
468 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
469 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
471 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
472 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
473 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
474 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
475 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
476 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
477 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
478 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
479 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
480 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
481 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
482 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
483 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
484 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
486 * This is currently setting a
487 * blue tint, and some things more , i leave it here for future test if
488 * somene is having problems with color on this sensor
489 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
492 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
502 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
503 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
504 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
505 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
506 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
510 static const __u8 qtable4[] = {
511 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
512 0x06, 0x08, 0x0A, 0x11,
513 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
514 0x19, 0x19, 0x17, 0x15,
515 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
516 0x21, 0x2E, 0x21, 0x23,
517 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
518 0x25, 0x29, 0x2C, 0x29,
519 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
520 0x17, 0x1B, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29
529 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
530 static void reg_r(struct gspca_dev *gspca_dev,
531 __u16 value, int len)
533 usb_control_msg(gspca_dev->dev,
534 usb_rcvctrlpipe(gspca_dev->dev, 0),
536 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
538 gspca_dev->usb_buf, len,
540 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
543 static void reg_w1(struct gspca_dev *gspca_dev,
547 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
548 gspca_dev->usb_buf[0] = data;
549 usb_control_msg(gspca_dev->dev,
550 usb_sndctrlpipe(gspca_dev->dev, 0),
552 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
555 gspca_dev->usb_buf, 1,
558 static void reg_w(struct gspca_dev *gspca_dev,
563 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
564 value, buffer[0], buffer[1]);
565 if (len <= sizeof gspca_dev->usb_buf) {
566 memcpy(gspca_dev->usb_buf, buffer, len);
567 usb_control_msg(gspca_dev->dev,
568 usb_sndctrlpipe(gspca_dev->dev, 0),
570 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
572 gspca_dev->usb_buf, len,
577 tmpbuf = kmalloc(len, GFP_KERNEL);
578 memcpy(tmpbuf, buffer, len);
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
590 /* I2C write 1 byte */
591 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
593 struct sd *sd = (struct sd *) gspca_dev;
595 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
596 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
597 gspca_dev->usb_buf[1] = sd->i2c_base;
598 gspca_dev->usb_buf[2] = reg;
599 gspca_dev->usb_buf[3] = val;
600 gspca_dev->usb_buf[4] = 0;
601 gspca_dev->usb_buf[5] = 0;
602 gspca_dev->usb_buf[6] = 0;
603 gspca_dev->usb_buf[7] = 0x10;
604 usb_control_msg(gspca_dev->dev,
605 usb_sndctrlpipe(gspca_dev->dev, 0),
607 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
608 0x08, /* value = i2c */
610 gspca_dev->usb_buf, 8,
614 /* I2C write 8 bytes */
615 static void i2c_w8(struct gspca_dev *gspca_dev,
618 memcpy(gspca_dev->usb_buf, buffer, 8);
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
623 0x08, 0, /* value, index */
624 gspca_dev->usb_buf, 8,
628 /* read 5 bytes in gspca_dev->usb_buf */
629 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
631 struct sd *sd = (struct sd *) gspca_dev;
634 mode[0] = 0x81 | 0x10;
635 mode[1] = sd->i2c_base;
642 i2c_w8(gspca_dev, mode);
644 mode[0] = 0x81 | (5 << 4) | 0x02;
646 i2c_w8(gspca_dev, mode);
648 reg_r(gspca_dev, 0x0a, 5);
651 static int probesensor(struct gspca_dev *gspca_dev)
653 struct sd *sd = (struct sd *) gspca_dev;
655 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
657 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
659 i2c_r5(gspca_dev, 0); /* read sensor id */
660 if (gspca_dev->usb_buf[0] == 0x02
661 && gspca_dev->usb_buf[1] == 0x09
662 && gspca_dev->usb_buf[2] == 0x01
663 && gspca_dev->usb_buf[3] == 0x00
664 && gspca_dev->usb_buf[4] == 0x00) {
665 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
666 sd->sensor = SENSOR_HV7131R;
667 return SENSOR_HV7131R;
669 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
670 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
671 gspca_dev->usb_buf[2]);
672 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
676 static int configure_gpio(struct gspca_dev *gspca_dev,
679 struct sd *sd = (struct sd *) gspca_dev;
681 static const __u8 reg9a_def[] =
682 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
683 static const __u8 reg9a_sn9c120[] = /* from win trace */
684 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
685 static const __u8 reg9a_sn9c325[] =
686 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
688 reg_w1(gspca_dev, 0xf1, 0x00);
689 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
692 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
693 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
694 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
695 switch (sd->bridge) {
697 reg9a = reg9a_sn9c325;
700 reg9a = reg9a_sn9c120;
706 reg_w(gspca_dev, 0x9a, reg9a, 6);
708 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
710 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
712 switch (sd->bridge) {
713 case BRIDGE_SN9C120: /* from win trace */
714 reg_w1(gspca_dev, 0x01, 0x61);
715 reg_w1(gspca_dev, 0x17, 0x20);
716 reg_w1(gspca_dev, 0x01, 0x60);
719 reg_w1(gspca_dev, 0x01, 0x43);
720 reg_w1(gspca_dev, 0x17, 0xae);
721 reg_w1(gspca_dev, 0x01, 0x42);
724 reg_w1(gspca_dev, 0x01, 0x43);
725 reg_w1(gspca_dev, 0x17, 0x61);
726 reg_w1(gspca_dev, 0x01, 0x42);
729 if (sd->sensor == SENSOR_HV7131R) {
730 if (probesensor(gspca_dev) < 0)
736 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
739 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
740 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
742 while (hv7131r_sensor_init[i][0]) {
743 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
746 i2c_w8(gspca_dev, SetSensorClk);
749 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
753 while (mi0360_sensor_init[i][0]) {
754 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
759 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
763 while (mo4000_sensor_init[i][0]) {
764 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
769 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
773 while (ov7648_sensor_init[i][0]) {
774 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
779 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
783 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
786 while (ov7660_sensor_init[i][0]) {
787 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
792 /* this function is called at probe time */
793 static int sd_config(struct gspca_dev *gspca_dev,
794 const struct usb_device_id *id)
796 struct sd *sd = (struct sd *) gspca_dev;
800 product = id->idProduct;
802 switch (id->idVendor) {
803 case 0x0458: /* Genius */
804 /* switch (product) {
806 sd->bridge = BRIDGE_SN9C120;
807 sd->sensor = SENSOR_MI0360;
813 /* switch (product) {
816 sd->bridge = BRIDGE_SN9C105;
817 sd->sensor = SENSOR_OV7660;
822 case 0x0471: /* Philips */
823 /* switch (product) {
827 sd->bridge = BRIDGE_SN9C105;
828 sd->sensor = SENSOR_MI0360;
833 case 0x0c45: /* Sonix */
836 sd->bridge = BRIDGE_SN9C102P;
837 /* sd->sensor = SENSOR_MI0360; * from BW600.inf */
838 /*fixme: MI0360 base=5d ? */
839 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
842 /* case 0x607a: * from BW600.inf
843 sd->bridge = BRIDGE_SN9C102P;
844 sd->sensor = SENSOR_OV7648;
848 sd->bridge = BRIDGE_SN9C102P;
849 sd->sensor = SENSOR_HV7131R;
852 /* case 0x607e: * from BW600.inf
853 sd->bridge = BRIDGE_SN9C102P;
854 sd->sensor = SENSOR_OV7630;
858 sd->bridge = BRIDGE_SN9C105;
859 sd->sensor = SENSOR_MI0360;
862 /* case 0x60c8: * from BW600.inf
863 sd->bridge = BRIDGE_SN9C105;
864 sd->sensor = SENSOR_OM6801;
867 /* case 0x60cc: * from BW600.inf
868 sd->bridge = BRIDGE_SN9C105;
869 sd->sensor = SENSOR_HV7131GP;
873 sd->bridge = BRIDGE_SN9C105;
874 sd->sensor = SENSOR_MO4000;
877 /* case 0x60ef: * from BW600.inf
878 sd->bridge = BRIDGE_SN9C105;
879 sd->sensor = SENSOR_ICM105C;
882 /* case 0x60fa: * from BW600.inf
883 sd->bridge = BRIDGE_SN9C105;
884 sd->sensor = SENSOR_OV7648;
888 sd->bridge = BRIDGE_SN9C105;
889 sd->sensor = SENSOR_OV7660;
893 sd->bridge = BRIDGE_SN9C105;
894 sd->sensor = SENSOR_HV7131R;
897 /* case 0x60fe: * from BW600.inf
898 sd->bridge = BRIDGE_SN9C105;
899 sd->sensor = SENSOR_OV7630;
902 /* case 0x6108: * from BW600.inf
903 sd->bridge = BRIDGE_SN9C120;
904 sd->sensor = SENSOR_OM6801;
907 /* case 0x6122: * from BW600.inf
908 sd->bridge = BRIDGE_SN9C110;
909 sd->sensor = SENSOR_ICM105C;
913 /* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
914 sd->bridge = BRIDGE_SN9C325;
915 sd->sensor = SENSOR_OV7648;
917 /*fixme: sensor_init has base = 00 et 6e!*/
919 /* case 0x6123: * from BW600.inf
920 sd->bridge = BRIDGE_SN9C110;
921 sd->sensor = SENSOR_SanyoCCD;
925 sd->bridge = BRIDGE_SN9C110;
926 sd->sensor = SENSOR_MO4000;
929 /* case 0x612e: * from BW600.inf
930 sd->bridge = BRIDGE_SN9C110;
931 sd->sensor = SENSOR_OV7630;
934 /* case 0x612f: * from BW600.inf
935 sd->bridge = BRIDGE_SN9C110;
936 sd->sensor = SENSOR_ICM105C;
940 sd->bridge = BRIDGE_SN9C120;
941 sd->sensor = SENSOR_MI0360;
945 sd->bridge = BRIDGE_SN9C120;
946 sd->sensor = SENSOR_MO4000;
949 /* case 0x613a: * from BW600.inf
950 sd->bridge = BRIDGE_SN9C120;
951 sd->sensor = SENSOR_OV7648;
955 sd->bridge = BRIDGE_SN9C120;
956 sd->sensor = SENSOR_OV7660;
960 sd->bridge = BRIDGE_SN9C120;
961 sd->sensor = SENSOR_HV7131R;
964 /* case 0x613e: * from BW600.inf
965 sd->bridge = BRIDGE_SN9C120;
966 sd->sensor = SENSOR_OV7630;
972 if (sd->sensor < 0) {
973 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
974 id->idVendor, product);
978 cam = &gspca_dev->cam;
980 cam->cam_mode = vga_mode;
981 cam->nmodes = ARRAY_SIZE(vga_mode);
983 sd->qindex = 4; /* set the quantization table */
984 sd->brightness = BRIGHTNESS_DEF;
985 sd->contrast = CONTRAST_DEF;
986 sd->colors = COLOR_DEF;
987 sd->autogain = AUTOGAIN_DEF;
991 /* this function is called at open time */
992 static int sd_open(struct gspca_dev *gspca_dev)
994 struct sd *sd = (struct sd *) gspca_dev;
995 /* const __u8 *sn9c1xx; */
996 __u8 regGpio[] = { 0x29, 0x74 };
999 /* setup a selector by bridge */
1000 reg_w1(gspca_dev, 0xf1, 0x01);
1001 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
1002 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1003 reg_r(gspca_dev, 0x00, 1);
1004 regF1 = gspca_dev->usb_buf[0];
1005 switch (sd->bridge) {
1006 case BRIDGE_SN9C102P:
1009 reg_w1(gspca_dev, 0x02, regGpio[1]);
1011 case BRIDGE_SN9C105:
1014 reg_w(gspca_dev, 0x02, regGpio, 2);
1016 case BRIDGE_SN9C120:
1020 reg_w(gspca_dev, 0x02, regGpio, 2);
1023 /* case BRIDGE_SN9C110: */
1024 /* case BRIDGE_SN9C325: */
1027 reg_w1(gspca_dev, 0x02, 0x62);
1031 reg_w1(gspca_dev, 0xf1, 0x01);
1036 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1039 struct sd *sd = (struct sd *) gspca_dev;
1040 static const __u8 doit[] = /* update sensor */
1041 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1042 static const __u8 sensorgo[] = /* sensor on */
1043 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1044 static const __u8 gainMo[] =
1045 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1047 switch (sd->sensor) {
1048 case SENSOR_HV7131R: {
1050 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1052 Expodoit[3] = expo >> 16;
1053 Expodoit[4] = expo >> 8;
1055 i2c_w8(gspca_dev, Expodoit);
1058 case SENSOR_MI0360: {
1059 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1060 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1064 else if (expo < 0x0001)
1066 expoMi[3] = expo >> 8;
1068 i2c_w8(gspca_dev, expoMi);
1069 i2c_w8(gspca_dev, doit);
1070 i2c_w8(gspca_dev, sensorgo);
1073 case SENSOR_MO4000: {
1075 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1077 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1081 else if (expo < 0x0001)
1083 expoMof[3] = (expo & 0x03fc) >> 2;
1084 i2c_w8(gspca_dev, expoMof);
1085 expoMo10[3] = ((expo & 0x1c00) >> 10)
1086 | ((expo & 0x0003) << 4);
1087 i2c_w8(gspca_dev, expoMo10);
1088 i2c_w8(gspca_dev, gainMo);
1089 PDEBUG(D_CONF, "set exposure %d",
1090 ((expoMo10[3] & 0x07) << 10)
1092 | ((expoMo10[3] & 0x30) >> 4));
1099 static void setbrightness(struct gspca_dev *gspca_dev)
1101 struct sd *sd = (struct sd *) gspca_dev;
1105 switch (sd->sensor) {
1106 case SENSOR_HV7131R:
1107 expo = sd->brightness << 4;
1108 if (expo > 0x002dc6c0)
1110 else if (expo < 0x02a0)
1112 sd->exposure = setexposure(gspca_dev, expo);
1115 expo = sd->brightness >> 4;
1116 sd->exposure = setexposure(gspca_dev, expo);
1119 expo = sd->brightness >> 4;
1120 sd->exposure = setexposure(gspca_dev, expo);
1126 k2 = sd->brightness >> 10;
1127 reg_w1(gspca_dev, 0x96, k2);
1130 static void setcontrast(struct gspca_dev *gspca_dev)
1132 struct sd *sd = (struct sd *) gspca_dev;
1134 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1136 if (sd->sensor == SENSOR_OV7660)
1140 contrast[0] = (k2 + 1) >> 1;
1141 contrast[4] = (k2 + 1) / 5;
1142 reg_w(gspca_dev, 0x84, contrast, 6);
1145 static void setcolors(struct gspca_dev *gspca_dev)
1147 struct sd *sd = (struct sd *) gspca_dev;
1151 colour = sd->colors - 128;
1153 data = (colour + 32) & 0x7f; /* blue */
1155 data = (-colour + 32) & 0x7f; /* red */
1156 reg_w1(gspca_dev, 0x05, data);
1159 /* -- start the camera -- */
1160 static void sd_start(struct gspca_dev *gspca_dev)
1162 struct sd *sd = (struct sd *) gspca_dev;
1167 const __u8 *sn9c1xx;
1169 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1170 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1171 static const __u8 CA_sn9c120[] =
1172 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1173 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1174 static const __u8 CE_sn9c325[] =
1175 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1177 sn9c1xx = sn_tb[(int) sd->sensor];
1178 configure_gpio(gspca_dev, sn9c1xx);
1180 /*fixme:jfm this sequence should appear at end of sd_start */
1182 reg_w1(gspca_dev, 0x01, 0x44); */
1183 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1184 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1185 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1186 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1187 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1188 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1189 reg_w1(gspca_dev, 0xd3, 0x50);
1190 reg_w1(gspca_dev, 0xc6, 0x00);
1191 reg_w1(gspca_dev, 0xc7, 0x00);
1192 reg_w1(gspca_dev, 0xc8, 0x50);
1193 reg_w1(gspca_dev, 0xc9, 0x3c);
1194 /*fixme:jfm end of ending sequence */
1195 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1196 switch (sd->bridge) {
1197 case BRIDGE_SN9C325:
1200 case BRIDGE_SN9C120:
1207 reg_w1(gspca_dev, 0x17, data);
1208 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1209 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1210 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1211 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1212 switch (sd->bridge) {
1213 case BRIDGE_SN9C325:
1214 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1215 sizeof regsn20_sn9c325);
1216 for (i = 0; i < 8; i++)
1217 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1218 sizeof reg84_sn9c325);
1219 reg_w1(gspca_dev, 0x9a, 0x0a);
1220 reg_w1(gspca_dev, 0x99, 0x60);
1222 case BRIDGE_SN9C120:
1223 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1224 sizeof regsn20_sn9c120);
1225 for (i = 0; i < 2; i++)
1226 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1227 sizeof reg84_sn9c120_1);
1228 for (i = 0; i < 6; i++)
1229 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1230 sizeof reg84_sn9c120_2);
1231 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1232 sizeof reg84_sn9c120_3);
1233 reg_w1(gspca_dev, 0x9a, 0x05);
1234 reg_w1(gspca_dev, 0x99, 0x5b);
1237 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1238 for (i = 0; i < 8; i++)
1239 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1240 reg_w1(gspca_dev, 0x9a, 0x08);
1241 reg_w1(gspca_dev, 0x99, 0x59);
1245 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1247 reg1 = 0x46; /* 320 clk 48Mhz */
1249 reg1 = 0x06; /* 640 clk 24Mz */
1251 switch (sd->sensor) {
1252 case SENSOR_HV7131R:
1253 hv7131R_InitSensor(gspca_dev);
1256 mi0360_InitSensor(gspca_dev);
1259 mo4000_InitSensor(gspca_dev);
1261 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1262 reg1 = 0x06; /* clk 24Mz */
1264 reg17 = 0x22; /* 640 MCKSIZE */
1265 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1269 ov7648_InitSensor(gspca_dev);
1278 /* case SENSOR_OV7660: */
1279 ov7660_InitSensor(gspca_dev);
1281 /* reg17 = 0x21; * 320 */
1283 /* reg1 = 0x46; (done) */
1285 reg17 = 0xa2; /* 640 */
1290 reg_w(gspca_dev, 0xc0, C0, 6);
1291 switch (sd->bridge) {
1292 case BRIDGE_SN9C120: /*jfm ?? */
1293 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1296 reg_w(gspca_dev, 0xca, CA, 4);
1299 switch (sd->bridge) {
1300 case BRIDGE_SN9C120: /*jfm ?? */
1301 case BRIDGE_SN9C325:
1302 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1305 reg_w(gspca_dev, 0xce, CE, 4);
1306 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1310 /* here change size mode 0 -> VGA; 1 -> CIF */
1311 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1312 reg_w1(gspca_dev, 0x18, data);
1314 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1315 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1317 data = sn9c1xx[0x18] | (mode << 4);
1318 reg_w1(gspca_dev, 0x18, data);
1320 reg_w1(gspca_dev, 0x17, reg17);
1321 reg_w1(gspca_dev, 0x01, reg1);
1322 setbrightness(gspca_dev);
1323 setcontrast(gspca_dev);
1326 static void sd_stopN(struct gspca_dev *gspca_dev)
1328 struct sd *sd = (struct sd *) gspca_dev;
1329 static const __u8 stophv7131[] =
1330 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1331 static const __u8 stopmi0360[] =
1332 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1334 const __u8 *sn9c1xx;
1337 switch (sd->sensor) {
1338 case SENSOR_HV7131R:
1339 i2c_w8(gspca_dev, stophv7131);
1343 i2c_w8(gspca_dev, stopmi0360);
1352 /* case SENSOR_OV7660: */
1355 sn9c1xx = sn_tb[(int) sd->sensor];
1356 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1357 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1358 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1359 reg_w1(gspca_dev, 0x01, data);
1360 reg_w1(gspca_dev, 0xf1, 0x01);
1363 static void sd_stop0(struct gspca_dev *gspca_dev)
1367 static void sd_close(struct gspca_dev *gspca_dev)
1371 static void setautogain(struct gspca_dev *gspca_dev)
1373 struct sd *sd = (struct sd *) gspca_dev;
1374 /* Thanks S., without your advice, autobright should not work :) */
1377 __u8 luma_mean = 130;
1378 __u8 luma_delta = 20;
1380 delta = sd->avg_lum;
1381 if (delta < luma_mean - luma_delta ||
1382 delta > luma_mean + luma_delta) {
1383 switch (sd->sensor) {
1384 case SENSOR_HV7131R:
1385 expotimes = sd->exposure >> 8;
1386 expotimes += (luma_mean - delta) >> 4;
1389 sd->exposure = setexposure(gspca_dev,
1390 (unsigned int) (expotimes << 8));
1394 expotimes = sd->exposure;
1395 expotimes += (luma_mean - delta) >> 6;
1398 sd->exposure = setexposure(gspca_dev,
1399 (unsigned int) expotimes);
1400 setcolors(gspca_dev);
1406 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1407 struct gspca_frame *frame, /* target */
1408 __u8 *data, /* isoc packet */
1409 int len) /* iso packet length */
1411 struct sd *sd = (struct sd *) gspca_dev;
1415 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1418 gspca_frame_add(gspca_dev, LAST_PACKET,
1419 frame, data, sof + 2);
1422 if (--sd->ag_cnt >= 0)
1424 sd->ag_cnt = AG_CNT_START;
1429 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1431 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1433 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1435 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1437 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1439 sd->avg_lum = avg_lum;
1440 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1441 setautogain(gspca_dev);
1444 if (gspca_dev->last_packet_type == LAST_PACKET) {
1446 /* put the JPEG 422 header */
1447 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1449 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1452 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1454 struct sd *sd = (struct sd *) gspca_dev;
1455 __u8 hexpo, mexpo, lexpo;
1457 switch (sd->sensor) {
1458 case SENSOR_HV7131R:
1459 /* read sensor exposure */
1460 i2c_r5(gspca_dev, 0x25);
1461 return (gspca_dev->usb_buf[0] << 16)
1462 | (gspca_dev->usb_buf[1] << 8)
1463 | gspca_dev->usb_buf[2];
1465 /* read sensor exposure */
1466 i2c_r5(gspca_dev, 0x09);
1467 return (gspca_dev->usb_buf[0] << 8)
1468 | gspca_dev->usb_buf[1];
1470 i2c_r5(gspca_dev, 0x0e);
1471 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1472 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1473 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1474 PDEBUG(D_CONF, "exposure %d",
1475 (hexpo << 10) | (mexpo << 2) | lexpo);
1476 return (hexpo << 10) | (mexpo << 2) | lexpo;
1478 /* case SENSOR_OV7660: */
1479 /* read sensor exposure */
1480 i2c_r5(gspca_dev, 0x04);
1481 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1482 lexpo = gspca_dev->usb_buf[0] & 0x02;
1483 i2c_r5(gspca_dev, 0x08);
1484 mexpo = gspca_dev->usb_buf[2];
1485 return (hexpo << 10) | (mexpo << 2) | lexpo;
1489 static void getbrightness(struct gspca_dev *gspca_dev)
1491 struct sd *sd = (struct sd *) gspca_dev;
1493 /* hardcoded registers seem not readable */
1494 switch (sd->sensor) {
1495 case SENSOR_HV7131R:
1496 /* sd->brightness = 0x7fff; */
1497 sd->brightness = getexposure(gspca_dev) >> 4;
1500 sd->brightness = getexposure(gspca_dev) << 4;
1503 /* sd->brightness = 0x1fff; */
1504 sd->brightness = getexposure(gspca_dev) << 4;
1509 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1511 struct sd *sd = (struct sd *) gspca_dev;
1513 sd->brightness = val;
1514 if (gspca_dev->streaming)
1515 setbrightness(gspca_dev);
1519 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1521 struct sd *sd = (struct sd *) gspca_dev;
1523 getbrightness(gspca_dev);
1524 *val = sd->brightness;
1528 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1530 struct sd *sd = (struct sd *) gspca_dev;
1533 if (gspca_dev->streaming)
1534 setcontrast(gspca_dev);
1538 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1540 struct sd *sd = (struct sd *) gspca_dev;
1542 *val = sd->contrast;
1546 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1548 struct sd *sd = (struct sd *) gspca_dev;
1551 if (gspca_dev->streaming)
1552 setcolors(gspca_dev);
1556 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1558 struct sd *sd = (struct sd *) gspca_dev;
1564 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1566 struct sd *sd = (struct sd *) gspca_dev;
1570 sd->ag_cnt = AG_CNT_START;
1576 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1578 struct sd *sd = (struct sd *) gspca_dev;
1580 *val = sd->autogain;
1584 /* sub-driver description */
1585 static const struct sd_desc sd_desc = {
1586 .name = MODULE_NAME,
1588 .nctrls = ARRAY_SIZE(sd_ctrls),
1589 .config = sd_config,
1595 .pkt_scan = sd_pkt_scan,
1598 /* -- module initialisation -- */
1599 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1600 static const __devinitdata struct usb_device_id device_table[] = {
1601 #ifndef CONFIG_USB_SN9C102
1602 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1603 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1604 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1605 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1606 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1608 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1609 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1610 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1611 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1612 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1613 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1614 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1615 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1616 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1617 #ifndef CONFIG_USB_SN9C102
1618 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1619 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1620 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1621 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1625 MODULE_DEVICE_TABLE(usb, device_table);
1627 /* -- device connect -- */
1628 static int sd_probe(struct usb_interface *intf,
1629 const struct usb_device_id *id)
1631 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1635 static struct usb_driver sd_driver = {
1636 .name = MODULE_NAME,
1637 .id_table = device_table,
1639 .disconnect = gspca_disconnect,
1642 /* -- module insert / remove -- */
1643 static int __init sd_mod_init(void)
1645 if (usb_register(&sd_driver) < 0)
1650 static void __exit sd_mod_exit(void)
1652 usb_deregister(&sd_driver);
1653 info("deregistered");
1656 module_init(sd_mod_init);
1657 module_exit(sd_mod_exit);