2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "sonixj"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
36 unsigned int exposure;
38 unsigned short brightness;
39 unsigned char contrast;
41 unsigned char autogain;
44 #define AG_CNT_START 13
48 #define BRIDGE_SN9C102P 0
49 #define BRIDGE_SN9C105 1
50 #define BRIDGE_SN9C110 2
51 #define BRIDGE_SN9C120 3
52 #define BRIDGE_SN9C325 4
53 char sensor; /* Type of image sensor chip */
54 #define SENSOR_HV7131R 0
55 #define SENSOR_MI0360 1
56 #define SENSOR_MO4000 2
57 #define SENSOR_OV7648 3
58 #define SENSOR_OV7660 4
59 unsigned char i2c_base;
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72 static struct ctrl sd_ctrls[] = {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
81 #define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
95 #define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
109 #define COLOR_DEF 127
110 .default_value = COLOR_DEF,
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 #define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
126 .set = sd_setautogain,
127 .get = sd_getautogain,
131 static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
149 /*Data from sn9c102p+hv71331r */
150 static const __u8 sn_hv7131[] = {
151 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
152 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
153 /* reg8 reg9 rega regb regc regd rege regf */
154 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
155 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
156 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
157 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
158 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161 static const __u8 sn_mi0360[] = {
162 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
164 /* reg8 reg9 rega regb regc regd rege regf */
165 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
166 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
167 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
168 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
169 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
172 static const __u8 sn_mo4000[] = {
173 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
174 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
175 /* reg8 reg9 rega regb regc regd rege regf */
176 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
178 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
179 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
180 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
183 static const __u8 sn_ov7648[] = {
184 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
185 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
186 /* reg8 reg9 rega regb regc regd rege regf */
187 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
188 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
189 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
190 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
194 static const __u8 sn_ov7660[] = {
195 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
197 /* reg8 reg9 rega regb regc regd rege regf */
198 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
199 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
200 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
201 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
202 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 /* sequence specific to the sensors - !! index = SENSOR_xxx */
206 static const __u8 *sn_tb[] = {
214 static const __u8 regsn20[] = {
215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
218 static const __u8 regsn20_sn9c325[] = {
219 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
220 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
223 static const __u8 reg84[] = {
224 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
225 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
226 /* 0x00, 0x00, 0x00, 0x00, 0x00 */
227 0xf7, 0x0f, 0x0a, 0x00, 0x00
229 static const __u8 reg84_sn9c325[] = {
230 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
231 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
232 0xf8, 0x0f, 0x00, 0x00, 0x00
235 static const __u8 hv7131r_sensor_init[][8] = {
236 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
237 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
238 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
239 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
240 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
241 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
242 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
244 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
245 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
246 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
247 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
248 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
249 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
250 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
251 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
253 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
254 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
255 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
256 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
259 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
262 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
263 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
266 static const __u8 mi0360_sensor_init[][8] = {
267 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
268 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
269 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
270 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
271 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
272 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
273 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
274 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
275 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
285 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
287 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
288 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
289 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
290 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
292 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
294 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
296 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
299 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
301 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
305 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
307 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
308 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
309 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
310 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
312 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
313 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
314 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
315 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
316 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
317 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
320 static const __u8 mo4000_sensor_init[][8] = {
321 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
322 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
323 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
324 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
325 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
327 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
328 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
329 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
330 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
331 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
332 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
333 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
334 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
335 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
336 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
337 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
343 static const __u8 ov7660_sensor_init[][8] = {
344 {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, 0x74, 0x00, 0x10},
350 /* GAIN BLUE RED VREF */
351 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
352 /* COM 1 BAVE GEAVE AECHH */
353 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
354 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
355 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
356 /* AECH CLKRC COM7 COM8 */
357 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
358 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
359 /* HSTART HSTOP VSTRT VSTOP */
360 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
361 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
362 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
363 /* BOS GBOS GROS ROS (BGGR offset) */
364 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
365 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
366 /* AEW AEB VPT BBIAS */
367 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
368 /* GbBIAS RSVD EXHCH EXHCL */
369 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
370 /* RBIAS ADVFL ASDVFH YAVE */
371 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
372 /* HSYST HSYEN HREF */
373 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
374 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
375 /* ADC ACOM OFON TSLB */
376 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
377 /* COM11 COM12 COM13 COM14 */
378 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
379 /* EDGE COM15 COM16 COM17 */
380 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
381 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
382 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
383 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
384 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
385 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
386 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
387 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
388 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
389 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
390 /* LCC1 LCC2 LCC3 LCC4 */
391 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
392 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
393 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
394 /* band gap reference [0:3] DBLV */
395 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
396 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
397 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
398 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
399 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
400 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
401 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
402 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
403 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
404 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
405 /****** (some exchanges in the win trace) ******/
406 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
407 /* bits[3..0]reserved */
408 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
409 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
410 /* VREF vertical frame ctrl */
411 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
412 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
413 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
414 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
415 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
416 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
417 /****** (some exchanges in the win trace) ******/
418 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
419 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
420 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
421 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
422 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
423 /****** (some exchanges in the win trace) ******/
424 /******!! startsensor KO if changed !!****/
425 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
426 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
431 /* reg 0x04 reg 0x07 reg 0x10 */
432 /* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
434 static const __u8 ov7648_sensor_init[][8] = {
435 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
436 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
437 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
438 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
439 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
441 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
442 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
443 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
444 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
445 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
446 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
447 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
448 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
449 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
450 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
451 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
452 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
453 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
454 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
455 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
456 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
457 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
458 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
459 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
460 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
461 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
462 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
464 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
465 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
466 * This is currently setting a
467 * blue tint, and some things more , i leave it here for future test if
468 * somene is having problems with color on this sensor
469 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
471 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
472 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
473 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
474 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
475 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
476 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
477 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
478 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
479 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
480 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
481 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
482 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
483 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
484 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
485 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
486 /* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
490 static const __u8 qtable4[] = {
491 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
492 0x06, 0x08, 0x0A, 0x11,
493 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
494 0x19, 0x19, 0x17, 0x15,
495 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
496 0x21, 0x2E, 0x21, 0x23,
497 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
498 0x25, 0x29, 0x2C, 0x29,
499 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
500 0x17, 0x1B, 0x29, 0x29,
501 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
502 0x29, 0x29, 0x29, 0x29,
503 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
504 0x29, 0x29, 0x29, 0x29,
505 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
506 0x29, 0x29, 0x29, 0x29
509 /* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
510 static void reg_r(struct gspca_dev *gspca_dev,
511 __u16 value, int len)
513 usb_control_msg(gspca_dev->dev,
514 usb_rcvctrlpipe(gspca_dev->dev, 0),
516 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
518 gspca_dev->usb_buf, len,
520 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
523 static void reg_w1(struct gspca_dev *gspca_dev,
527 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
528 gspca_dev->usb_buf[0] = data;
529 usb_control_msg(gspca_dev->dev,
530 usb_sndctrlpipe(gspca_dev->dev, 0),
532 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
535 gspca_dev->usb_buf, 1,
538 static void reg_w(struct gspca_dev *gspca_dev,
543 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
544 value, buffer[0], buffer[1]);
545 if (len <= sizeof gspca_dev->usb_buf) {
546 memcpy(gspca_dev->usb_buf, buffer, len);
547 usb_control_msg(gspca_dev->dev,
548 usb_sndctrlpipe(gspca_dev->dev, 0),
550 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
552 gspca_dev->usb_buf, len,
557 tmpbuf = kmalloc(len, GFP_KERNEL);
558 memcpy(tmpbuf, buffer, len);
559 usb_control_msg(gspca_dev->dev,
560 usb_sndctrlpipe(gspca_dev->dev, 0),
562 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
570 /* I2C write 1 byte */
571 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
573 struct sd *sd = (struct sd *) gspca_dev;
575 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
576 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
577 gspca_dev->usb_buf[1] = sd->i2c_base;
578 gspca_dev->usb_buf[2] = reg;
579 gspca_dev->usb_buf[3] = val;
580 gspca_dev->usb_buf[4] = 0;
581 gspca_dev->usb_buf[5] = 0;
582 gspca_dev->usb_buf[6] = 0;
583 gspca_dev->usb_buf[7] = 0x10;
584 usb_control_msg(gspca_dev->dev,
585 usb_sndctrlpipe(gspca_dev->dev, 0),
587 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
588 0x08, /* value = i2c */
590 gspca_dev->usb_buf, 8,
594 /* I2C write 8 bytes */
595 static void i2c_w8(struct gspca_dev *gspca_dev,
598 memcpy(gspca_dev->usb_buf, buffer, 8);
599 usb_control_msg(gspca_dev->dev,
600 usb_sndctrlpipe(gspca_dev->dev, 0),
602 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
603 0x08, 0, /* value, index */
604 gspca_dev->usb_buf, 8,
608 /* read 5 bytes in gspca_dev->usb_buf */
609 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
611 struct sd *sd = (struct sd *) gspca_dev;
614 mode[0] = 0x81 | 0x10;
615 mode[1] = sd->i2c_base;
622 i2c_w8(gspca_dev, mode);
624 mode[0] = 0x81 | (5 << 4) | 0x02;
626 i2c_w8(gspca_dev, mode);
628 reg_r(gspca_dev, 0x0a, 5);
631 static int probesensor(struct gspca_dev *gspca_dev)
633 struct sd *sd = (struct sd *) gspca_dev;
635 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
637 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
639 i2c_r5(gspca_dev, 0); /* read sensor id */
640 if (gspca_dev->usb_buf[0] == 0x02
641 && gspca_dev->usb_buf[1] == 0x09
642 && gspca_dev->usb_buf[2] == 0x01
643 && gspca_dev->usb_buf[3] == 0x00
644 && gspca_dev->usb_buf[4] == 0x00) {
645 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
646 sd->sensor = SENSOR_HV7131R;
647 return SENSOR_HV7131R;
649 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
650 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
651 gspca_dev->usb_buf[2]);
652 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
656 static int configure_gpio(struct gspca_dev *gspca_dev,
659 struct sd *sd = (struct sd *) gspca_dev;
661 static const __u8 reg9a_def[] =
662 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
663 static const __u8 reg9a_sn9c325[] =
664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
665 static const __u8 regd4[] = {0x60, 0x00, 0x00};
667 reg_w1(gspca_dev, 0xf1, 0x00);
668 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
671 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
672 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
673 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
674 switch (sd->bridge) {
676 reg9a = reg9a_sn9c325;
682 reg_w(gspca_dev, 0x9a, reg9a, 6);
684 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
686 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
688 switch (sd->bridge) {
690 reg_w1(gspca_dev, 0x01, 0x43);
691 reg_w1(gspca_dev, 0x17, 0xae);
692 reg_w1(gspca_dev, 0x01, 0x42);
695 reg_w1(gspca_dev, 0x01, 0x43);
696 reg_w1(gspca_dev, 0x17, 0x61);
697 reg_w1(gspca_dev, 0x01, 0x42);
700 if (sd->sensor == SENSOR_HV7131R) {
701 if (probesensor(gspca_dev) < 0)
707 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
710 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
711 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
713 while (hv7131r_sensor_init[i][0]) {
714 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
717 i2c_w8(gspca_dev, SetSensorClk);
720 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
724 while (mi0360_sensor_init[i][0]) {
725 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
730 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
734 while (mo4000_sensor_init[i][0]) {
735 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
740 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
744 while (ov7648_sensor_init[i][0]) {
745 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
750 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
754 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
757 while (ov7660_sensor_init[i][0]) {
758 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
763 /* this function is called at probe time */
764 static int sd_config(struct gspca_dev *gspca_dev,
765 const struct usb_device_id *id)
767 struct sd *sd = (struct sd *) gspca_dev;
770 cam = &gspca_dev->cam;
772 cam->cam_mode = vga_mode;
773 cam->nmodes = ARRAY_SIZE(vga_mode);
775 sd->bridge = id->driver_info >> 16;
776 sd->sensor = id->driver_info >> 8;
777 sd->i2c_base = id->driver_info;
779 sd->qindex = 4; /* set the quantization table */
780 sd->brightness = BRIGHTNESS_DEF;
781 sd->contrast = CONTRAST_DEF;
782 sd->colors = COLOR_DEF;
783 sd->autogain = AUTOGAIN_DEF;
789 /* this function is called at open time */
790 static int sd_open(struct gspca_dev *gspca_dev)
792 struct sd *sd = (struct sd *) gspca_dev;
793 /* const __u8 *sn9c1xx; */
794 __u8 regGpio[] = { 0x29, 0x74 };
797 /* setup a selector by bridge */
798 reg_w1(gspca_dev, 0xf1, 0x01);
799 reg_r(gspca_dev, 0x00, 1);
800 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
801 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
802 regF1 = gspca_dev->usb_buf[0];
803 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
804 switch (sd->bridge) {
805 case BRIDGE_SN9C102P:
808 reg_w1(gspca_dev, 0x02, regGpio[1]);
813 reg_w(gspca_dev, 0x02, regGpio, 2);
819 reg_w(gspca_dev, 0x02, regGpio, 2);
822 /* case BRIDGE_SN9C110: */
823 /* case BRIDGE_SN9C325: */
826 reg_w1(gspca_dev, 0x02, 0x62);
830 reg_w1(gspca_dev, 0xf1, 0x01);
835 static unsigned int setexposure(struct gspca_dev *gspca_dev,
838 struct sd *sd = (struct sd *) gspca_dev;
839 static const __u8 doit[] = /* update sensor */
840 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
841 static const __u8 sensorgo[] = /* sensor on */
842 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
843 static const __u8 gainMo[] =
844 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
846 switch (sd->sensor) {
847 case SENSOR_HV7131R: {
849 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
851 Expodoit[3] = expo >> 16;
852 Expodoit[4] = expo >> 8;
854 i2c_w8(gspca_dev, Expodoit);
857 case SENSOR_MI0360: {
858 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
859 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
863 else if (expo < 0x0001)
865 expoMi[3] = expo >> 8;
867 i2c_w8(gspca_dev, expoMi);
868 i2c_w8(gspca_dev, doit);
869 i2c_w8(gspca_dev, sensorgo);
872 case SENSOR_MO4000: {
874 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
876 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
880 else if (expo < 0x0001)
882 expoMof[3] = (expo & 0x03fc) >> 2;
883 i2c_w8(gspca_dev, expoMof);
884 expoMo10[3] = ((expo & 0x1c00) >> 10)
885 | ((expo & 0x0003) << 4);
886 i2c_w8(gspca_dev, expoMo10);
887 i2c_w8(gspca_dev, gainMo);
888 PDEBUG(D_CONF, "set exposure %d",
889 ((expoMo10[3] & 0x07) << 10)
891 | ((expoMo10[3] & 0x30) >> 4));
898 static void setbrightness(struct gspca_dev *gspca_dev)
900 struct sd *sd = (struct sd *) gspca_dev;
904 switch (sd->sensor) {
906 expo = sd->brightness << 4;
907 if (expo > 0x002dc6c0)
909 else if (expo < 0x02a0)
911 sd->exposure = setexposure(gspca_dev, expo);
915 expo = sd->brightness >> 4;
916 sd->exposure = setexposure(gspca_dev, expo);
920 k2 = sd->brightness >> 10;
921 reg_w1(gspca_dev, 0x96, k2);
924 static void setcontrast(struct gspca_dev *gspca_dev)
926 struct sd *sd = (struct sd *) gspca_dev;
928 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
932 contrast[0] = (k2 + 1) >> 1;
933 contrast[4] = (k2 + 1) / 5;
934 reg_w(gspca_dev, 0x84, contrast, 6);
937 static void setcolors(struct gspca_dev *gspca_dev)
939 struct sd *sd = (struct sd *) gspca_dev;
943 colour = sd->colors - 128;
945 data = (colour + 32) & 0x7f; /* blue */
947 data = (-colour + 32) & 0x7f; /* red */
948 reg_w1(gspca_dev, 0x05, data);
951 static void setautogain(struct gspca_dev *gspca_dev)
953 struct sd *sd = (struct sd *) gspca_dev;
955 switch (sd->sensor) {
960 sd->ag_cnt = AG_CNT_START;
967 /* -- start the camera -- */
968 static void sd_start(struct gspca_dev *gspca_dev)
970 struct sd *sd = (struct sd *) gspca_dev;
972 __u8 reg1, reg17, reg18;
975 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
976 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
977 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
978 static const __u8 CE_sn9c325[] =
979 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
981 sn9c1xx = sn_tb[(int) sd->sensor];
982 configure_gpio(gspca_dev, sn9c1xx);
984 /* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
985 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
986 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
987 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
988 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
989 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
990 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
991 reg_w1(gspca_dev, 0xd3, 0x50);
992 reg_w1(gspca_dev, 0xc6, 0x00);
993 reg_w1(gspca_dev, 0xc7, 0x00);
994 reg_w1(gspca_dev, 0xc8, 0x50);
995 reg_w1(gspca_dev, 0xc9, 0x3c);
996 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
997 switch (sd->bridge) {
1005 reg_w1(gspca_dev, 0x17, reg17);
1006 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1007 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1008 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1009 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1010 switch (sd->bridge) {
1011 case BRIDGE_SN9C325:
1012 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1013 sizeof regsn20_sn9c325);
1014 for (i = 0; i < 8; i++)
1015 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1016 sizeof reg84_sn9c325);
1017 reg_w1(gspca_dev, 0x9a, 0x0a);
1018 reg_w1(gspca_dev, 0x99, 0x60);
1021 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1022 for (i = 0; i < 8; i++)
1023 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1024 reg_w1(gspca_dev, 0x9a, 0x08);
1025 reg_w1(gspca_dev, 0x99, 0x59);
1029 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1031 reg1 = 0x46; /* 320 clk 48Mhz */
1033 reg1 = 0x06; /* 640 clk 24Mz */
1035 switch (sd->sensor) {
1036 case SENSOR_HV7131R:
1037 hv7131R_InitSensor(gspca_dev);
1040 mi0360_InitSensor(gspca_dev);
1043 mo4000_InitSensor(gspca_dev);
1045 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1046 reg1 = 0x06; /* clk 24Mz */
1048 reg17 = 0x22; /* 640 MCKSIZE */
1049 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1053 ov7648_InitSensor(gspca_dev);
1062 /* case SENSOR_OV7660: */
1063 ov7660_InitSensor(gspca_dev);
1065 /* reg17 = 0x21; * 320 */
1067 /* reg1 = 0x46; (done) */
1069 reg17 = 0x22; /* 640 MCKSIZE */
1074 reg_w(gspca_dev, 0xc0, C0, 6);
1075 reg_w(gspca_dev, 0xca, CA, 4);
1076 switch (sd->bridge) {
1077 case BRIDGE_SN9C325:
1078 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1081 reg_w(gspca_dev, 0xce, CE, 4);
1082 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1086 /* here change size mode 0 -> VGA; 1 -> CIF */
1087 reg18 = sn9c1xx[0x18] | (mode << 4);
1088 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1090 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1091 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1093 reg_w1(gspca_dev, 0x18, reg18);
1095 reg_w1(gspca_dev, 0x17, reg17);
1096 reg_w1(gspca_dev, 0x01, reg1);
1097 setbrightness(gspca_dev);
1098 setcontrast(gspca_dev);
1099 setautogain(gspca_dev);
1102 static void sd_stopN(struct gspca_dev *gspca_dev)
1104 struct sd *sd = (struct sd *) gspca_dev;
1105 static const __u8 stophv7131[] =
1106 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1107 static const __u8 stopmi0360[] =
1108 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1110 const __u8 *sn9c1xx;
1113 switch (sd->sensor) {
1114 case SENSOR_HV7131R:
1115 i2c_w8(gspca_dev, stophv7131);
1119 i2c_w8(gspca_dev, stopmi0360);
1126 /* case SENSOR_MO4000: */
1127 /* case SENSOR_OV7660: */
1130 sn9c1xx = sn_tb[(int) sd->sensor];
1131 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1132 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1133 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1134 reg_w1(gspca_dev, 0x01, data);
1135 reg_w1(gspca_dev, 0xf1, 0x01);
1138 static void sd_stop0(struct gspca_dev *gspca_dev)
1142 static void sd_close(struct gspca_dev *gspca_dev)
1146 static void do_autogain(struct gspca_dev *gspca_dev)
1148 struct sd *sd = (struct sd *) gspca_dev;
1151 __u8 luma_mean = 130;
1152 __u8 luma_delta = 20;
1154 /* Thanks S., without your advice, autobright should not work :) */
1157 if (--sd->ag_cnt >= 0)
1159 sd->ag_cnt = AG_CNT_START;
1161 delta = atomic_read(&sd->avg_lum);
1162 PDEBUG(D_FRAM, "mean lum %d", delta);
1163 if (delta < luma_mean - luma_delta ||
1164 delta > luma_mean + luma_delta) {
1165 switch (sd->sensor) {
1166 case SENSOR_HV7131R:
1167 expotimes = sd->exposure >> 8;
1168 expotimes += (luma_mean - delta) >> 4;
1171 sd->exposure = setexposure(gspca_dev,
1172 (unsigned int) (expotimes << 8));
1175 /* case SENSOR_MO4000: */
1176 /* case SENSOR_MI0360: */
1177 expotimes = sd->exposure;
1178 expotimes += (luma_mean - delta) >> 6;
1181 sd->exposure = setexposure(gspca_dev,
1182 (unsigned int) expotimes);
1183 setcolors(gspca_dev);
1189 /* scan the URB packets */
1190 /* This function is run at interrupt level. */
1191 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1192 struct gspca_frame *frame, /* target */
1193 __u8 *data, /* isoc packet */
1194 int len) /* iso packet length */
1196 struct sd *sd = (struct sd *) gspca_dev;
1200 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1203 gspca_frame_add(gspca_dev, LAST_PACKET,
1204 frame, data, sof + 2);
1211 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1213 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1215 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1217 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1219 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1221 atomic_set(&sd->avg_lum, avg_lum);
1224 if (gspca_dev->last_packet_type == LAST_PACKET) {
1226 /* put the JPEG 422 header */
1227 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1229 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1232 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1234 struct sd *sd = (struct sd *) gspca_dev;
1235 __u8 hexpo, mexpo, lexpo;
1237 switch (sd->sensor) {
1238 case SENSOR_HV7131R:
1239 /* read sensor exposure */
1240 i2c_r5(gspca_dev, 0x25);
1241 return (gspca_dev->usb_buf[0] << 16)
1242 | (gspca_dev->usb_buf[1] << 8)
1243 | gspca_dev->usb_buf[2];
1245 /* read sensor exposure */
1246 i2c_r5(gspca_dev, 0x09);
1247 return (gspca_dev->usb_buf[0] << 8)
1248 | gspca_dev->usb_buf[1];
1250 i2c_r5(gspca_dev, 0x0e);
1251 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1252 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1253 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1254 PDEBUG(D_CONF, "exposure %d",
1255 (hexpo << 10) | (mexpo << 2) | lexpo);
1256 return (hexpo << 10) | (mexpo << 2) | lexpo;
1258 /* case SENSOR_OV7648: * jfm: is it ok for 7648? */
1259 /* case SENSOR_OV7660: */
1260 /* read sensor exposure */
1261 i2c_r5(gspca_dev, 0x04);
1262 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1263 lexpo = gspca_dev->usb_buf[0] & 0x02;
1264 i2c_r5(gspca_dev, 0x08);
1265 mexpo = gspca_dev->usb_buf[2];
1266 return (hexpo << 10) | (mexpo << 2) | lexpo;
1270 static void getbrightness(struct gspca_dev *gspca_dev)
1272 struct sd *sd = (struct sd *) gspca_dev;
1274 /* hardcoded registers seem not readable */
1275 switch (sd->sensor) {
1276 case SENSOR_HV7131R:
1277 sd->brightness = getexposure(gspca_dev) >> 4;
1280 sd->brightness = getexposure(gspca_dev) << 4;
1283 sd->brightness = getexposure(gspca_dev) << 4;
1288 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1290 struct sd *sd = (struct sd *) gspca_dev;
1292 sd->brightness = val;
1293 if (gspca_dev->streaming)
1294 setbrightness(gspca_dev);
1298 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1300 struct sd *sd = (struct sd *) gspca_dev;
1302 getbrightness(gspca_dev);
1303 *val = sd->brightness;
1307 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1309 struct sd *sd = (struct sd *) gspca_dev;
1312 if (gspca_dev->streaming)
1313 setcontrast(gspca_dev);
1317 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1319 struct sd *sd = (struct sd *) gspca_dev;
1321 *val = sd->contrast;
1325 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1327 struct sd *sd = (struct sd *) gspca_dev;
1330 if (gspca_dev->streaming)
1331 setcolors(gspca_dev);
1335 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1337 struct sd *sd = (struct sd *) gspca_dev;
1343 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1345 struct sd *sd = (struct sd *) gspca_dev;
1348 if (gspca_dev->streaming)
1349 setautogain(gspca_dev);
1353 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1355 struct sd *sd = (struct sd *) gspca_dev;
1357 *val = sd->autogain;
1361 /* sub-driver description */
1362 static const struct sd_desc sd_desc = {
1363 .name = MODULE_NAME,
1365 .nctrls = ARRAY_SIZE(sd_ctrls),
1366 .config = sd_config,
1372 .pkt_scan = sd_pkt_scan,
1373 .dq_callback = do_autogain,
1376 /* -- module initialisation -- */
1377 #define BSI(bridge, sensor, i2c_addr) \
1378 .driver_info = (BRIDGE_ ## bridge << 16) \
1379 | (SENSOR_ ## sensor << 8) \
1381 static const __devinitdata struct usb_device_id device_table[] = {
1382 #ifndef CONFIG_USB_SN9C102
1383 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1384 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1385 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1386 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1387 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1389 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1390 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1392 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1393 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1394 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1395 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1396 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1397 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1398 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1399 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1400 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1401 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1402 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1403 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1404 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1405 /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1406 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1407 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1408 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1409 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1411 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1412 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1413 /* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1414 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1415 #ifndef CONFIG_USB_SN9C102
1416 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1417 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1418 /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1419 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1420 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1421 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1423 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1426 MODULE_DEVICE_TABLE(usb, device_table);
1428 /* -- device connect -- */
1429 static int sd_probe(struct usb_interface *intf,
1430 const struct usb_device_id *id)
1432 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1436 static struct usb_driver sd_driver = {
1437 .name = MODULE_NAME,
1438 .id_table = device_table,
1440 .disconnect = gspca_disconnect,
1443 /* -- module insert / remove -- */
1444 static int __init sd_mod_init(void)
1446 if (usb_register(&sd_driver) < 0)
1451 static void __exit sd_mod_exit(void)
1453 usb_deregister(&sd_driver);
1454 info("deregistered");
1457 module_init(sd_mod_init);
1458 module_exit(sd_mod_exit);