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, 5)
28 static const char version[] = "2.1.5";
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 static void reg_r(struct usb_device *dev,
517 __u8 *buffer, int len)
520 usb_rcvctrlpipe(dev, 0),
522 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
528 static void reg_w(struct usb_device *dev,
536 memcpy(tmpbuf, buffer, len);
538 usb_sndctrlpipe(dev, 0),
540 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
547 tmpbuf = kmalloc(len, GFP_KERNEL);
548 memcpy(tmpbuf, buffer, len);
550 usb_sndctrlpipe(dev, 0),
552 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
561 static void i2c_w2(struct gspca_dev *gspca_dev,
564 struct sd *sd = (struct sd *) gspca_dev;
565 struct usb_device *dev = gspca_dev->dev;
569 mode[0] = sd->i2c_ctrl_reg | (2 << 4);
570 mode[1] = sd->i2c_base;
577 reg_w(dev, 0x08, mode, 8);
581 static void i2c_w8(struct usb_device *dev, const __u8 *buffer)
583 reg_w(dev, 0x08, buffer, 8);
588 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg,
591 struct sd *sd = (struct sd *) gspca_dev;
592 struct usb_device *dev = gspca_dev->dev;
595 mode[0] = sd->i2c_ctrl_reg | 0x10;
596 mode[1] = sd->i2c_base;
604 mode[0] = sd->i2c_ctrl_reg | (5 << 4) | 0x02;
607 reg_r(dev, 0x0a, buffer, 5);
610 static int probesensor(struct gspca_dev *gspca_dev)
612 struct sd *sd = (struct sd *) gspca_dev;
613 struct usb_device *dev = gspca_dev->dev;
615 static const __u8 datasend[] = { 2, 0 };
616 /* reg val1 val2 val3 val4 */
619 i2c_w2(gspca_dev, datasend);
620 /* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
623 reg_w(dev, 0x02, ®02, 1); /* Gpio on */
625 i2c_r5(gspca_dev, 0, datarecd); /* read sensor id */
626 if (datarecd[0] == 0x02
627 && datarecd[1] == 0x09
628 && datarecd[2] == 0x01
629 && datarecd[3] == 0x00
630 && datarecd[4] == 0x00) {
631 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
632 sd->sensor = SENSOR_HV7131R;
633 return SENSOR_HV7131R;
635 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
636 datarecd[0], datarecd[1], datarecd[2]);
637 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
641 static int configure_gpio(struct gspca_dev *gspca_dev,
644 struct sd *sd = (struct sd *) gspca_dev;
645 struct usb_device *dev = gspca_dev->dev;
649 static const __u8 reg9a_def[] =
650 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
651 static const __u8 reg9a_sn9c120[] = /* from win trace */
652 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
653 static const __u8 reg9a_sn9c325[] =
654 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
658 reg_w(dev, 0xf1, ®F1, 1);
660 reg_w(dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
663 reg_w(dev, 0x01, &sn9c1xx[1], 2);
664 reg_w(dev, 0x08, &sn9c1xx[8], 2);
665 reg_w(dev, 0x17, &sn9c1xx[0x17], 3);
666 switch (sd->customid) {
668 reg9a = reg9a_sn9c325;
671 reg9a = reg9a_sn9c120;
677 reg_w(dev, 0x9a, reg9a, 6);
679 data = 0x60; /*fixme:jfm 60 00 00 (3) */
680 reg_w(dev, 0xd4, &data, 1);
682 reg_w(dev, 0x03, &sn9c1xx[3], 0x0f);
684 switch (sd->customid) {
685 case SN9C120: /* from win trace */
687 reg_w(dev, 0x01, &data, 1);
689 reg_w(dev, 0x17, &data, 1);
691 reg_w(dev, 0x01, &data, 1);
695 reg_w(dev, 0x01, &data, 1);
697 reg_w(dev, 0x17, &data, 1);
699 reg_w(dev, 0x01, &data, 1);
703 reg_w(dev, 0x01, &data, 1);
705 reg_w(dev, 0x17, &data, 1);
707 reg_w(dev, 0x01, &data, 1);
710 if (sd->sensor == SENSOR_HV7131R) {
711 if (probesensor(gspca_dev) < 0)
717 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
720 struct usb_device *dev = gspca_dev->dev;
721 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
722 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
724 while (hv7131r_sensor_init[i][0]) {
725 i2c_w8(dev, hv7131r_sensor_init[i]);
728 i2c_w8(dev, SetSensorClk);
731 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
734 struct usb_device *dev = gspca_dev->dev;
736 while (mi0360_sensor_init[i][0]) {
737 i2c_w8(dev, mi0360_sensor_init[i]);
742 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
745 struct usb_device *dev = gspca_dev->dev;
747 while (mo4000_sensor_init[i][0]) {
748 i2c_w8(dev, mo4000_sensor_init[i]);
753 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
755 struct usb_device *dev = gspca_dev->dev;
758 while (ov7648_sensor_init[i][0]) {
759 i2c_w8(dev, ov7648_sensor_init[i]);
764 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
767 struct usb_device *dev = gspca_dev->dev;
769 while (ov7660_sensor_init[i][0]) {
770 i2c_w8(dev, ov7660_sensor_init[i]);
775 /* this function is called at probe time */
776 static int sd_config(struct gspca_dev *gspca_dev,
777 const struct usb_device_id *id)
779 struct sd *sd = (struct sd *) gspca_dev;
784 vendor = id->idVendor;
785 product = id->idProduct;
788 case 0x0458: /* Genius */
789 /* switch (product) {
791 sd->customid = SN9C120;
792 sd->sensor = SENSOR_MI0360;
793 sd->i2c_ctrl_reg = 0x81;
799 /* switch (product) {
802 sd->customid = SN9C105;
803 sd->sensor = SENSOR_OV7660;
804 sd->i2c_ctrl_reg = 0x81;
809 case 0x0471: /* Philips */
810 /* switch (product) {
814 sd->customid = SN9C105;
815 sd->sensor = SENSOR_MI0360;
816 sd->i2c_ctrl_reg = 0x81;
821 case 0x0c45: /* Sonix */
824 sd->customid = SN9C102P;
825 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
826 /* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
827 sd->i2c_ctrl_reg = 0x81;
830 /* case 0x607a: * from BW600.inf
831 sd->customid = SN9C102P;
832 sd->sensor = SENSOR_OV7648;
833 sd->i2c_ctrl_reg = 0x??;
837 sd->customid = SN9C102P;
838 sd->sensor = SENSOR_HV7131R;
839 sd->i2c_ctrl_reg = 0x81;
842 /* case 0x607e: * from BW600.inf
843 sd->customid = SN9C102P;
844 sd->sensor = SENSOR_OV7630;
845 sd->i2c_ctrl_reg = 0x??;
849 sd->customid = SN9C105;
850 sd->sensor = SENSOR_MI0360;
851 sd->i2c_ctrl_reg = 0x81;
854 /* case 0x60c8: * from BW600.inf
855 sd->customid = SN9C105;
856 sd->sensor = SENSOR_OM6801;
857 sd->i2c_ctrl_reg = 0x??;
860 /* case 0x60cc: * from BW600.inf
861 sd->customid = SN9C105;
862 sd->sensor = SENSOR_HV7131GP;
863 sd->i2c_ctrl_reg = 0x??;
867 sd->customid = SN9C105;
868 sd->sensor = SENSOR_MO4000;
869 sd->i2c_ctrl_reg = 0x81;
872 /* case 0x60ef: * from BW600.inf
873 sd->customid = SN9C105;
874 sd->sensor = SENSOR_ICM105C;
875 sd->i2c_ctrl_reg = 0x??;
878 /* case 0x60fa: * from BW600.inf
879 sd->customid = SN9C105;
880 sd->sensor = SENSOR_OV7648;
881 sd->i2c_ctrl_reg = 0x??;
885 sd->customid = SN9C105;
886 sd->sensor = SENSOR_OV7660;
887 sd->i2c_ctrl_reg = 0x81;
891 sd->customid = SN9C105;
892 sd->sensor = SENSOR_HV7131R;
893 sd->i2c_ctrl_reg = 0x81;
896 /* case 0x60fe: * from BW600.inf
897 sd->customid = SN9C105;
898 sd->sensor = SENSOR_OV7630;
899 sd->i2c_ctrl_reg = 0x??;
902 /* case 0x6108: * from BW600.inf
903 sd->customid = SN9C120;
904 sd->sensor = SENSOR_OM6801;
905 sd->i2c_ctrl_reg = 0x??;
908 /* case 0x6122: * from BW600.inf
909 sd->customid = SN9C110;
910 sd->sensor = SENSOR_ICM105C;
911 sd->i2c_ctrl_reg = 0x??;
915 /* sd->customid = SN9C110; * in BW600.inf */
916 sd->customid = SN9C325;
917 sd->sensor = SENSOR_OV7648;
918 sd->i2c_ctrl_reg = 0x81;
921 /* case 0x6123: * from BW600.inf
922 sd->customid = SN9C110;
923 sd->sensor = SENSOR_SanyoCCD;
924 sd->i2c_ctrl_reg = 0x??;
928 sd->customid = SN9C110;
929 sd->sensor = SENSOR_MO4000;
930 sd->i2c_ctrl_reg = 0x81;
933 /* case 0x612e: * from BW600.inf
934 sd->customid = SN9C110;
935 sd->sensor = SENSOR_OV7630;
936 sd->i2c_ctrl_reg = 0x??;
939 /* case 0x612f: * from BW600.inf
940 sd->customid = SN9C110;
941 sd->sensor = SENSOR_ICM105C;
942 sd->i2c_ctrl_reg = 0x??;
946 sd->customid = SN9C120;
947 sd->sensor = SENSOR_MI0360;
948 sd->i2c_ctrl_reg = 0x81;
952 sd->customid = SN9C120;
953 sd->sensor = SENSOR_MO4000;
954 sd->i2c_ctrl_reg = 0x81;
957 /* case 0x613a: * from BW600.inf
958 sd->customid = SN9C120;
959 sd->sensor = SENSOR_OV7648;
960 sd->i2c_ctrl_reg = 0x??;
964 sd->customid = SN9C120;
965 sd->sensor = SENSOR_OV7660;
966 sd->i2c_ctrl_reg = 0x81;
970 sd->customid = SN9C120;
971 sd->sensor = SENSOR_HV7131R;
972 sd->i2c_ctrl_reg = 0x81;
975 /* case 0x613e: * from BW600.inf
976 sd->customid = SN9C120;
977 sd->sensor = SENSOR_OV7630;
978 sd->i2c_ctrl_reg = 0x??;
984 if (sd->sensor < 0) {
985 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
990 cam = &gspca_dev->cam;
991 cam->dev_name = (char *) id->driver_info;
993 cam->cam_mode = vga_mode;
994 cam->nmodes = ARRAY_SIZE(vga_mode);
996 sd->qindex = 4; /* set the quantization table */
997 sd->brightness = BRIGHTNESS_DEF;
998 sd->contrast = CONTRAST_DEF;
999 sd->colors = COLOR_DEF;
1000 sd->autogain = AUTOGAIN_DEF;
1004 /* this function is called at open time */
1005 static int sd_open(struct gspca_dev *gspca_dev)
1007 struct sd *sd = (struct sd *) gspca_dev;
1008 struct usb_device *dev = gspca_dev->dev;
1009 /* const __u8 *sn9c1xx; */
1011 __u8 regGpio[] = { 0x29, 0x74 };
1013 /* setup a selector by customid */
1015 reg_w(dev, 0xf1, ®F1, 1);
1016 reg_r(dev, 0x00, ®F1, 1); /* -> regF1 = 0x00 */
1017 reg_w(dev, 0xf1, ®F1, 1);
1018 reg_r(dev, 0x00, ®F1, 1);
1019 switch (sd->customid) {
1023 reg_w(dev, 0x02, ®Gpio[1], 1);
1028 reg_w(dev, 0x02, regGpio, 2);
1034 reg_w(dev, 0x02, ®Gpio[1], 1);
1040 reg_w(dev, 0x02, regGpio, 2);
1047 reg_w(dev, 0x02, ®Gpio[1], 1);
1052 reg_w(dev, 0xf1, ®F1, 1);
1057 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1060 struct sd *sd = (struct sd *) gspca_dev;
1061 static const __u8 doit[] = /* update sensor */
1062 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1063 static const __u8 sensorgo[] = /* sensor on */
1064 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1065 static const __u8 gainMo[] =
1066 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1068 switch (sd->sensor) {
1069 case SENSOR_HV7131R: {
1071 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1073 Expodoit[3] = expo >> 16;
1074 Expodoit[4] = expo >> 8;
1076 i2c_w8(gspca_dev->dev, Expodoit);
1079 case SENSOR_MI0360: {
1080 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1081 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1085 else if (expo < 0x0001)
1087 expoMi[3] = expo >> 8;
1089 i2c_w8(gspca_dev->dev, expoMi);
1090 i2c_w8(gspca_dev->dev, doit);
1091 i2c_w8(gspca_dev->dev, sensorgo);
1094 case SENSOR_MO4000: {
1096 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1098 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1102 else if (expo < 0x0001)
1104 expoMof[3] = (expo & 0x03fc) >> 2;
1105 i2c_w8(gspca_dev->dev, expoMof);
1106 expoMo10[3] = ((expo & 0x1c00) >> 10)
1107 | ((expo & 0x0003) << 4);
1108 i2c_w8(gspca_dev->dev, expoMo10);
1109 i2c_w8(gspca_dev->dev, gainMo);
1110 PDEBUG(D_CONF, "set exposure %d",
1111 ((expoMo10[3] & 0x07) << 10)
1113 | ((expoMo10[3] & 0x30) >> 4));
1120 static void setbrightness(struct gspca_dev *gspca_dev)
1122 struct sd *sd = (struct sd *) gspca_dev;
1126 switch (sd->sensor) {
1127 case SENSOR_HV7131R:
1128 expo = sd->brightness << 4;
1129 if (expo > 0x002dc6c0)
1131 else if (expo < 0x02a0)
1133 sd->exposure = setexposure(gspca_dev, expo);
1136 expo = sd->brightness >> 4;
1137 sd->exposure = setexposure(gspca_dev, expo);
1140 expo = sd->brightness >> 4;
1141 sd->exposure = setexposure(gspca_dev, expo);
1147 k2 = sd->brightness >> 10;
1148 reg_w(gspca_dev->dev, 0x96, &k2, 1);
1151 static void setcontrast(struct gspca_dev *gspca_dev)
1153 struct sd *sd = (struct sd *) gspca_dev;
1155 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1157 if (sd->sensor == SENSOR_OV7660)
1161 contrast[0] = (k2 + 1) >> 1;
1162 contrast[4] = (k2 + 1) / 5;
1163 reg_w(gspca_dev->dev, 0x84, contrast, 6);
1166 static void setcolors(struct gspca_dev *gspca_dev)
1168 struct sd *sd = (struct sd *) gspca_dev;
1172 colour = sd->colors - 128;
1174 data = (colour + 32) & 0x7f; /* blue */
1176 data = (-colour + 32) & 0x7f; /* red */
1177 reg_w(gspca_dev->dev, 0x05, &data, 1);
1180 /* -- start the camera -- */
1181 static void sd_start(struct gspca_dev *gspca_dev)
1183 struct sd *sd = (struct sd *) gspca_dev;
1184 struct usb_device *dev = gspca_dev->dev;
1189 const __u8 *sn9c1xx;
1191 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1192 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1193 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1194 static const __u8 CA_sn9c120[] =
1195 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1196 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1197 static const __u8 CE_sn9c325[] =
1198 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1200 sn9c1xx = sn_tb[(int) sd->sensor];
1201 configure_gpio(gspca_dev, sn9c1xx);
1203 /*fixme:jfm this sequence should appear at end of sd_start */
1206 reg_w(dev, 0x01, &data, 1); */
1207 reg_w(dev, 0x15, &sn9c1xx[0x15], 1);
1208 reg_w(dev, 0x16, &sn9c1xx[0x16], 1);
1209 reg_w(dev, 0x12, &sn9c1xx[0x12], 1);
1210 reg_w(dev, 0x13, &sn9c1xx[0x13], 1);
1211 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1212 reg_w(dev, 0xd2, &DC29[0], 1);
1213 reg_w(dev, 0xd3, &DC29[1], 1);
1214 reg_w(dev, 0xc6, &DC29[2], 1);
1215 reg_w(dev, 0xc7, &DC29[3], 1);
1216 reg_w(dev, 0xc8, &DC29[4], 1);
1217 reg_w(dev, 0xc9, &DC29[5], 1);
1218 /*fixme:jfm end of ending sequence */
1219 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1220 if (sd->customid == SN9C325)
1224 reg_w(dev, 0x17, &data, 1);
1225 reg_w(dev, 0x05, &sn9c1xx[5], 1);
1226 reg_w(dev, 0x07, &sn9c1xx[7], 1);
1227 reg_w(dev, 0x06, &sn9c1xx[6], 1);
1228 reg_w(dev, 0x14, &sn9c1xx[0x14], 1);
1229 if (sd->customid == SN9C325) {
1230 reg_w(dev, 0x20, regsn20_sn9c325, 0x11);
1231 for (i = 0; i < 8; i++)
1232 reg_w(dev, 0x84, reg84_sn9c325, 0x15);
1234 reg_w(dev, 0x9a, &data, 1);
1236 reg_w(dev, 0x99, &data, 1);
1238 reg_w(dev, 0x20, regsn20, 0x11);
1239 for (i = 0; i < 8; i++)
1240 reg_w(dev, 0x84, reg84, 0x15);
1242 reg_w(dev, 0x9a, &data, 1);
1244 reg_w(dev, 0x99, &data, 1);
1247 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1250 switch (sd->sensor) {
1251 case SENSOR_HV7131R:
1252 hv7131R_InitSensor(gspca_dev);
1254 reg1 = 0x46; /* 320 clk 48Mhz */
1256 reg1 = 0x06; /* 640 clk 24Mz */
1259 mi0360_InitSensor(gspca_dev);
1261 reg1 = 0x46; /* 320 clk 48Mhz */
1263 reg1 = 0x06; /* 640 clk 24Mz */
1266 mo4000_InitSensor(gspca_dev);
1268 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1269 reg1 = 0x06; /* clk 24Mz */
1271 reg17 = 0x22; /* 640 MCKSIZE */
1272 reg1 = 0x06; /* 640 clk 24Mz */
1278 ov7648_InitSensor(gspca_dev);
1285 /* case SENSOR_OV7660: */
1286 ov7660_InitSensor(gspca_dev);
1288 /* reg17 = 0x21; * 320 */
1292 reg17 = 0xa2; /* 640 */
1297 reg_w(dev, 0xc0, C0, 6);
1298 switch (sd->customid) {
1299 case SN9C120: /*jfm ?? */
1300 reg_w(dev, 0xca, CA_sn9c120, 4);
1303 reg_w(dev, 0xca, CA, 4);
1306 switch (sd->customid) {
1307 case SN9C120: /*jfm ?? */
1309 reg_w(dev, 0xce, CE_sn9c325, 4);
1312 reg_w(dev, 0xce, CE, 4);
1313 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1317 /* here change size mode 0 -> VGA; 1 -> CIF */
1318 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1319 reg_w(dev, 0x18, &data, 1);
1321 reg_w(dev, 0x100, qtable4, 0x40);
1322 reg_w(dev, 0x140, qtable4 + 0x40, 0x40);
1324 data = sn9c1xx[0x18] | (mode << 4);
1325 reg_w(dev, 0x18, &data, 1);
1327 reg_w(dev, 0x17, ®17, 1);
1328 reg_w(dev, 0x01, ®1, 1);
1329 setbrightness(gspca_dev);
1330 setcontrast(gspca_dev);
1333 static void sd_stopN(struct gspca_dev *gspca_dev)
1335 struct sd *sd = (struct sd *) gspca_dev;
1336 struct usb_device *dev = gspca_dev->dev;
1337 static const __u8 stophv7131[] =
1338 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1339 static const __u8 stopmi0360[] =
1340 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1343 const __u8 *sn9c1xx;
1346 switch (sd->sensor) {
1347 case SENSOR_HV7131R:
1348 i2c_w8(dev, stophv7131);
1352 i2c_w8(dev, stopmi0360);
1361 /* case SENSOR_OV7660: */
1364 sn9c1xx = sn_tb[(int) sd->sensor];
1365 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1366 reg_w(dev, 0x17, &sn9c1xx[0x17], 1);
1367 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1368 reg_w(dev, 0x01, &data, 1);
1370 reg_w(dev, 0xf1, ®F1, 1);
1373 static void sd_stop0(struct gspca_dev *gspca_dev)
1377 static void sd_close(struct gspca_dev *gspca_dev)
1381 static void setautogain(struct gspca_dev *gspca_dev)
1383 struct sd *sd = (struct sd *) gspca_dev;
1384 /* Thanks S., without your advice, autobright should not work :) */
1387 __u8 luma_mean = 130;
1388 __u8 luma_delta = 20;
1390 delta = sd->avg_lum;
1391 if (delta < luma_mean - luma_delta ||
1392 delta > luma_mean + luma_delta) {
1393 switch (sd->sensor) {
1394 case SENSOR_HV7131R:
1395 expotimes = sd->exposure >> 8;
1396 expotimes += (luma_mean - delta) >> 4;
1399 sd->exposure = setexposure(gspca_dev,
1400 (unsigned int) (expotimes << 8));
1404 expotimes = sd->exposure;
1405 expotimes += (luma_mean - delta) >> 6;
1408 sd->exposure = setexposure(gspca_dev,
1409 (unsigned int) expotimes);
1410 setcolors(gspca_dev);
1416 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1417 struct gspca_frame *frame, /* target */
1418 __u8 *data, /* isoc packet */
1419 int len) /* iso packet length */
1421 struct sd *sd = (struct sd *) gspca_dev;
1425 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1428 gspca_frame_add(gspca_dev, LAST_PACKET,
1429 frame, data, sof + 2);
1432 if (--sd->ag_cnt >= 0)
1434 sd->ag_cnt = AG_CNT_START;
1439 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1441 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1443 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1445 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1447 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1449 sd->avg_lum = avg_lum;
1450 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1451 setautogain(gspca_dev);
1454 if (gspca_dev->last_packet_type == LAST_PACKET) {
1456 /* put the JPEG 422 header */
1457 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1459 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1462 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1464 struct sd *sd = (struct sd *) gspca_dev;
1465 __u8 hexpo, mexpo, lexpo;
1468 switch (sd->sensor) {
1469 case SENSOR_HV7131R:
1470 /* read sensor exposure */
1471 i2c_r5(gspca_dev, 0x25, expo);
1472 return (expo[0] << 16) | (expo[1] << 8) | expo[2];
1474 /* read sensor exposure */
1475 i2c_r5(gspca_dev, 0x09, expo);
1476 return (expo[0] << 8) | expo[1];
1478 i2c_r5(gspca_dev, 0x0e, expo);
1479 hexpo = 0; /* expo[1] & 0x07; */
1480 mexpo = 0x40; /* expo[2] &0xff; */
1481 lexpo = (expo[1] & 0x30) >> 4;
1482 PDEBUG(D_CONF, "exposure %d",
1483 (hexpo << 10) | (mexpo << 2) | lexpo);
1484 return (hexpo << 10) | (mexpo << 2) | lexpo;
1486 /* case SENSOR_OV7660: */
1487 /* read sensor exposure */
1488 i2c_r5(gspca_dev, 0x04, expo);
1489 hexpo = expo[3] & 0x2f;
1490 lexpo = expo[0] & 0x02;
1491 i2c_r5(gspca_dev, 0x08, expo);
1493 return (hexpo << 10) | (mexpo << 2) | lexpo;
1497 static void getbrightness(struct gspca_dev *gspca_dev)
1499 struct sd *sd = (struct sd *) gspca_dev;
1501 /* hardcoded registers seem not readable */
1502 switch (sd->sensor) {
1503 case SENSOR_HV7131R:
1504 /* sd->brightness = 0x7fff; */
1505 sd->brightness = getexposure(gspca_dev) >> 4;
1508 sd->brightness = getexposure(gspca_dev) << 4;
1511 /* sd->brightness = 0x1fff; */
1512 sd->brightness = getexposure(gspca_dev) << 4;
1517 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1519 struct sd *sd = (struct sd *) gspca_dev;
1521 sd->brightness = val;
1522 if (gspca_dev->streaming)
1523 setbrightness(gspca_dev);
1527 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1529 struct sd *sd = (struct sd *) gspca_dev;
1531 getbrightness(gspca_dev);
1532 *val = sd->brightness;
1536 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1538 struct sd *sd = (struct sd *) gspca_dev;
1541 if (gspca_dev->streaming)
1542 setcontrast(gspca_dev);
1546 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1548 struct sd *sd = (struct sd *) gspca_dev;
1550 *val = sd->contrast;
1554 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1556 struct sd *sd = (struct sd *) gspca_dev;
1559 if (gspca_dev->streaming)
1560 setcolors(gspca_dev);
1564 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1566 struct sd *sd = (struct sd *) gspca_dev;
1572 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1574 struct sd *sd = (struct sd *) gspca_dev;
1578 sd->ag_cnt = AG_CNT_START;
1584 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1586 struct sd *sd = (struct sd *) gspca_dev;
1588 *val = sd->autogain;
1592 /* sub-driver description */
1593 static const struct sd_desc sd_desc = {
1594 .name = MODULE_NAME,
1596 .nctrls = ARRAY_SIZE(sd_ctrls),
1597 .config = sd_config,
1603 .pkt_scan = sd_pkt_scan,
1606 /* -- module initialisation -- */
1607 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1608 static const __devinitdata struct usb_device_id device_table[] = {
1609 #ifndef CONFIG_USB_SN9C102
1610 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1611 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1612 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1613 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1614 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1616 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1617 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1618 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1619 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1620 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1621 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1622 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1623 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1624 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1625 #ifndef CONFIG_USB_SN9C102
1626 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1627 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1628 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1629 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1633 MODULE_DEVICE_TABLE(usb, device_table);
1635 /* -- device connect -- */
1636 static int sd_probe(struct usb_interface *intf,
1637 const struct usb_device_id *id)
1639 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1643 static struct usb_driver sd_driver = {
1644 .name = MODULE_NAME,
1645 .id_table = device_table,
1647 .disconnect = gspca_disconnect,
1650 /* -- module insert / remove -- */
1651 static int __init sd_mod_init(void)
1653 if (usb_register(&sd_driver) < 0)
1655 info("v%s registered", version);
1658 static void __exit sd_mod_exit(void)
1660 usb_deregister(&sd_driver);
1661 info("deregistered");
1664 module_init(sd_mod_init);
1665 module_exit(sd_mod_exit);