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_OV7630 4
59 #define SENSOR_OV7648 5
60 #define SENSOR_OV7660 6
61 unsigned char i2c_base;
64 /* V4L2 controls supported by the driver */
65 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
74 static struct ctrl sd_ctrls[] = {
77 .id = V4L2_CID_BRIGHTNESS,
78 .type = V4L2_CTRL_TYPE_INTEGER,
81 #define BRIGHTNESS_MAX 0xffff
82 .maximum = BRIGHTNESS_MAX,
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,
96 #define CONTRAST_MAX 127
97 .maximum = CONTRAST_MAX,
99 #define CONTRAST_DEF 63
100 .default_value = CONTRAST_DEF,
102 .set = sd_setcontrast,
103 .get = sd_getcontrast,
107 .id = V4L2_CID_SATURATION,
108 .type = V4L2_CTRL_TYPE_INTEGER,
114 .default_value = COLOR_DEF,
121 .id = V4L2_CID_AUTOGAIN,
122 .type = V4L2_CTRL_TYPE_BOOLEAN,
127 #define AUTOGAIN_DEF 1
128 .default_value = AUTOGAIN_DEF,
130 .set = sd_setautogain,
131 .get = sd_getautogain,
135 static struct v4l2_pix_format vga_mode[] = {
136 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .sizeimage = 160 * 120 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
141 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .sizeimage = 320 * 240 * 3 / 8 + 590,
144 .colorspace = V4L2_COLORSPACE_JPEG,
146 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .sizeimage = 640 * 480 * 3 / 8 + 590,
149 .colorspace = V4L2_COLORSPACE_JPEG,
153 /*Data from sn9c102p+hv71331r */
154 static const __u8 sn_hv7131[] = {
155 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
156 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
157 /* reg8 reg9 rega regb regc regd rege regf */
158 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
159 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
160 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
161 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
162 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
165 static const __u8 sn_mi0360[] = {
166 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
167 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
168 /* reg8 reg9 rega regb regc regd rege regf */
169 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
170 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
171 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
172 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
173 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
176 static const __u8 sn_mo4000[] = {
177 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
178 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
179 /* reg8 reg9 rega regb regc regd rege regf */
180 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
182 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
183 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
184 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
187 static const __u8 sn_om6802[] = {
188 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
189 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
190 /* reg8 reg9 rega regb regc regd rege regf */
191 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
193 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
194 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
195 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
197 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
201 static const __u8 sn_ov7630[] = {
202 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
203 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
204 /* reg8 reg9 rega regb regc regd rege regf */
205 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
206 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
207 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
208 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
209 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
212 static const __u8 sn_ov7648[] = {
213 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
214 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
215 /* reg8 reg9 rega regb regc regd rege regf */
216 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
217 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
218 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
219 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
220 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
223 static const __u8 sn_ov7660[] = {
224 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
225 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
226 /* reg8 reg9 rega regb regc regd rege regf */
227 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
228 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
229 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
230 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
231 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 /* sequence specific to the sensors - !! index = SENSOR_xxx */
235 static const __u8 *sn_tb[] = {
245 static const __u8 gamma_def[] = {
246 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
247 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
250 static const __u8 reg84[] = {
251 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
252 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
253 0xf7, 0x0f, 0x00, 0x00, 0x00
255 static const __u8 hv7131r_sensor_init[][8] = {
256 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
257 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
258 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
259 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
262 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
266 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
267 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
268 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
269 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
270 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
271 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
273 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
286 static const __u8 mi0360_sensor_init[][8] = {
287 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
291 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
292 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
293 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
308 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
309 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
310 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
312 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
314 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
315 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
316 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
318 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
319 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
323 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
324 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
325 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
327 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
328 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
330 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
332 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
333 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
334 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
335 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
336 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
337 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
340 static const __u8 mo4000_sensor_init[][8] = {
341 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
360 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
363 static __u8 om6802_sensor_init[][8] = {
364 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
365 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
366 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
367 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
368 /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
369 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
370 /* white balance & auto-exposure */
371 /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
373 /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
374 * max AGC value in AE */
375 /* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
377 /* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
378 * preset brightness */
379 /* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
381 /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
383 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
384 /* luminance mode (0x4f = AE) */
385 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
387 /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
389 /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
391 /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
392 /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
393 /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
394 /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
397 static const __u8 ov7630_sensor_init[][8] = {
398 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
399 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
400 /* win: delay 20ms */
401 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
402 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
403 /* win: delay 20ms */
404 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
405 /* win: i2c_r from 00 to 80 */
406 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
407 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
408 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
409 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
410 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
411 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
412 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
413 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
414 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
415 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
416 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
417 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
418 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
421 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
422 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
423 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
424 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
425 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
426 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
427 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
428 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
429 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
430 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
431 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
433 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
435 /*fixme: + 0x12, 0x04*/
436 {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
437 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
438 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
439 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
441 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
446 {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10},
449 static const __u8 ov7660_sensor_init[][8] = {
450 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
452 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
453 /* Outformat = rawRGB */
454 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
455 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
456 /* GAIN BLUE RED VREF */
457 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
458 /* COM 1 BAVE GEAVE AECHH */
459 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
460 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
461 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
462 /* AECH CLKRC COM7 COM8 */
463 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
464 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
465 /* HSTART HSTOP VSTRT VSTOP */
466 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
467 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
468 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
469 /* BOS GBOS GROS ROS (BGGR offset) */
470 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
471 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
472 /* AEW AEB VPT BBIAS */
473 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
474 /* GbBIAS RSVD EXHCH EXHCL */
475 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
476 /* RBIAS ADVFL ASDVFH YAVE */
477 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
478 /* HSYST HSYEN HREF */
479 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
480 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
481 /* ADC ACOM OFON TSLB */
482 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
483 /* COM11 COM12 COM13 COM14 */
484 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
485 /* EDGE COM15 COM16 COM17 */
486 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
487 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
488 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
489 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
490 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
491 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
492 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
493 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
494 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
495 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
496 /* LCC1 LCC2 LCC3 LCC4 */
497 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
498 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
499 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
500 /* band gap reference [0:3] DBLV */
501 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
502 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
503 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
504 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
505 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
506 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
507 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
508 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
509 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
510 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
511 /****** (some exchanges in the win trace) ******/
512 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
513 /* bits[3..0]reserved */
514 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
515 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
516 /* VREF vertical frame ctrl */
517 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
518 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
519 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
520 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
521 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
522 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
523 /****** (some exchanges in the win trace) ******/
524 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
525 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
526 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
527 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
528 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
529 /****** (some exchanges in the win trace) ******/
530 /******!! startsensor KO if changed !!****/
531 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
532 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
533 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
534 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
537 /* reg 0x04 reg 0x07 reg 0x10 */
538 /* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
540 static const __u8 ov7648_sensor_init[][8] = {
541 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
542 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
543 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
544 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
545 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
546 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
547 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
548 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
549 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
550 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
551 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
552 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
553 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
554 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
555 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
556 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
557 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
558 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
559 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
560 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
561 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
562 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
563 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
564 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
565 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
566 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
567 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
568 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
569 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
570 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
571 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
572 * This is currently setting a
573 * blue tint, and some things more , i leave it here for future test if
574 * somene is having problems with color on this sensor
575 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
576 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
577 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
578 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
579 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
580 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
581 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
582 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
583 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
584 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
585 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
586 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
587 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
588 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
589 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
590 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
591 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
592 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
596 static const __u8 qtable4[] = {
597 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
598 0x06, 0x08, 0x0A, 0x11,
599 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
600 0x19, 0x19, 0x17, 0x15,
601 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
602 0x21, 0x2E, 0x21, 0x23,
603 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
604 0x25, 0x29, 0x2C, 0x29,
605 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
606 0x17, 0x1B, 0x29, 0x29,
607 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
608 0x29, 0x29, 0x29, 0x29,
609 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
610 0x29, 0x29, 0x29, 0x29,
611 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
612 0x29, 0x29, 0x29, 0x29
615 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
616 static void reg_r(struct gspca_dev *gspca_dev,
617 __u16 value, int len)
619 usb_control_msg(gspca_dev->dev,
620 usb_rcvctrlpipe(gspca_dev->dev, 0),
622 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
624 gspca_dev->usb_buf, len,
626 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
629 static void reg_w1(struct gspca_dev *gspca_dev,
633 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
634 gspca_dev->usb_buf[0] = data;
635 usb_control_msg(gspca_dev->dev,
636 usb_sndctrlpipe(gspca_dev->dev, 0),
638 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
641 gspca_dev->usb_buf, 1,
644 static void reg_w(struct gspca_dev *gspca_dev,
649 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
650 value, buffer[0], buffer[1]);
651 if (len <= sizeof gspca_dev->usb_buf) {
652 memcpy(gspca_dev->usb_buf, buffer, len);
653 usb_control_msg(gspca_dev->dev,
654 usb_sndctrlpipe(gspca_dev->dev, 0),
656 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
658 gspca_dev->usb_buf, len,
663 tmpbuf = kmalloc(len, GFP_KERNEL);
664 memcpy(tmpbuf, buffer, len);
665 usb_control_msg(gspca_dev->dev,
666 usb_sndctrlpipe(gspca_dev->dev, 0),
668 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
676 /* I2C write 1 byte */
677 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
679 struct sd *sd = (struct sd *) gspca_dev;
681 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
682 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
683 gspca_dev->usb_buf[1] = sd->i2c_base;
684 gspca_dev->usb_buf[2] = reg;
685 gspca_dev->usb_buf[3] = val;
686 gspca_dev->usb_buf[4] = 0;
687 gspca_dev->usb_buf[5] = 0;
688 gspca_dev->usb_buf[6] = 0;
689 gspca_dev->usb_buf[7] = 0x10;
690 usb_control_msg(gspca_dev->dev,
691 usb_sndctrlpipe(gspca_dev->dev, 0),
693 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
694 0x08, /* value = i2c */
696 gspca_dev->usb_buf, 8,
700 /* I2C write 8 bytes */
701 static void i2c_w8(struct gspca_dev *gspca_dev,
704 memcpy(gspca_dev->usb_buf, buffer, 8);
705 usb_control_msg(gspca_dev->dev,
706 usb_sndctrlpipe(gspca_dev->dev, 0),
708 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
709 0x08, 0, /* value, index */
710 gspca_dev->usb_buf, 8,
714 /* read 5 bytes in gspca_dev->usb_buf */
715 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
717 struct sd *sd = (struct sd *) gspca_dev;
720 mode[0] = 0x81 | 0x10;
721 mode[1] = sd->i2c_base;
728 i2c_w8(gspca_dev, mode);
730 mode[0] = 0x81 | (5 << 4) | 0x02;
732 i2c_w8(gspca_dev, mode);
734 reg_r(gspca_dev, 0x0a, 5);
737 static int probesensor(struct gspca_dev *gspca_dev)
739 struct sd *sd = (struct sd *) gspca_dev;
741 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
743 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
745 i2c_r5(gspca_dev, 0); /* read sensor id */
746 if (gspca_dev->usb_buf[0] == 0x02
747 && gspca_dev->usb_buf[1] == 0x09
748 && gspca_dev->usb_buf[2] == 0x01
749 && gspca_dev->usb_buf[3] == 0x00
750 && gspca_dev->usb_buf[4] == 0x00) {
751 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
752 sd->sensor = SENSOR_HV7131R;
753 return SENSOR_HV7131R;
755 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
756 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
757 gspca_dev->usb_buf[2]);
758 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
762 static int configure_gpio(struct gspca_dev *gspca_dev,
765 struct sd *sd = (struct sd *) gspca_dev;
767 static const __u8 reg9a_def[] =
768 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
769 static const __u8 reg9a_sn9c325[] =
770 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
771 static const __u8 regd4[] = {0x60, 0x00, 0x00};
773 reg_w1(gspca_dev, 0xf1, 0x00);
774 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
777 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
778 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
779 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
780 switch (sd->bridge) {
782 reg9a = reg9a_sn9c325;
788 reg_w(gspca_dev, 0x9a, reg9a, 6);
790 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
792 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
794 switch (sd->sensor) {
796 reg_w1(gspca_dev, 0x02, 0x71);
797 reg_w1(gspca_dev, 0x01, 0x42);
798 reg_w1(gspca_dev, 0x17, 0x64);
799 reg_w1(gspca_dev, 0x01, 0x42);
801 /*jfm: from win trace */
803 reg_w1(gspca_dev, 0x01, 0x61);
804 reg_w1(gspca_dev, 0x17, 0xe2);
805 reg_w1(gspca_dev, 0x01, 0x60);
806 reg_w1(gspca_dev, 0x01, 0x40);
809 reg_w1(gspca_dev, 0x01, 0x43);
810 reg_w1(gspca_dev, 0x17, 0xae);
811 reg_w1(gspca_dev, 0x01, 0x42);
814 reg_w1(gspca_dev, 0x01, 0x43);
815 reg_w1(gspca_dev, 0x17, 0x61);
816 reg_w1(gspca_dev, 0x01, 0x42);
817 if (sd->sensor == SENSOR_HV7131R) {
818 if (probesensor(gspca_dev) < 0)
826 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
829 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
830 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
832 while (hv7131r_sensor_init[i][0]) {
833 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
836 i2c_w8(gspca_dev, SetSensorClk);
839 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
843 while (mi0360_sensor_init[i][0]) {
844 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
849 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
853 while (mo4000_sensor_init[i][0]) {
854 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
859 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
863 while (om6802_sensor_init[i][0]) {
864 i2c_w8(gspca_dev, om6802_sensor_init[i]);
869 static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
873 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
875 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
878 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
880 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
883 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
885 /*jfm:win i2c_r from 00 to 80*/
887 while (ov7630_sensor_init[i][0]) {
888 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
893 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
897 while (ov7648_sensor_init[i][0]) {
898 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
903 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
907 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
910 while (ov7660_sensor_init[i][0]) {
911 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
916 /* this function is called at probe time */
917 static int sd_config(struct gspca_dev *gspca_dev,
918 const struct usb_device_id *id)
920 struct sd *sd = (struct sd *) gspca_dev;
923 cam = &gspca_dev->cam;
925 cam->cam_mode = vga_mode;
926 cam->nmodes = ARRAY_SIZE(vga_mode);
928 sd->bridge = id->driver_info >> 16;
929 sd->sensor = id->driver_info >> 8;
930 sd->i2c_base = id->driver_info;
932 sd->qindex = 4; /* set the quantization table */
933 sd->brightness = BRIGHTNESS_DEF;
934 sd->contrast = CONTRAST_DEF;
935 sd->colors = COLOR_DEF;
936 sd->autogain = AUTOGAIN_DEF;
942 /* this function is called at open time */
943 static int sd_open(struct gspca_dev *gspca_dev)
945 struct sd *sd = (struct sd *) gspca_dev;
946 /* const __u8 *sn9c1xx; */
947 __u8 regGpio[] = { 0x29, 0x74 };
950 /* setup a selector by bridge */
951 reg_w1(gspca_dev, 0xf1, 0x01);
952 reg_r(gspca_dev, 0x00, 1);
953 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
954 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
955 regF1 = gspca_dev->usb_buf[0];
956 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
957 switch (sd->bridge) {
958 case BRIDGE_SN9C102P:
961 reg_w1(gspca_dev, 0x02, regGpio[1]);
966 reg_w(gspca_dev, 0x02, regGpio, 2);
972 reg_w(gspca_dev, 0x02, regGpio, 2);
975 /* case BRIDGE_SN9C110: */
976 /* case BRIDGE_SN9C325: */
979 reg_w1(gspca_dev, 0x02, 0x62);
983 reg_w1(gspca_dev, 0xf1, 0x01);
988 static unsigned int setexposure(struct gspca_dev *gspca_dev,
991 struct sd *sd = (struct sd *) gspca_dev;
992 static const __u8 doit[] = /* update sensor */
993 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
994 static const __u8 sensorgo[] = /* sensor on */
995 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
996 static const __u8 gainMo[] =
997 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
999 switch (sd->sensor) {
1000 case SENSOR_HV7131R: {
1002 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1004 Expodoit[3] = expo >> 16;
1005 Expodoit[4] = expo >> 8;
1007 i2c_w8(gspca_dev, Expodoit);
1010 case SENSOR_MI0360: {
1011 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1012 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1016 else if (expo < 0x0001)
1018 expoMi[3] = expo >> 8;
1020 i2c_w8(gspca_dev, expoMi);
1021 i2c_w8(gspca_dev, doit);
1022 i2c_w8(gspca_dev, sensorgo);
1025 case SENSOR_MO4000: {
1027 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1029 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1033 else if (expo < 0x0001)
1035 expoMof[3] = (expo & 0x03fc) >> 2;
1036 i2c_w8(gspca_dev, expoMof);
1037 expoMo10[3] = ((expo & 0x1c00) >> 10)
1038 | ((expo & 0x0003) << 4);
1039 i2c_w8(gspca_dev, expoMo10);
1040 i2c_w8(gspca_dev, gainMo);
1041 PDEBUG(D_CONF, "set exposure %d",
1042 ((expoMo10[3] & 0x07) << 10)
1044 | ((expoMo10[3] & 0x30) >> 4));
1047 case SENSOR_OM6802: {
1049 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1055 gainOm[3] = expo >> 2;
1056 i2c_w8(gspca_dev, gainOm);
1057 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
1058 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1065 /* this function is used for sensors o76xx only */
1066 static void setbrightcont(struct gspca_dev *gspca_dev)
1068 struct sd *sd = (struct sd *) gspca_dev;
1070 __u8 reg84_full[13];
1072 memset(reg84_full, 0, sizeof reg84_full);
1073 val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
1074 reg84_full[2] = val;
1075 reg84_full[0] = (val + 1) / 2;
1076 reg84_full[4] = (val + 1) / 5;
1077 if (val > BRIGHTNESS_DEF)
1078 val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
1082 reg84_full[10] = val; /* 00..1f */
1083 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1086 /* sensor != ov76xx */
1087 static void setbrightness(struct gspca_dev *gspca_dev)
1089 struct sd *sd = (struct sd *) gspca_dev;
1093 k2 = sd->brightness >> 10;
1094 switch (sd->sensor) {
1095 case SENSOR_HV7131R:
1096 expo = sd->brightness << 4;
1097 if (expo > 0x002dc6c0)
1099 else if (expo < 0x02a0)
1101 sd->exposure = setexposure(gspca_dev, expo);
1105 expo = sd->brightness >> 4;
1106 sd->exposure = setexposure(gspca_dev, expo);
1109 expo = sd->brightness >> 6;
1110 sd->exposure = setexposure(gspca_dev, expo);
1111 k2 = sd->brightness >> 11;
1115 reg_w1(gspca_dev, 0x96, k2);
1118 /* sensor != ov76xx */
1119 static void setcontrast(struct gspca_dev *gspca_dev)
1121 struct sd *sd = (struct sd *) gspca_dev;
1123 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1127 contrast[0] = (k2 + 1) >> 1;
1128 contrast[4] = (k2 + 1) / 5;
1129 reg_w(gspca_dev, 0x84, contrast, 6);
1132 static void setcolors(struct gspca_dev *gspca_dev)
1134 struct sd *sd = (struct sd *) gspca_dev;
1137 if (sd->colors >= 32) {
1138 red = 32 + (sd->colors - 32) / 2;
1139 blue = 64 - sd->colors;
1142 blue = 32 + (32 - sd->colors) / 2;
1144 reg_w1(gspca_dev, 0x05, red);
1145 /* reg_w1(gspca_dev, 0x07, 32); */
1146 reg_w1(gspca_dev, 0x06, blue);
1149 static void setautogain(struct gspca_dev *gspca_dev)
1151 struct sd *sd = (struct sd *) gspca_dev;
1153 switch (sd->sensor) {
1154 case SENSOR_HV7131R:
1158 sd->ag_cnt = AG_CNT_START;
1165 /* -- start the camera -- */
1166 static void sd_start(struct gspca_dev *gspca_dev)
1168 struct sd *sd = (struct sd *) gspca_dev;
1170 __u8 reg1, reg17, reg18;
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 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1176 static const __u8 CE_ov76xx[] =
1177 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
1179 sn9c1xx = sn_tb[(int) sd->sensor];
1180 configure_gpio(gspca_dev, sn9c1xx);
1182 /* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
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 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1195 switch (sd->sensor) {
1202 /*jfm: from win trace */
1210 reg_w1(gspca_dev, 0x17, reg17);
1211 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1212 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1213 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1214 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1215 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1216 for (i = 0; i < 8; i++)
1217 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1218 reg_w1(gspca_dev, 0x9a, 0x08);
1219 reg_w1(gspca_dev, 0x99, 0x59);
1221 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1223 reg1 = 0x46; /* 320 clk 48Mhz */
1225 reg1 = 0x06; /* 640 clk 24Mz */
1227 switch (sd->sensor) {
1228 case SENSOR_HV7131R:
1229 hv7131R_InitSensor(gspca_dev);
1232 mi0360_InitSensor(gspca_dev);
1235 mo4000_InitSensor(gspca_dev);
1237 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1238 reg1 = 0x06; /* clk 24Mz */
1240 reg17 = 0x22; /* 640 MCKSIZE */
1241 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1245 om6802_InitSensor(gspca_dev);
1246 reg17 = 0x64; /* 640 MCKSIZE */
1249 ov7630_InitSensor(gspca_dev);
1254 ov7648_InitSensor(gspca_dev);
1263 /* case SENSOR_OV7660: */
1264 ov7660_InitSensor(gspca_dev);
1266 /* reg17 = 0x21; * 320 */
1268 /* reg1 = 0x46; (done) */
1270 reg17 = 0x22; /* 640 MCKSIZE */
1275 reg_w(gspca_dev, 0xc0, C0, 6);
1276 reg_w(gspca_dev, 0xca, CA, 4);
1277 switch (sd->sensor) {
1280 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
1283 reg_w(gspca_dev, 0xce, CE, 4);
1284 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1288 /* here change size mode 0 -> VGA; 1 -> CIF */
1289 reg18 = sn9c1xx[0x18] | (mode << 4);
1290 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1292 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1293 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1295 reg_w1(gspca_dev, 0x18, reg18);
1297 reg_w1(gspca_dev, 0x17, reg17);
1298 reg_w1(gspca_dev, 0x01, reg1);
1299 switch (sd->sensor) {
1300 case SENSOR_HV7131R:
1304 setbrightness(gspca_dev);
1305 setcontrast(gspca_dev);
1307 default: /* OV76xx */
1308 setbrightcont(gspca_dev);
1311 setautogain(gspca_dev);
1314 static void sd_stopN(struct gspca_dev *gspca_dev)
1316 struct sd *sd = (struct sd *) gspca_dev;
1317 static const __u8 stophv7131[] =
1318 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1319 static const __u8 stopmi0360[] =
1320 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1322 const __u8 *sn9c1xx;
1325 switch (sd->sensor) {
1326 case SENSOR_HV7131R:
1327 i2c_w8(gspca_dev, stophv7131);
1331 i2c_w8(gspca_dev, stopmi0360);
1339 /* case SENSOR_MO4000: */
1340 /* case SENSOR_OV7660: */
1343 sn9c1xx = sn_tb[(int) sd->sensor];
1344 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1345 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1346 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1347 reg_w1(gspca_dev, 0x01, data);
1348 reg_w1(gspca_dev, 0xf1, 0x00);
1351 static void sd_stop0(struct gspca_dev *gspca_dev)
1355 static void sd_close(struct gspca_dev *gspca_dev)
1359 static void do_autogain(struct gspca_dev *gspca_dev)
1361 struct sd *sd = (struct sd *) gspca_dev;
1364 __u8 luma_mean = 130;
1365 __u8 luma_delta = 20;
1367 /* Thanks S., without your advice, autobright should not work :) */
1370 if (--sd->ag_cnt >= 0)
1372 sd->ag_cnt = AG_CNT_START;
1374 delta = atomic_read(&sd->avg_lum);
1375 PDEBUG(D_FRAM, "mean lum %d", delta);
1376 if (delta < luma_mean - luma_delta ||
1377 delta > luma_mean + luma_delta) {
1378 switch (sd->sensor) {
1379 case SENSOR_HV7131R:
1380 expotimes = sd->exposure >> 8;
1381 expotimes += (luma_mean - delta) >> 4;
1384 sd->exposure = setexposure(gspca_dev,
1385 (unsigned int) (expotimes << 8));
1388 /* case SENSOR_MO4000: */
1389 /* case SENSOR_MI0360: */
1390 /* case SENSOR_OM6802: */
1391 expotimes = sd->exposure;
1392 expotimes += (luma_mean - delta) >> 6;
1395 sd->exposure = setexposure(gspca_dev,
1396 (unsigned int) expotimes);
1397 setcolors(gspca_dev);
1403 /* scan the URB packets */
1404 /* This function is run at interrupt level. */
1405 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1406 struct gspca_frame *frame, /* target */
1407 __u8 *data, /* isoc packet */
1408 int len) /* iso packet length */
1410 struct sd *sd = (struct sd *) gspca_dev;
1414 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1417 gspca_frame_add(gspca_dev, LAST_PACKET,
1418 frame, data, sof + 2);
1425 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1427 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1429 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1431 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1433 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1435 atomic_set(&sd->avg_lum, avg_lum);
1438 if (gspca_dev->last_packet_type == LAST_PACKET) {
1440 /* put the JPEG 422 header */
1441 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1443 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1446 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1448 struct sd *sd = (struct sd *) gspca_dev;
1450 sd->brightness = val;
1451 if (gspca_dev->streaming) {
1452 switch (sd->sensor) {
1453 case SENSOR_HV7131R:
1457 setbrightness(gspca_dev);
1459 default: /* OV76xx */
1460 setbrightcont(gspca_dev);
1467 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1469 struct sd *sd = (struct sd *) gspca_dev;
1471 *val = sd->brightness;
1475 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1477 struct sd *sd = (struct sd *) gspca_dev;
1480 if (gspca_dev->streaming) {
1481 switch (sd->sensor) {
1482 case SENSOR_HV7131R:
1486 setcontrast(gspca_dev);
1488 default: /* OV76xx */
1489 setbrightcont(gspca_dev);
1496 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1498 struct sd *sd = (struct sd *) gspca_dev;
1500 *val = sd->contrast;
1504 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1506 struct sd *sd = (struct sd *) gspca_dev;
1509 if (gspca_dev->streaming)
1510 setcolors(gspca_dev);
1514 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1516 struct sd *sd = (struct sd *) gspca_dev;
1522 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1524 struct sd *sd = (struct sd *) gspca_dev;
1527 if (gspca_dev->streaming)
1528 setautogain(gspca_dev);
1532 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1534 struct sd *sd = (struct sd *) gspca_dev;
1536 *val = sd->autogain;
1540 /* sub-driver description */
1541 static const struct sd_desc sd_desc = {
1542 .name = MODULE_NAME,
1544 .nctrls = ARRAY_SIZE(sd_ctrls),
1545 .config = sd_config,
1551 .pkt_scan = sd_pkt_scan,
1552 .dq_callback = do_autogain,
1555 /* -- module initialisation -- */
1556 #define BSI(bridge, sensor, i2c_addr) \
1557 .driver_info = (BRIDGE_ ## bridge << 16) \
1558 | (SENSOR_ ## sensor << 8) \
1560 static const __devinitdata struct usb_device_id device_table[] = {
1561 #ifndef CONFIG_USB_SN9C102
1562 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1563 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1564 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1565 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1566 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1568 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1569 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1571 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1572 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1573 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1574 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1575 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1576 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1577 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1578 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1579 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1580 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1581 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1582 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1583 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1584 /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1585 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1586 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1587 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1588 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1590 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
1591 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1592 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
1593 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1594 #ifndef CONFIG_USB_SN9C102
1595 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1596 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1597 /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1598 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1599 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1600 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1602 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1605 MODULE_DEVICE_TABLE(usb, device_table);
1607 /* -- device connect -- */
1608 static int sd_probe(struct usb_interface *intf,
1609 const struct usb_device_id *id)
1611 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1615 static struct usb_driver sd_driver = {
1616 .name = MODULE_NAME,
1617 .id_table = device_table,
1619 .disconnect = gspca_disconnect,
1622 /* -- module insert / remove -- */
1623 static int __init sd_mod_init(void)
1625 if (usb_register(&sd_driver) < 0)
1630 static void __exit sd_mod_exit(void)
1632 usb_deregister(&sd_driver);
1633 info("deregistered");
1636 module_init(sd_mod_init);
1637 module_exit(sd_mod_exit);