2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "sonixj"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28 static const char version[] = "2.1.7";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
39 unsigned int exposure;
41 unsigned short brightness;
42 unsigned char contrast;
44 unsigned char autogain;
47 #define AG_CNT_START 13
50 char sensor; /* Type of image sensor chip */
51 #define SENSOR_HV7131R 0
52 #define SENSOR_MI0360 1
53 #define SENSOR_MO4000 2
54 #define SENSOR_OV7648 3
55 #define SENSOR_OV7660 4
56 unsigned char customid;
62 unsigned char i2c_base;
63 unsigned char i2c_ctrl_reg;
66 /* V4L2 controls supported by the driver */
67 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
76 static struct ctrl sd_ctrls[] = {
79 .id = V4L2_CID_BRIGHTNESS,
80 .type = V4L2_CTRL_TYPE_INTEGER,
85 #define BRIGHTNESS_DEF 0x7fff
86 .default_value = BRIGHTNESS_DEF,
88 .set = sd_setbrightness,
89 .get = sd_getbrightness,
93 .id = V4L2_CID_CONTRAST,
94 .type = V4L2_CTRL_TYPE_INTEGER,
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,
113 #define COLOR_DEF 127
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 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
156 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
158 /* rega regb regc regd rege regf reg10 reg11 */
159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
160 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
162 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
165 static const __u8 sn_mi0360[] = {
166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
167 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
169 /* rega regb regc regd rege regf reg10 reg11 */
170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
171 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
173 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
176 static const __u8 sn_mo4000[] = {
177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
178 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
180 /* reg9 rega regb regc regd rege regf reg10 reg11*/
181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
182 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
184 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
185 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
186 0xd3, 0xdf, 0xea, 0xf5
189 static const __u8 sn_ov7648[] = {
190 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
191 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
192 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
195 static const __u8 sn_ov7660[] = {
196 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
197 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
198 /* reg9 rega regb regc regd rege regf reg10 reg11*/
199 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
200 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
201 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, 0x07, 0x00, 0x00,
202 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206 /* sequence specific to the sensors - !! index = SENSOR_xxx */
207 static const __u8 *sn_tb[] = {
215 static const __u8 regsn20[] = {
216 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
217 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 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_sn9c325[] = {
231 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
232 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
233 0xf8, 0x0f, 0x00, 0x00, 0x00
236 static const __u8 hv7131r_sensor_init[][8] = {
237 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
238 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
239 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
240 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
241 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
242 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
243 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
245 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
246 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
247 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
248 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
249 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
250 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
251 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
252 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
254 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
255 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
257 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
258 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
262 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
263 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
267 static const __u8 mi0360_sensor_init[][8] = {
268 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
269 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
270 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
272 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
273 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
274 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
275 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
287 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
288 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
290 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
291 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
293 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
295 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
297 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
300 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
302 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
304 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
306 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
308 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
309 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
310 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
311 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
313 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
314 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
315 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
316 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
317 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
318 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
321 static const __u8 mo4000_sensor_init[][8] = {
322 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
323 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
324 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
325 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
327 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
328 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
329 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
330 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
331 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
332 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
333 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
334 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
335 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
336 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
337 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
344 static const __u8 ov7660_sensor_init[][8] = {
345 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
346 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
347 /* Outformat ?? rawRGB */
348 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
349 /* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
350 * GAIN BLUE RED VREF */
351 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
352 /* GAIN BLUE RED VREF */
353 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
354 /* COM 1 BAVE GEAVE AECHH */
355 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
356 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
357 /* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
358 * AECH CLKRC COM7 COM8 */
359 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
360 /* AECH CLKRC COM7 COM8 */
361 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
362 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
363 /* HSTART HSTOP VSTRT VSTOP */
364 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
365 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
366 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
367 /* BOS GBOS GROS ROS (BGGR offset) */
368 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
369 * AEW AEB VPT BBIAS */
370 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
371 /* AEW AEB VPT BBIAS */
372 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
373 /* GbBIAS RSVD EXHCH EXHCL */
374 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
375 /* RBIAS ADVFL ASDVFH YAVE */
376 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
377 /* HSYST HSYEN HREF */
378 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
379 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
380 /* ADC ACOM OFON TSLB */
381 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
382 /* COM11 COM12 COM13 COM14 */
383 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
384 /* EDGE COM15 COM16 COM17 */
385 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
386 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
387 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
388 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
389 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
390 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
391 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
392 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
393 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
394 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
395 /* LCC1 LCC2 LCC3 LCC4 */
396 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
397 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
398 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
399 /* band gap reference [0..3] DBLV */
400 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
401 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
402 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
403 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
404 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
405 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
406 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
407 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
408 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
409 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
410 /****** (some exchanges in the win trace) ******/
411 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
412 /* bits[3..0]reserved */
413 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
414 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
415 /* VREF vertical frame ctrl */
416 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
417 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
418 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10},
421 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, */
422 /****** (some exchanges in the win trace) ******/
423 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
424 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
425 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
426 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
427 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, */
428 /****** (some exchanges in the win trace) ******/
429 /**********startsensor KO if changed !!****/
430 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
431 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
433 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
434 /* here may start the isoc exchanges */
437 /* reg0x04 reg0x07 reg 0x10 */
438 /* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
440 static const __u8 ov7648_sensor_init[][8] = {
441 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
442 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
443 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
444 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
445 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
446 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
448 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
449 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
450 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
451 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
452 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
453 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
454 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
455 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
456 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
457 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
458 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
459 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
460 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
461 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
462 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
463 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
464 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
465 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
466 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
467 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
468 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
469 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
470 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
471 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
472 * This is currently setting a
473 * blue tint, and some things more , i leave it here for future test if
474 * somene is having problems with color on this sensor
475 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
476 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
477 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
478 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
479 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
480 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
481 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
482 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
483 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
484 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
485 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
486 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
487 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
488 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
489 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
490 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
491 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
492 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
496 static const __u8 qtable4[] = {
497 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
498 0x06, 0x08, 0x0A, 0x11,
499 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
500 0x19, 0x19, 0x17, 0x15,
501 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
502 0x21, 0x2E, 0x21, 0x23,
503 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
504 0x25, 0x29, 0x2C, 0x29,
505 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
506 0x17, 0x1B, 0x29, 0x29,
507 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
508 0x29, 0x29, 0x29, 0x29,
509 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
510 0x29, 0x29, 0x29, 0x29,
511 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
512 0x29, 0x29, 0x29, 0x29
515 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
516 static void reg_r(struct gspca_dev *gspca_dev,
517 __u16 value, int len)
519 usb_control_msg(gspca_dev->dev,
520 usb_rcvctrlpipe(gspca_dev->dev, 0),
522 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
524 gspca_dev->usb_buf, len,
528 static void reg_w(struct gspca_dev *gspca_dev,
533 if (len <= sizeof gspca_dev->usb_buf) {
534 memcpy(gspca_dev->usb_buf, buffer, len);
535 usb_control_msg(gspca_dev->dev,
536 usb_sndctrlpipe(gspca_dev->dev, 0),
538 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
540 gspca_dev->usb_buf, len,
545 tmpbuf = kmalloc(len, GFP_KERNEL);
546 memcpy(tmpbuf, buffer, len);
547 usb_control_msg(gspca_dev->dev,
548 usb_sndctrlpipe(gspca_dev->dev, 0),
550 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
558 /* I2C write 2 bytes */
559 static void i2c_w2(struct gspca_dev *gspca_dev,
562 struct sd *sd = (struct sd *) gspca_dev;
566 mode[0] = sd->i2c_ctrl_reg | (2 << 4);
567 mode[1] = sd->i2c_base;
574 reg_w(gspca_dev, 0x08, mode, 8);
577 /* I2C write 8 bytes */
578 static void i2c_w8(struct gspca_dev *gspca_dev,
581 reg_w(gspca_dev, 0x08, buffer, 8);
585 /* read 5 bytes in gspca_dev->usb_buf */
586 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
588 struct sd *sd = (struct sd *) gspca_dev;
591 mode[0] = sd->i2c_ctrl_reg | 0x10;
592 mode[1] = sd->i2c_base;
599 i2c_w8(gspca_dev, mode);
600 mode[0] = sd->i2c_ctrl_reg | (5 << 4) | 0x02;
602 i2c_w8(gspca_dev, mode);
603 reg_r(gspca_dev, 0x0a, 5);
606 static int probesensor(struct gspca_dev *gspca_dev)
608 struct sd *sd = (struct sd *) gspca_dev;
610 static const __u8 datasend[] = { 2, 0 };
611 /* reg val1 val2 val3 val4 */
613 i2c_w2(gspca_dev, datasend);
614 /* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
617 reg_w(gspca_dev, 0x02, ®02, 1); /* Gpio on */
619 i2c_r5(gspca_dev, 0); /* read sensor id */
620 if (gspca_dev->usb_buf[0] == 0x02
621 && gspca_dev->usb_buf[1] == 0x09
622 && gspca_dev->usb_buf[2] == 0x01
623 && gspca_dev->usb_buf[3] == 0x00
624 && gspca_dev->usb_buf[4] == 0x00) {
625 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
626 sd->sensor = SENSOR_HV7131R;
627 return SENSOR_HV7131R;
629 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
630 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
631 gspca_dev->usb_buf[2]);
632 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
636 static int configure_gpio(struct gspca_dev *gspca_dev,
639 struct sd *sd = (struct sd *) gspca_dev;
643 static const __u8 reg9a_def[] =
644 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
645 static const __u8 reg9a_sn9c120[] = /* from win trace */
646 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
647 static const __u8 reg9a_sn9c325[] =
648 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
652 reg_w(gspca_dev, 0xf1, ®F1, 1);
654 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1);
655 /*fixme:jfm was [1] en v1*/
658 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
659 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
660 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 3);
661 switch (sd->customid) {
663 reg9a = reg9a_sn9c325;
666 reg9a = reg9a_sn9c120;
672 reg_w(gspca_dev, 0x9a, reg9a, 6);
674 data = 0x60; /*fixme:jfm 60 00 00 (3) */
675 reg_w(gspca_dev, 0xd4, &data, 1);
677 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
679 switch (sd->customid) {
680 case SN9C120: /* from win trace */
682 reg_w(gspca_dev, 0x01, &data, 1);
684 reg_w(gspca_dev, 0x17, &data, 1);
686 reg_w(gspca_dev, 0x01, &data, 1);
690 reg_w(gspca_dev, 0x01, &data, 1);
692 reg_w(gspca_dev, 0x17, &data, 1);
694 reg_w(gspca_dev, 0x01, &data, 1);
698 reg_w(gspca_dev, 0x01, &data, 1);
700 reg_w(gspca_dev, 0x17, &data, 1);
702 reg_w(gspca_dev, 0x01, &data, 1);
705 if (sd->sensor == SENSOR_HV7131R) {
706 if (probesensor(gspca_dev) < 0)
712 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
715 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
716 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
718 while (hv7131r_sensor_init[i][0]) {
719 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
722 i2c_w8(gspca_dev, SetSensorClk);
725 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
729 while (mi0360_sensor_init[i][0]) {
730 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
735 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
739 while (mo4000_sensor_init[i][0]) {
740 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
745 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
749 while (ov7648_sensor_init[i][0]) {
750 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
755 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
759 while (ov7660_sensor_init[i][0]) {
760 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
765 /* this function is called at probe time */
766 static int sd_config(struct gspca_dev *gspca_dev,
767 const struct usb_device_id *id)
769 struct sd *sd = (struct sd *) gspca_dev;
774 vendor = id->idVendor;
775 product = id->idProduct;
778 case 0x0458: /* Genius */
779 /* switch (product) {
781 sd->customid = SN9C120;
782 sd->sensor = SENSOR_MI0360;
783 sd->i2c_ctrl_reg = 0x81;
789 /* switch (product) {
792 sd->customid = SN9C105;
793 sd->sensor = SENSOR_OV7660;
794 sd->i2c_ctrl_reg = 0x81;
799 case 0x0471: /* Philips */
800 /* switch (product) {
804 sd->customid = SN9C105;
805 sd->sensor = SENSOR_MI0360;
806 sd->i2c_ctrl_reg = 0x81;
811 case 0x0c45: /* Sonix */
814 sd->customid = SN9C102P;
815 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
816 /* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
817 sd->i2c_ctrl_reg = 0x81;
820 /* case 0x607a: * from BW600.inf
821 sd->customid = SN9C102P;
822 sd->sensor = SENSOR_OV7648;
823 sd->i2c_ctrl_reg = 0x??;
827 sd->customid = SN9C102P;
828 sd->sensor = SENSOR_HV7131R;
829 sd->i2c_ctrl_reg = 0x81;
832 /* case 0x607e: * from BW600.inf
833 sd->customid = SN9C102P;
834 sd->sensor = SENSOR_OV7630;
835 sd->i2c_ctrl_reg = 0x??;
839 sd->customid = SN9C105;
840 sd->sensor = SENSOR_MI0360;
841 sd->i2c_ctrl_reg = 0x81;
844 /* case 0x60c8: * from BW600.inf
845 sd->customid = SN9C105;
846 sd->sensor = SENSOR_OM6801;
847 sd->i2c_ctrl_reg = 0x??;
850 /* case 0x60cc: * from BW600.inf
851 sd->customid = SN9C105;
852 sd->sensor = SENSOR_HV7131GP;
853 sd->i2c_ctrl_reg = 0x??;
857 sd->customid = SN9C105;
858 sd->sensor = SENSOR_MO4000;
859 sd->i2c_ctrl_reg = 0x81;
862 /* case 0x60ef: * from BW600.inf
863 sd->customid = SN9C105;
864 sd->sensor = SENSOR_ICM105C;
865 sd->i2c_ctrl_reg = 0x??;
868 /* case 0x60fa: * from BW600.inf
869 sd->customid = SN9C105;
870 sd->sensor = SENSOR_OV7648;
871 sd->i2c_ctrl_reg = 0x??;
875 sd->customid = SN9C105;
876 sd->sensor = SENSOR_OV7660;
877 sd->i2c_ctrl_reg = 0x81;
881 sd->customid = SN9C105;
882 sd->sensor = SENSOR_HV7131R;
883 sd->i2c_ctrl_reg = 0x81;
886 /* case 0x60fe: * from BW600.inf
887 sd->customid = SN9C105;
888 sd->sensor = SENSOR_OV7630;
889 sd->i2c_ctrl_reg = 0x??;
892 /* case 0x6108: * from BW600.inf
893 sd->customid = SN9C120;
894 sd->sensor = SENSOR_OM6801;
895 sd->i2c_ctrl_reg = 0x??;
898 /* case 0x6122: * from BW600.inf
899 sd->customid = SN9C110;
900 sd->sensor = SENSOR_ICM105C;
901 sd->i2c_ctrl_reg = 0x??;
905 /* sd->customid = SN9C110; * in BW600.inf */
906 sd->customid = SN9C325;
907 sd->sensor = SENSOR_OV7648;
908 sd->i2c_ctrl_reg = 0x81;
911 /* case 0x6123: * from BW600.inf
912 sd->customid = SN9C110;
913 sd->sensor = SENSOR_SanyoCCD;
914 sd->i2c_ctrl_reg = 0x??;
918 sd->customid = SN9C110;
919 sd->sensor = SENSOR_MO4000;
920 sd->i2c_ctrl_reg = 0x81;
923 /* case 0x612e: * from BW600.inf
924 sd->customid = SN9C110;
925 sd->sensor = SENSOR_OV7630;
926 sd->i2c_ctrl_reg = 0x??;
929 /* case 0x612f: * from BW600.inf
930 sd->customid = SN9C110;
931 sd->sensor = SENSOR_ICM105C;
932 sd->i2c_ctrl_reg = 0x??;
936 sd->customid = SN9C120;
937 sd->sensor = SENSOR_MI0360;
938 sd->i2c_ctrl_reg = 0x81;
942 sd->customid = SN9C120;
943 sd->sensor = SENSOR_MO4000;
944 sd->i2c_ctrl_reg = 0x81;
947 /* case 0x613a: * from BW600.inf
948 sd->customid = SN9C120;
949 sd->sensor = SENSOR_OV7648;
950 sd->i2c_ctrl_reg = 0x??;
954 sd->customid = SN9C120;
955 sd->sensor = SENSOR_OV7660;
956 sd->i2c_ctrl_reg = 0x81;
960 sd->customid = SN9C120;
961 sd->sensor = SENSOR_HV7131R;
962 sd->i2c_ctrl_reg = 0x81;
965 /* case 0x613e: * from BW600.inf
966 sd->customid = SN9C120;
967 sd->sensor = SENSOR_OV7630;
968 sd->i2c_ctrl_reg = 0x??;
974 if (sd->sensor < 0) {
975 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
980 cam = &gspca_dev->cam;
981 cam->dev_name = (char *) id->driver_info;
983 cam->cam_mode = vga_mode;
984 cam->nmodes = ARRAY_SIZE(vga_mode);
986 sd->qindex = 4; /* set the quantization table */
987 sd->brightness = BRIGHTNESS_DEF;
988 sd->contrast = CONTRAST_DEF;
989 sd->colors = COLOR_DEF;
990 sd->autogain = AUTOGAIN_DEF;
994 /* this function is called at open time */
995 static int sd_open(struct gspca_dev *gspca_dev)
997 struct sd *sd = (struct sd *) gspca_dev;
998 /* const __u8 *sn9c1xx; */
1000 __u8 regGpio[] = { 0x29, 0x74 };
1002 /* setup a selector by customid */
1004 reg_w(gspca_dev, 0xf1, ®F1, 1);
1005 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
1006 regF1 = gspca_dev->usb_buf[0];
1007 reg_w(gspca_dev, 0xf1, ®F1, 1);
1008 reg_r(gspca_dev, 0x00, 1);
1009 regF1 = gspca_dev->usb_buf[0];
1010 switch (sd->customid) {
1014 reg_w(gspca_dev, 0x02, ®Gpio[1], 1);
1019 reg_w(gspca_dev, 0x02, regGpio, 2);
1025 reg_w(gspca_dev, 0x02, ®Gpio[1], 1);
1031 reg_w(gspca_dev, 0x02, regGpio, 2);
1038 reg_w(gspca_dev, 0x02, ®Gpio[1], 1);
1043 reg_w(gspca_dev, 0xf1, ®F1, 1);
1048 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1051 struct sd *sd = (struct sd *) gspca_dev;
1052 static const __u8 doit[] = /* update sensor */
1053 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1054 static const __u8 sensorgo[] = /* sensor on */
1055 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1056 static const __u8 gainMo[] =
1057 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1059 switch (sd->sensor) {
1060 case SENSOR_HV7131R: {
1062 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1064 Expodoit[3] = expo >> 16;
1065 Expodoit[4] = expo >> 8;
1067 i2c_w8(gspca_dev, Expodoit);
1070 case SENSOR_MI0360: {
1071 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1072 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1076 else if (expo < 0x0001)
1078 expoMi[3] = expo >> 8;
1080 i2c_w8(gspca_dev, expoMi);
1081 i2c_w8(gspca_dev, doit);
1082 i2c_w8(gspca_dev, sensorgo);
1085 case SENSOR_MO4000: {
1087 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1089 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1093 else if (expo < 0x0001)
1095 expoMof[3] = (expo & 0x03fc) >> 2;
1096 i2c_w8(gspca_dev, expoMof);
1097 expoMo10[3] = ((expo & 0x1c00) >> 10)
1098 | ((expo & 0x0003) << 4);
1099 i2c_w8(gspca_dev, expoMo10);
1100 i2c_w8(gspca_dev, gainMo);
1101 PDEBUG(D_CONF, "set exposure %d",
1102 ((expoMo10[3] & 0x07) << 10)
1104 | ((expoMo10[3] & 0x30) >> 4));
1111 static void setbrightness(struct gspca_dev *gspca_dev)
1113 struct sd *sd = (struct sd *) gspca_dev;
1117 switch (sd->sensor) {
1118 case SENSOR_HV7131R:
1119 expo = sd->brightness << 4;
1120 if (expo > 0x002dc6c0)
1122 else if (expo < 0x02a0)
1124 sd->exposure = setexposure(gspca_dev, expo);
1127 expo = sd->brightness >> 4;
1128 sd->exposure = setexposure(gspca_dev, expo);
1131 expo = sd->brightness >> 4;
1132 sd->exposure = setexposure(gspca_dev, expo);
1138 k2 = sd->brightness >> 10;
1139 reg_w(gspca_dev, 0x96, &k2, 1);
1142 static void setcontrast(struct gspca_dev *gspca_dev)
1144 struct sd *sd = (struct sd *) gspca_dev;
1146 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1148 if (sd->sensor == SENSOR_OV7660)
1152 contrast[0] = (k2 + 1) >> 1;
1153 contrast[4] = (k2 + 1) / 5;
1154 reg_w(gspca_dev, 0x84, contrast, 6);
1157 static void setcolors(struct gspca_dev *gspca_dev)
1159 struct sd *sd = (struct sd *) gspca_dev;
1163 colour = sd->colors - 128;
1165 data = (colour + 32) & 0x7f; /* blue */
1167 data = (-colour + 32) & 0x7f; /* red */
1168 reg_w(gspca_dev, 0x05, &data, 1);
1171 /* -- start the camera -- */
1172 static void sd_start(struct gspca_dev *gspca_dev)
1174 struct sd *sd = (struct sd *) gspca_dev;
1179 const __u8 *sn9c1xx;
1181 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1182 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1183 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1184 static const __u8 CA_sn9c120[] =
1185 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1186 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1187 static const __u8 CE_sn9c325[] =
1188 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1190 sn9c1xx = sn_tb[(int) sd->sensor];
1191 configure_gpio(gspca_dev, sn9c1xx);
1193 /*fixme:jfm this sequence should appear at end of sd_start */
1196 reg_w(gspca_dev, 0x01, &data, 1); */
1197 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1198 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1199 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1200 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1201 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1202 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1203 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1204 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1205 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1206 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1207 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
1208 /*fixme:jfm end of ending sequence */
1209 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1210 if (sd->customid == SN9C325)
1214 reg_w(gspca_dev, 0x17, &data, 1);
1215 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1216 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1217 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1218 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
1219 if (sd->customid == SN9C325) {
1220 reg_w(gspca_dev, 0x20, regsn20_sn9c325, 0x11);
1221 for (i = 0; i < 8; i++)
1222 reg_w(gspca_dev, 0x84, reg84_sn9c325, 0x15);
1224 reg_w(gspca_dev, 0x9a, &data, 1);
1226 reg_w(gspca_dev, 0x99, &data, 1);
1228 reg_w(gspca_dev, 0x20, regsn20, 0x11);
1229 for (i = 0; i < 8; i++)
1230 reg_w(gspca_dev, 0x84, reg84, 0x15);
1232 reg_w(gspca_dev, 0x9a, &data, 1);
1234 reg_w(gspca_dev, 0x99, &data, 1);
1237 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1240 switch (sd->sensor) {
1241 case SENSOR_HV7131R:
1242 hv7131R_InitSensor(gspca_dev);
1244 reg1 = 0x46; /* 320 clk 48Mhz */
1246 reg1 = 0x06; /* 640 clk 24Mz */
1249 mi0360_InitSensor(gspca_dev);
1251 reg1 = 0x46; /* 320 clk 48Mhz */
1253 reg1 = 0x06; /* 640 clk 24Mz */
1256 mo4000_InitSensor(gspca_dev);
1258 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1259 reg1 = 0x06; /* clk 24Mz */
1261 reg17 = 0x22; /* 640 MCKSIZE */
1262 reg1 = 0x06; /* 640 clk 24Mz */
1268 ov7648_InitSensor(gspca_dev);
1275 /* case SENSOR_OV7660: */
1276 ov7660_InitSensor(gspca_dev);
1278 /* reg17 = 0x21; * 320 */
1282 reg17 = 0xa2; /* 640 */
1287 reg_w(gspca_dev, 0xc0, C0, 6);
1288 switch (sd->customid) {
1289 case SN9C120: /*jfm ?? */
1290 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1293 reg_w(gspca_dev, 0xca, CA, 4);
1296 switch (sd->customid) {
1297 case SN9C120: /*jfm ?? */
1299 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1302 reg_w(gspca_dev, 0xce, CE, 4);
1303 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1307 /* here change size mode 0 -> VGA; 1 -> CIF */
1308 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1309 reg_w(gspca_dev, 0x18, &data, 1);
1311 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1312 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1314 data = sn9c1xx[0x18] | (mode << 4);
1315 reg_w(gspca_dev, 0x18, &data, 1);
1317 reg_w(gspca_dev, 0x17, ®17, 1);
1318 reg_w(gspca_dev, 0x01, ®1, 1);
1319 setbrightness(gspca_dev);
1320 setcontrast(gspca_dev);
1323 static void sd_stopN(struct gspca_dev *gspca_dev)
1325 struct sd *sd = (struct sd *) gspca_dev;
1326 static const __u8 stophv7131[] =
1327 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1328 static const __u8 stopmi0360[] =
1329 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1332 const __u8 *sn9c1xx;
1335 switch (sd->sensor) {
1336 case SENSOR_HV7131R:
1337 i2c_w8(gspca_dev, stophv7131);
1341 i2c_w8(gspca_dev, stopmi0360);
1350 /* case SENSOR_OV7660: */
1353 sn9c1xx = sn_tb[(int) sd->sensor];
1354 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1355 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1356 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1357 reg_w(gspca_dev, 0x01, &data, 1);
1359 reg_w(gspca_dev, 0xf1, ®F1, 1);
1362 static void sd_stop0(struct gspca_dev *gspca_dev)
1366 static void sd_close(struct gspca_dev *gspca_dev)
1370 static void setautogain(struct gspca_dev *gspca_dev)
1372 struct sd *sd = (struct sd *) gspca_dev;
1373 /* Thanks S., without your advice, autobright should not work :) */
1376 __u8 luma_mean = 130;
1377 __u8 luma_delta = 20;
1379 delta = sd->avg_lum;
1380 if (delta < luma_mean - luma_delta ||
1381 delta > luma_mean + luma_delta) {
1382 switch (sd->sensor) {
1383 case SENSOR_HV7131R:
1384 expotimes = sd->exposure >> 8;
1385 expotimes += (luma_mean - delta) >> 4;
1388 sd->exposure = setexposure(gspca_dev,
1389 (unsigned int) (expotimes << 8));
1393 expotimes = sd->exposure;
1394 expotimes += (luma_mean - delta) >> 6;
1397 sd->exposure = setexposure(gspca_dev,
1398 (unsigned int) expotimes);
1399 setcolors(gspca_dev);
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);
1421 if (--sd->ag_cnt >= 0)
1423 sd->ag_cnt = AG_CNT_START;
1428 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1430 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1432 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1434 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1436 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1438 sd->avg_lum = avg_lum;
1439 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1440 setautogain(gspca_dev);
1443 if (gspca_dev->last_packet_type == LAST_PACKET) {
1445 /* put the JPEG 422 header */
1446 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1448 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1451 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1453 struct sd *sd = (struct sd *) gspca_dev;
1454 __u8 hexpo, mexpo, lexpo;
1456 switch (sd->sensor) {
1457 case SENSOR_HV7131R:
1458 /* read sensor exposure */
1459 i2c_r5(gspca_dev, 0x25);
1460 return (gspca_dev->usb_buf[0] << 16)
1461 | (gspca_dev->usb_buf[1] << 8)
1462 | gspca_dev->usb_buf[2];
1464 /* read sensor exposure */
1465 i2c_r5(gspca_dev, 0x09);
1466 return (gspca_dev->usb_buf[0] << 8)
1467 | gspca_dev->usb_buf[1];
1469 i2c_r5(gspca_dev, 0x0e);
1470 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1471 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1472 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1473 PDEBUG(D_CONF, "exposure %d",
1474 (hexpo << 10) | (mexpo << 2) | lexpo);
1475 return (hexpo << 10) | (mexpo << 2) | lexpo;
1477 /* case SENSOR_OV7660: */
1478 /* read sensor exposure */
1479 i2c_r5(gspca_dev, 0x04);
1480 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1481 lexpo = gspca_dev->usb_buf[0] & 0x02;
1482 i2c_r5(gspca_dev, 0x08);
1483 mexpo = gspca_dev->usb_buf[2];
1484 return (hexpo << 10) | (mexpo << 2) | lexpo;
1488 static void getbrightness(struct gspca_dev *gspca_dev)
1490 struct sd *sd = (struct sd *) gspca_dev;
1492 /* hardcoded registers seem not readable */
1493 switch (sd->sensor) {
1494 case SENSOR_HV7131R:
1495 /* sd->brightness = 0x7fff; */
1496 sd->brightness = getexposure(gspca_dev) >> 4;
1499 sd->brightness = getexposure(gspca_dev) << 4;
1502 /* sd->brightness = 0x1fff; */
1503 sd->brightness = getexposure(gspca_dev) << 4;
1508 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1510 struct sd *sd = (struct sd *) gspca_dev;
1512 sd->brightness = val;
1513 if (gspca_dev->streaming)
1514 setbrightness(gspca_dev);
1518 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1520 struct sd *sd = (struct sd *) gspca_dev;
1522 getbrightness(gspca_dev);
1523 *val = sd->brightness;
1527 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1529 struct sd *sd = (struct sd *) gspca_dev;
1532 if (gspca_dev->streaming)
1533 setcontrast(gspca_dev);
1537 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1539 struct sd *sd = (struct sd *) gspca_dev;
1541 *val = sd->contrast;
1545 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1547 struct sd *sd = (struct sd *) gspca_dev;
1550 if (gspca_dev->streaming)
1551 setcolors(gspca_dev);
1555 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1557 struct sd *sd = (struct sd *) gspca_dev;
1563 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1565 struct sd *sd = (struct sd *) gspca_dev;
1569 sd->ag_cnt = AG_CNT_START;
1575 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1577 struct sd *sd = (struct sd *) gspca_dev;
1579 *val = sd->autogain;
1583 /* sub-driver description */
1584 static const struct sd_desc sd_desc = {
1585 .name = MODULE_NAME,
1587 .nctrls = ARRAY_SIZE(sd_ctrls),
1588 .config = sd_config,
1594 .pkt_scan = sd_pkt_scan,
1597 /* -- module initialisation -- */
1598 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1599 static const __devinitdata struct usb_device_id device_table[] = {
1600 #ifndef CONFIG_USB_SN9C102
1601 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1602 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1603 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1604 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1605 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1607 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1608 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1609 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1610 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1611 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1612 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1613 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1614 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1615 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1616 #ifndef CONFIG_USB_SN9C102
1617 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1618 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1619 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1620 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1624 MODULE_DEVICE_TABLE(usb, device_table);
1626 /* -- device connect -- */
1627 static int sd_probe(struct usb_interface *intf,
1628 const struct usb_device_id *id)
1630 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1634 static struct usb_driver sd_driver = {
1635 .name = MODULE_NAME,
1636 .id_table = device_table,
1638 .disconnect = gspca_disconnect,
1641 /* -- module insert / remove -- */
1642 static int __init sd_mod_init(void)
1644 if (usb_register(&sd_driver) < 0)
1646 info("v%s registered", version);
1649 static void __exit sd_mod_exit(void)
1651 usb_deregister(&sd_driver);
1652 info("deregistered");
1655 module_init(sd_mod_init);
1656 module_exit(sd_mod_exit);