V4L/DVB (8513): gspca: Set the specific per webcam information in driver_info.
[linux-2.6/btrfs-unstable.git] / drivers / media / video / gspca / sonixj.c
blob46f2cf66d48f87d71920e8a175b5c7886ee69d2e
1 /*
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
10 * any later version.
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"
24 #include "gspca.h"
25 #include "jpeg.h"
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 */
32 struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
35 int avg_lum;
36 unsigned int exposure;
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
43 signed char ag_cnt;
44 #define AG_CNT_START 13
46 char qindex;
47 unsigned char bridge;
48 #define BRIDGE_SN9C102P 0
49 #define BRIDGE_SN9C105 1
50 #define BRIDGE_SN9C110 2
51 #define BRIDGE_SN9C120 3
52 #define BRIDGE_SN9C325 4
53 char sensor; /* Type of image sensor chip */
54 #define SENSOR_HV7131R 0
55 #define SENSOR_MI0360 1
56 #define SENSOR_MO4000 2
57 #define SENSOR_OV7648 3
58 #define SENSOR_OV7660 4
59 unsigned char i2c_base;
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72 static struct ctrl sd_ctrls[] = {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 0xffff,
80 .step = 1,
81 #define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 127,
94 .step = 1,
95 #define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 255,
108 .step = 1,
109 #define COLOR_DEF 127
110 .default_value = COLOR_DEF,
112 .set = sd_setcolors,
113 .get = sd_getcolors,
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
123 #define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
126 .set = sd_setautogain,
127 .get = sd_getautogain,
131 static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 160,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 320,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 640,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 0},
149 /*Data from sn9c102p+hv71331r */
150 static const __u8 sn_hv7131[] = {
151 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
152 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
153 /* rega regb regc regd rege regf reg10 reg11 */
154 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
155 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
156 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
157 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161 static const __u8 sn_mi0360[] = {
162 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
164 /* rega regb regc regd rege regf reg10 reg11 */
165 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
166 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
167 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
168 /* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
172 static const __u8 sn_mo4000[] = {
173 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
174 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
175 /* reg9 rega regb regc regd rege regf reg10 reg11*/
176 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
177 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
178 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
179 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
181 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
182 0xd3, 0xdf, 0xea, 0xf5
185 static const __u8 sn_ov7648[] = {
186 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
187 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
188 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
191 static const __u8 sn_ov7660[] = {
192 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
193 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
194 /* reg9 rega regb regc regd rege regf reg10 reg11*/
195 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
196 /* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
197 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
198 /* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
202 /* sequence specific to the sensors - !! index = SENSOR_xxx */
203 static const __u8 *sn_tb[] = {
204 sn_hv7131,
205 sn_mi0360,
206 sn_mo4000,
207 sn_ov7648,
208 sn_ov7660
211 static const __u8 regsn20[] = {
212 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
213 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
215 static const __u8 regsn20_sn9c120[] = {
216 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
217 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
219 static const __u8 regsn20_sn9c325[] = {
220 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
221 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
224 static const __u8 reg84[] = {
225 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
226 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
227 /* 0x00, 0x00, 0x00, 0x00, 0x00 */
228 0xf7, 0x0f, 0x0a, 0x00, 0x00
230 static const __u8 reg84_sn9c120_1[] = {
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x0c, 0x00, 0x00
235 static const __u8 reg84_sn9c120_2[] = {
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x0c, 0x02, 0x3b
240 static const __u8 reg84_sn9c120_3[] = {
241 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
242 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
243 0xf5, 0x0f, 0x0c, 0x02, 0x3b
245 static const __u8 reg84_sn9c325[] = {
246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
248 0xf8, 0x0f, 0x00, 0x00, 0x00
251 static const __u8 hv7131r_sensor_init[][8] = {
252 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
253 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
254 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
255 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
258 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
262 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
263 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
264 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
267 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
269 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
270 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
272 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
282 static const __u8 mi0360_sensor_init[][8] = {
283 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
287 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
288 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
305 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
306 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
308 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
310 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
312 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
315 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
317 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
318 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
319 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
321 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
323 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
324 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
325 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
326 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
328 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
329 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
330 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
331 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
332 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
333 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
336 static const __u8 mo4000_sensor_init[][8] = {
337 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
359 static const __u8 ov7660_sensor_init[][8] = {
360 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
361 /* (delay 20ms) */
362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
363 /* Outformat ?? rawRGB */
364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
366 /* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
367 /* GAIN BLUE RED VREF */
368 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
369 /* COM 1 BAVE GEAVE AECHH */
370 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
371 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
372 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
373 /* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
374 /* AECH CLKRC COM7 COM8 */
375 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
376 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
377 /* HSTART HSTOP VSTRT VSTOP */
378 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
379 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
380 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
381 /* BOS GBOS GROS ROS (BGGR offset) */
382 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
383 /* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
384 /* AEW AEB VPT BBIAS */
385 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
386 /* GbBIAS RSVD EXHCH EXHCL */
387 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
388 /* RBIAS ADVFL ASDVFH YAVE */
389 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
390 /* HSYST HSYEN HREF */
391 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
392 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
393 /* ADC ACOM OFON TSLB */
394 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
395 /* COM11 COM12 COM13 COM14 */
396 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
397 /* EDGE COM15 COM16 COM17 */
398 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
400 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
402 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
403 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
404 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
406 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
408 /* LCC1 LCC2 LCC3 LCC4 */
409 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
410 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
411 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
412 /* band gap reference [0..3] DBLV */
413 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
420 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
421 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
422 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
423 /****** (some exchanges in the win trace) ******/
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 /* bits[3..0]reserved */
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
428 /* VREF vertical frame ctrl */
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
431 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
433 /* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
434 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
435 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
436 /****** (some exchanges in the win trace) ******/
437 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
438 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
439 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
441 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
442 /****** (some exchanges in the win trace) ******/
443 /**********startsensor KO if changed !!****/
444 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
448 /* here may start the isoc exchanges */
451 /* reg0x04 reg0x07 reg 0x10 */
452 /* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
454 static const __u8 ov7648_sensor_init[][8] = {
455 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
456 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
459 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
460 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
461 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
462 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
464 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
465 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
466 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
467 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
468 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
469 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
471 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
472 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
473 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
474 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
475 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
476 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
477 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
478 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
479 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
480 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
481 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
482 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
483 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
484 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
486 * This is currently setting a
487 * blue tint, and some things more , i leave it here for future test if
488 * somene is having problems with color on this sensor
489 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
492 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
502 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
503 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
504 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
505 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
506 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
510 static const __u8 qtable4[] = {
511 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
512 0x06, 0x08, 0x0A, 0x11,
513 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
514 0x19, 0x19, 0x17, 0x15,
515 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
516 0x21, 0x2E, 0x21, 0x23,
517 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
518 0x25, 0x29, 0x2C, 0x29,
519 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
520 0x17, 0x1B, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29
529 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
530 static void reg_r(struct gspca_dev *gspca_dev,
531 __u16 value, int len)
533 usb_control_msg(gspca_dev->dev,
534 usb_rcvctrlpipe(gspca_dev->dev, 0),
536 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
537 value, 0,
538 gspca_dev->usb_buf, len,
539 500);
540 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
543 static void reg_w1(struct gspca_dev *gspca_dev,
544 __u16 value,
545 __u8 data)
547 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
548 gspca_dev->usb_buf[0] = data;
549 usb_control_msg(gspca_dev->dev,
550 usb_sndctrlpipe(gspca_dev->dev, 0),
551 0x08,
552 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
553 value,
555 gspca_dev->usb_buf, 1,
556 500);
558 static void reg_w(struct gspca_dev *gspca_dev,
559 __u16 value,
560 const __u8 *buffer,
561 int len)
563 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
564 value, buffer[0], buffer[1]);
565 if (len <= sizeof gspca_dev->usb_buf) {
566 memcpy(gspca_dev->usb_buf, buffer, len);
567 usb_control_msg(gspca_dev->dev,
568 usb_sndctrlpipe(gspca_dev->dev, 0),
569 0x08,
570 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
571 value, 0,
572 gspca_dev->usb_buf, len,
573 500);
574 } else {
575 __u8 *tmpbuf;
577 tmpbuf = kmalloc(len, GFP_KERNEL);
578 memcpy(tmpbuf, buffer, len);
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
581 0x08,
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
583 value, 0,
584 tmpbuf, len,
585 500);
586 kfree(tmpbuf);
590 /* I2C write 1 byte */
591 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
593 struct sd *sd = (struct sd *) gspca_dev;
595 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
596 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
597 gspca_dev->usb_buf[1] = sd->i2c_base;
598 gspca_dev->usb_buf[2] = reg;
599 gspca_dev->usb_buf[3] = val;
600 gspca_dev->usb_buf[4] = 0;
601 gspca_dev->usb_buf[5] = 0;
602 gspca_dev->usb_buf[6] = 0;
603 gspca_dev->usb_buf[7] = 0x10;
604 usb_control_msg(gspca_dev->dev,
605 usb_sndctrlpipe(gspca_dev->dev, 0),
606 0x08,
607 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
608 0x08, /* value = i2c */
610 gspca_dev->usb_buf, 8,
611 500);
614 /* I2C write 8 bytes */
615 static void i2c_w8(struct gspca_dev *gspca_dev,
616 const __u8 *buffer)
618 memcpy(gspca_dev->usb_buf, buffer, 8);
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
621 0x08,
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
623 0x08, 0, /* value, index */
624 gspca_dev->usb_buf, 8,
625 500);
628 /* read 5 bytes in gspca_dev->usb_buf */
629 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
631 struct sd *sd = (struct sd *) gspca_dev;
632 __u8 mode[8];
634 mode[0] = 0x81 | 0x10;
635 mode[1] = sd->i2c_base;
636 mode[2] = reg;
637 mode[3] = 0;
638 mode[4] = 0;
639 mode[5] = 0;
640 mode[6] = 0;
641 mode[7] = 0x10;
642 i2c_w8(gspca_dev, mode);
643 msleep(2);
644 mode[0] = 0x81 | (5 << 4) | 0x02;
645 mode[2] = 0;
646 i2c_w8(gspca_dev, mode);
647 msleep(2);
648 reg_r(gspca_dev, 0x0a, 5);
651 static int probesensor(struct gspca_dev *gspca_dev)
653 struct sd *sd = (struct sd *) gspca_dev;
655 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
656 msleep(10);
657 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
658 msleep(10);
659 i2c_r5(gspca_dev, 0); /* read sensor id */
660 if (gspca_dev->usb_buf[0] == 0x02
661 && gspca_dev->usb_buf[1] == 0x09
662 && gspca_dev->usb_buf[2] == 0x01
663 && gspca_dev->usb_buf[3] == 0x00
664 && gspca_dev->usb_buf[4] == 0x00) {
665 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
666 sd->sensor = SENSOR_HV7131R;
667 return SENSOR_HV7131R;
669 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
670 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
671 gspca_dev->usb_buf[2]);
672 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
673 return -ENODEV;
676 static int configure_gpio(struct gspca_dev *gspca_dev,
677 const __u8 *sn9c1xx)
679 struct sd *sd = (struct sd *) gspca_dev;
680 const __u8 *reg9a;
681 static const __u8 reg9a_def[] =
682 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
683 static const __u8 reg9a_sn9c120[] = /* from win trace */
684 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
685 static const __u8 reg9a_sn9c325[] =
686 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
688 reg_w1(gspca_dev, 0xf1, 0x00);
689 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
691 /* configure gpio */
692 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
693 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
694 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
695 switch (sd->bridge) {
696 case BRIDGE_SN9C325:
697 reg9a = reg9a_sn9c325;
698 break;
699 case BRIDGE_SN9C120:
700 reg9a = reg9a_sn9c120;
701 break;
702 default:
703 reg9a = reg9a_def;
704 break;
706 reg_w(gspca_dev, 0x9a, reg9a, 6);
708 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
710 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
712 switch (sd->bridge) {
713 case BRIDGE_SN9C120: /* from win trace */
714 reg_w1(gspca_dev, 0x01, 0x61);
715 reg_w1(gspca_dev, 0x17, 0x20);
716 reg_w1(gspca_dev, 0x01, 0x60);
717 break;
718 case BRIDGE_SN9C325:
719 reg_w1(gspca_dev, 0x01, 0x43);
720 reg_w1(gspca_dev, 0x17, 0xae);
721 reg_w1(gspca_dev, 0x01, 0x42);
722 break;
723 default:
724 reg_w1(gspca_dev, 0x01, 0x43);
725 reg_w1(gspca_dev, 0x17, 0x61);
726 reg_w1(gspca_dev, 0x01, 0x42);
729 if (sd->sensor == SENSOR_HV7131R) {
730 if (probesensor(gspca_dev) < 0)
731 return -ENODEV;
733 return 0;
736 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
738 int i = 0;
739 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
740 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
742 while (hv7131r_sensor_init[i][0]) {
743 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
744 i++;
746 i2c_w8(gspca_dev, SetSensorClk);
749 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
751 int i = 0;
753 while (mi0360_sensor_init[i][0]) {
754 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
755 i++;
759 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
761 int i = 0;
763 while (mo4000_sensor_init[i][0]) {
764 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
765 i++;
769 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
771 int i = 0;
773 while (ov7648_sensor_init[i][0]) {
774 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
775 i++;
779 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
781 int i = 0;
783 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
784 i++;
785 msleep(20);
786 while (ov7660_sensor_init[i][0]) {
787 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
788 i++;
792 /* this function is called at probe time */
793 static int sd_config(struct gspca_dev *gspca_dev,
794 const struct usb_device_id *id)
796 struct sd *sd = (struct sd *) gspca_dev;
797 struct cam *cam;
799 cam = &gspca_dev->cam;
800 cam->epaddr = 0x01;
801 cam->cam_mode = vga_mode;
802 cam->nmodes = ARRAY_SIZE(vga_mode);
804 sd->bridge = id->driver_info >> 16;
805 sd->sensor = id->driver_info >> 8;
806 sd->i2c_base = id->driver_info;
808 sd->qindex = 4; /* set the quantization table */
809 sd->brightness = BRIGHTNESS_DEF;
810 sd->contrast = CONTRAST_DEF;
811 sd->colors = COLOR_DEF;
812 sd->autogain = AUTOGAIN_DEF;
813 return 0;
816 /* this function is called at open time */
817 static int sd_open(struct gspca_dev *gspca_dev)
819 struct sd *sd = (struct sd *) gspca_dev;
820 /* const __u8 *sn9c1xx; */
821 __u8 regGpio[] = { 0x29, 0x74 };
822 __u8 regF1;
824 /* setup a selector by bridge */
825 reg_w1(gspca_dev, 0xf1, 0x01);
826 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
827 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
828 reg_r(gspca_dev, 0x00, 1);
829 regF1 = gspca_dev->usb_buf[0];
830 switch (sd->bridge) {
831 case BRIDGE_SN9C102P:
832 if (regF1 != 0x11)
833 return -ENODEV;
834 reg_w1(gspca_dev, 0x02, regGpio[1]);
835 break;
836 case BRIDGE_SN9C105:
837 if (regF1 != 0x11)
838 return -ENODEV;
839 reg_w(gspca_dev, 0x02, regGpio, 2);
840 break;
841 case BRIDGE_SN9C120:
842 if (regF1 != 0x12)
843 return -ENODEV;
844 regGpio[1] = 0x70;
845 reg_w(gspca_dev, 0x02, regGpio, 2);
846 break;
847 default:
848 /* case BRIDGE_SN9C110: */
849 /* case BRIDGE_SN9C325: */
850 if (regF1 != 0x12)
851 return -ENODEV;
852 reg_w1(gspca_dev, 0x02, 0x62);
853 break;
856 reg_w1(gspca_dev, 0xf1, 0x01);
858 return 0;
861 static unsigned int setexposure(struct gspca_dev *gspca_dev,
862 unsigned int expo)
864 struct sd *sd = (struct sd *) gspca_dev;
865 static const __u8 doit[] = /* update sensor */
866 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
867 static const __u8 sensorgo[] = /* sensor on */
868 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
869 static const __u8 gainMo[] =
870 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
872 switch (sd->sensor) {
873 case SENSOR_HV7131R: {
874 __u8 Expodoit[] =
875 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
877 Expodoit[3] = expo >> 16;
878 Expodoit[4] = expo >> 8;
879 Expodoit[5] = expo;
880 i2c_w8(gspca_dev, Expodoit);
881 break;
883 case SENSOR_MI0360: {
884 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
885 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
887 if (expo > 0x0635)
888 expo = 0x0635;
889 else if (expo < 0x0001)
890 expo = 0x0001;
891 expoMi[3] = expo >> 8;
892 expoMi[4] = expo;
893 i2c_w8(gspca_dev, expoMi);
894 i2c_w8(gspca_dev, doit);
895 i2c_w8(gspca_dev, sensorgo);
896 break;
898 case SENSOR_MO4000: {
899 __u8 expoMof[] =
900 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
901 __u8 expoMo10[] =
902 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
904 if (expo > 0x1fff)
905 expo = 0x1fff;
906 else if (expo < 0x0001)
907 expo = 0x0001;
908 expoMof[3] = (expo & 0x03fc) >> 2;
909 i2c_w8(gspca_dev, expoMof);
910 expoMo10[3] = ((expo & 0x1c00) >> 10)
911 | ((expo & 0x0003) << 4);
912 i2c_w8(gspca_dev, expoMo10);
913 i2c_w8(gspca_dev, gainMo);
914 PDEBUG(D_CONF, "set exposure %d",
915 ((expoMo10[3] & 0x07) << 10)
916 | (expoMof[3] << 2)
917 | ((expoMo10[3] & 0x30) >> 4));
918 break;
921 return expo;
924 static void setbrightness(struct gspca_dev *gspca_dev)
926 struct sd *sd = (struct sd *) gspca_dev;
927 unsigned int expo;
928 __u8 k2;
930 switch (sd->sensor) {
931 case SENSOR_HV7131R:
932 expo = sd->brightness << 4;
933 if (expo > 0x002dc6c0)
934 expo = 0x002dc6c0;
935 else if (expo < 0x02a0)
936 expo = 0x02a0;
937 sd->exposure = setexposure(gspca_dev, expo);
938 break;
939 case SENSOR_MI0360:
940 expo = sd->brightness >> 4;
941 sd->exposure = setexposure(gspca_dev, expo);
942 break;
943 case SENSOR_MO4000:
944 expo = sd->brightness >> 4;
945 sd->exposure = setexposure(gspca_dev, expo);
946 break;
947 case SENSOR_OV7660:
948 return; /*jfm??*/
951 k2 = sd->brightness >> 10;
952 reg_w1(gspca_dev, 0x96, k2);
955 static void setcontrast(struct gspca_dev *gspca_dev)
957 struct sd *sd = (struct sd *) gspca_dev;
958 __u8 k2;
959 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
961 if (sd->sensor == SENSOR_OV7660)
962 return; /*jfm??*/
963 k2 = sd->contrast;
964 contrast[2] = k2;
965 contrast[0] = (k2 + 1) >> 1;
966 contrast[4] = (k2 + 1) / 5;
967 reg_w(gspca_dev, 0x84, contrast, 6);
970 static void setcolors(struct gspca_dev *gspca_dev)
972 struct sd *sd = (struct sd *) gspca_dev;
973 __u8 data;
974 int colour;
976 colour = sd->colors - 128;
977 if (colour > 0)
978 data = (colour + 32) & 0x7f; /* blue */
979 else
980 data = (-colour + 32) & 0x7f; /* red */
981 reg_w1(gspca_dev, 0x05, data);
984 /* -- start the camera -- */
985 static void sd_start(struct gspca_dev *gspca_dev)
987 struct sd *sd = (struct sd *) gspca_dev;
988 int i;
989 __u8 data;
990 __u8 reg1;
991 __u8 reg17;
992 const __u8 *sn9c1xx;
993 int mode;
994 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
995 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
996 static const __u8 CA_sn9c120[] =
997 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
998 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
999 static const __u8 CE_sn9c325[] =
1000 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1002 sn9c1xx = sn_tb[(int) sd->sensor];
1003 configure_gpio(gspca_dev, sn9c1xx);
1005 /*fixme:jfm this sequence should appear at end of sd_start */
1006 /* with
1007 reg_w1(gspca_dev, 0x01, 0x44); */
1008 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1009 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1010 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1011 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1012 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1013 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1014 reg_w1(gspca_dev, 0xd3, 0x50);
1015 reg_w1(gspca_dev, 0xc6, 0x00);
1016 reg_w1(gspca_dev, 0xc7, 0x00);
1017 reg_w1(gspca_dev, 0xc8, 0x50);
1018 reg_w1(gspca_dev, 0xc9, 0x3c);
1019 /*fixme:jfm end of ending sequence */
1020 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1021 switch (sd->bridge) {
1022 case BRIDGE_SN9C325:
1023 data = 0xae;
1024 break;
1025 case BRIDGE_SN9C120:
1026 data = 0xa0;
1027 break;
1028 default:
1029 data = 0x60;
1030 break;
1032 reg_w1(gspca_dev, 0x17, data);
1033 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1034 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1035 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1036 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1037 switch (sd->bridge) {
1038 case BRIDGE_SN9C325:
1039 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1040 sizeof regsn20_sn9c325);
1041 for (i = 0; i < 8; i++)
1042 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1043 sizeof reg84_sn9c325);
1044 reg_w1(gspca_dev, 0x9a, 0x0a);
1045 reg_w1(gspca_dev, 0x99, 0x60);
1046 break;
1047 case BRIDGE_SN9C120:
1048 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1049 sizeof regsn20_sn9c120);
1050 for (i = 0; i < 2; i++)
1051 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1052 sizeof reg84_sn9c120_1);
1053 for (i = 0; i < 6; i++)
1054 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1055 sizeof reg84_sn9c120_2);
1056 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1057 sizeof reg84_sn9c120_3);
1058 reg_w1(gspca_dev, 0x9a, 0x05);
1059 reg_w1(gspca_dev, 0x99, 0x5b);
1060 break;
1061 default:
1062 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1063 for (i = 0; i < 8; i++)
1064 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1065 reg_w1(gspca_dev, 0x9a, 0x08);
1066 reg_w1(gspca_dev, 0x99, 0x59);
1067 break;
1070 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1071 if (mode)
1072 reg1 = 0x46; /* 320 clk 48Mhz */
1073 else
1074 reg1 = 0x06; /* 640 clk 24Mz */
1075 reg17 = 0x61;
1076 switch (sd->sensor) {
1077 case SENSOR_HV7131R:
1078 hv7131R_InitSensor(gspca_dev);
1079 break;
1080 case SENSOR_MI0360:
1081 mi0360_InitSensor(gspca_dev);
1082 break;
1083 case SENSOR_MO4000:
1084 mo4000_InitSensor(gspca_dev);
1085 if (mode) {
1086 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1087 reg1 = 0x06; /* clk 24Mz */
1088 } else {
1089 reg17 = 0x22; /* 640 MCKSIZE */
1090 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1092 break;
1093 case SENSOR_OV7648:
1094 ov7648_InitSensor(gspca_dev);
1095 reg17 = 0xa2;
1096 reg1 = 0x44;
1097 /* if (mode)
1098 ; * 320x2...
1099 else
1100 ; * 640x... */
1101 break;
1102 default:
1103 /* case SENSOR_OV7660: */
1104 ov7660_InitSensor(gspca_dev);
1105 if (mode) {
1106 /* reg17 = 0x21; * 320 */
1107 /* reg1 = 0x44; */
1108 /* reg1 = 0x46; (done) */
1109 } else {
1110 reg17 = 0xa2; /* 640 */
1111 reg1 = 0x40;
1113 break;
1115 reg_w(gspca_dev, 0xc0, C0, 6);
1116 switch (sd->bridge) {
1117 case BRIDGE_SN9C120: /*jfm ?? */
1118 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1119 break;
1120 default:
1121 reg_w(gspca_dev, 0xca, CA, 4);
1122 break;
1124 switch (sd->bridge) {
1125 case BRIDGE_SN9C120: /*jfm ?? */
1126 case BRIDGE_SN9C325:
1127 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1128 break;
1129 default:
1130 reg_w(gspca_dev, 0xce, CE, 4);
1131 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1132 break;
1135 /* here change size mode 0 -> VGA; 1 -> CIF */
1136 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1137 reg_w1(gspca_dev, 0x18, data);
1139 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1140 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1142 data = sn9c1xx[0x18] | (mode << 4);
1143 reg_w1(gspca_dev, 0x18, data);
1145 reg_w1(gspca_dev, 0x17, reg17);
1146 reg_w1(gspca_dev, 0x01, reg1);
1147 setbrightness(gspca_dev);
1148 setcontrast(gspca_dev);
1151 static void sd_stopN(struct gspca_dev *gspca_dev)
1153 struct sd *sd = (struct sd *) gspca_dev;
1154 static const __u8 stophv7131[] =
1155 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1156 static const __u8 stopmi0360[] =
1157 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1158 __u8 data;
1159 const __u8 *sn9c1xx;
1161 data = 0x0b;
1162 switch (sd->sensor) {
1163 case SENSOR_HV7131R:
1164 i2c_w8(gspca_dev, stophv7131);
1165 data = 0x2b;
1166 break;
1167 case SENSOR_MI0360:
1168 i2c_w8(gspca_dev, stopmi0360);
1169 data = 0x29;
1170 break;
1171 case SENSOR_MO4000:
1172 break;
1173 case SENSOR_OV7648:
1174 data = 0x29;
1175 break;
1176 default:
1177 /* case SENSOR_OV7660: */
1178 break;
1180 sn9c1xx = sn_tb[(int) sd->sensor];
1181 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1182 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1183 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1184 reg_w1(gspca_dev, 0x01, data);
1185 reg_w1(gspca_dev, 0xf1, 0x01);
1188 static void sd_stop0(struct gspca_dev *gspca_dev)
1192 static void sd_close(struct gspca_dev *gspca_dev)
1196 static void setautogain(struct gspca_dev *gspca_dev)
1198 struct sd *sd = (struct sd *) gspca_dev;
1199 /* Thanks S., without your advice, autobright should not work :) */
1200 int delta;
1201 int expotimes = 0;
1202 __u8 luma_mean = 130;
1203 __u8 luma_delta = 20;
1205 delta = sd->avg_lum;
1206 if (delta < luma_mean - luma_delta ||
1207 delta > luma_mean + luma_delta) {
1208 switch (sd->sensor) {
1209 case SENSOR_HV7131R:
1210 expotimes = sd->exposure >> 8;
1211 expotimes += (luma_mean - delta) >> 4;
1212 if (expotimes < 0)
1213 expotimes = 0;
1214 sd->exposure = setexposure(gspca_dev,
1215 (unsigned int) (expotimes << 8));
1216 break;
1217 case SENSOR_MO4000:
1218 case SENSOR_MI0360:
1219 expotimes = sd->exposure;
1220 expotimes += (luma_mean - delta) >> 6;
1221 if (expotimes < 0)
1222 expotimes = 0;
1223 sd->exposure = setexposure(gspca_dev,
1224 (unsigned int) expotimes);
1225 setcolors(gspca_dev);
1226 break;
1231 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1232 struct gspca_frame *frame, /* target */
1233 __u8 *data, /* isoc packet */
1234 int len) /* iso packet length */
1236 struct sd *sd = (struct sd *) gspca_dev;
1237 int sof, avg_lum;
1239 sof = len - 64;
1240 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1242 /* end of frame */
1243 gspca_frame_add(gspca_dev, LAST_PACKET,
1244 frame, data, sof + 2);
1245 if (sd->ag_cnt < 0)
1246 return;
1247 if (--sd->ag_cnt >= 0)
1248 return;
1249 sd->ag_cnt = AG_CNT_START;
1250 /* w1 w2 w3 */
1251 /* w4 w5 w6 */
1252 /* w7 w8 */
1253 /* w4 */
1254 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1255 /* w6 */
1256 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1257 /* w2 */
1258 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1259 /* w8 */
1260 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1261 /* w5 */
1262 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1263 avg_lum >>= 4;
1264 sd->avg_lum = avg_lum;
1265 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1266 setautogain(gspca_dev);
1267 return;
1269 if (gspca_dev->last_packet_type == LAST_PACKET) {
1271 /* put the JPEG 422 header */
1272 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1274 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1277 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1279 struct sd *sd = (struct sd *) gspca_dev;
1280 __u8 hexpo, mexpo, lexpo;
1282 switch (sd->sensor) {
1283 case SENSOR_HV7131R:
1284 /* read sensor exposure */
1285 i2c_r5(gspca_dev, 0x25);
1286 return (gspca_dev->usb_buf[0] << 16)
1287 | (gspca_dev->usb_buf[1] << 8)
1288 | gspca_dev->usb_buf[2];
1289 case SENSOR_MI0360:
1290 /* read sensor exposure */
1291 i2c_r5(gspca_dev, 0x09);
1292 return (gspca_dev->usb_buf[0] << 8)
1293 | gspca_dev->usb_buf[1];
1294 case SENSOR_MO4000:
1295 i2c_r5(gspca_dev, 0x0e);
1296 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1297 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1298 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1299 PDEBUG(D_CONF, "exposure %d",
1300 (hexpo << 10) | (mexpo << 2) | lexpo);
1301 return (hexpo << 10) | (mexpo << 2) | lexpo;
1302 default:
1303 /* case SENSOR_OV7660: */
1304 /* read sensor exposure */
1305 i2c_r5(gspca_dev, 0x04);
1306 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1307 lexpo = gspca_dev->usb_buf[0] & 0x02;
1308 i2c_r5(gspca_dev, 0x08);
1309 mexpo = gspca_dev->usb_buf[2];
1310 return (hexpo << 10) | (mexpo << 2) | lexpo;
1314 static void getbrightness(struct gspca_dev *gspca_dev)
1316 struct sd *sd = (struct sd *) gspca_dev;
1318 /* hardcoded registers seem not readable */
1319 switch (sd->sensor) {
1320 case SENSOR_HV7131R:
1321 /* sd->brightness = 0x7fff; */
1322 sd->brightness = getexposure(gspca_dev) >> 4;
1323 break;
1324 case SENSOR_MI0360:
1325 sd->brightness = getexposure(gspca_dev) << 4;
1326 break;
1327 case SENSOR_MO4000:
1328 /* sd->brightness = 0x1fff; */
1329 sd->brightness = getexposure(gspca_dev) << 4;
1330 break;
1334 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1336 struct sd *sd = (struct sd *) gspca_dev;
1338 sd->brightness = val;
1339 if (gspca_dev->streaming)
1340 setbrightness(gspca_dev);
1341 return 0;
1344 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1346 struct sd *sd = (struct sd *) gspca_dev;
1348 getbrightness(gspca_dev);
1349 *val = sd->brightness;
1350 return 0;
1353 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1355 struct sd *sd = (struct sd *) gspca_dev;
1357 sd->contrast = val;
1358 if (gspca_dev->streaming)
1359 setcontrast(gspca_dev);
1360 return 0;
1363 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1365 struct sd *sd = (struct sd *) gspca_dev;
1367 *val = sd->contrast;
1368 return 0;
1371 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1373 struct sd *sd = (struct sd *) gspca_dev;
1375 sd->colors = val;
1376 if (gspca_dev->streaming)
1377 setcolors(gspca_dev);
1378 return 0;
1381 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1383 struct sd *sd = (struct sd *) gspca_dev;
1385 *val = sd->colors;
1386 return 0;
1389 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1391 struct sd *sd = (struct sd *) gspca_dev;
1393 sd->autogain = val;
1394 if (val)
1395 sd->ag_cnt = AG_CNT_START;
1396 else
1397 sd->ag_cnt = -1;
1398 return 0;
1401 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1403 struct sd *sd = (struct sd *) gspca_dev;
1405 *val = sd->autogain;
1406 return 0;
1409 /* sub-driver description */
1410 static const struct sd_desc sd_desc = {
1411 .name = MODULE_NAME,
1412 .ctrls = sd_ctrls,
1413 .nctrls = ARRAY_SIZE(sd_ctrls),
1414 .config = sd_config,
1415 .open = sd_open,
1416 .start = sd_start,
1417 .stopN = sd_stopN,
1418 .stop0 = sd_stop0,
1419 .close = sd_close,
1420 .pkt_scan = sd_pkt_scan,
1423 /* -- module initialisation -- */
1424 #define BSI(bridge, sensor, i2c_addr) \
1425 .driver_info = (BRIDGE_ ## bridge << 16) \
1426 | (SENSOR_ ## sensor << 8) \
1427 | (i2c_addr)
1428 static const __devinitdata struct usb_device_id device_table[] = {
1429 #ifndef CONFIG_USB_SN9C102
1430 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1431 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1432 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1433 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1434 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1435 #endif
1436 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1437 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1438 /* bw600.inf:
1439 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1440 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1441 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1442 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1443 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1444 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1445 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1446 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1447 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1448 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1449 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1450 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1451 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1452 /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1453 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1454 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1455 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1456 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1457 /* bw600.inf:
1458 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1459 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1460 /* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1461 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1462 #ifndef CONFIG_USB_SN9C102
1463 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1464 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1465 /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1466 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1467 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1468 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1469 #endif
1472 MODULE_DEVICE_TABLE(usb, device_table);
1474 /* -- device connect -- */
1475 static int sd_probe(struct usb_interface *intf,
1476 const struct usb_device_id *id)
1478 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1479 THIS_MODULE);
1482 static struct usb_driver sd_driver = {
1483 .name = MODULE_NAME,
1484 .id_table = device_table,
1485 .probe = sd_probe,
1486 .disconnect = gspca_disconnect,
1489 /* -- module insert / remove -- */
1490 static int __init sd_mod_init(void)
1492 if (usb_register(&sd_driver) < 0)
1493 return -1;
1494 info("registered");
1495 return 0;
1497 static void __exit sd_mod_exit(void)
1499 usb_deregister(&sd_driver);
1500 info("deregistered");
1503 module_init(sd_mod_init);
1504 module_exit(sd_mod_exit);