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;
787 /* this function is called at open time */
788 static int sd_open(struct gspca_dev *gspca_dev)
790 struct sd *sd = (struct sd *) gspca_dev;
791 /* const __u8 *sn9c1xx; */
792 __u8 regGpio[] = { 0x29, 0x74 };
795 /* setup a selector by bridge */
796 reg_w1(gspca_dev, 0xf1, 0x01);
797 reg_r(gspca_dev, 0x00, 1);
798 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
799 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
800 regF1 = gspca_dev->usb_buf[0];
801 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
802 switch (sd->bridge) {
803 case BRIDGE_SN9C102P:
806 reg_w1(gspca_dev, 0x02, regGpio[1]);
811 reg_w(gspca_dev, 0x02, regGpio, 2);
817 reg_w(gspca_dev, 0x02, regGpio, 2);
820 /* case BRIDGE_SN9C110: */
821 /* case BRIDGE_SN9C325: */
824 reg_w1(gspca_dev, 0x02, 0x62);
828 reg_w1(gspca_dev, 0xf1, 0x01);
833 static unsigned int setexposure(struct gspca_dev *gspca_dev,
836 struct sd *sd = (struct sd *) gspca_dev;
837 static const __u8 doit[] = /* update sensor */
838 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
839 static const __u8 sensorgo[] = /* sensor on */
840 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
841 static const __u8 gainMo[] =
842 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
844 switch (sd->sensor) {
845 case SENSOR_HV7131R: {
847 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
849 Expodoit[3] = expo >> 16;
850 Expodoit[4] = expo >> 8;
852 i2c_w8(gspca_dev, Expodoit);
855 case SENSOR_MI0360: {
856 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
857 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
861 else if (expo < 0x0001)
863 expoMi[3] = expo >> 8;
865 i2c_w8(gspca_dev, expoMi);
866 i2c_w8(gspca_dev, doit);
867 i2c_w8(gspca_dev, sensorgo);
870 case SENSOR_MO4000: {
872 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
874 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
878 else if (expo < 0x0001)
880 expoMof[3] = (expo & 0x03fc) >> 2;
881 i2c_w8(gspca_dev, expoMof);
882 expoMo10[3] = ((expo & 0x1c00) >> 10)
883 | ((expo & 0x0003) << 4);
884 i2c_w8(gspca_dev, expoMo10);
885 i2c_w8(gspca_dev, gainMo);
886 PDEBUG(D_CONF, "set exposure %d",
887 ((expoMo10[3] & 0x07) << 10)
889 | ((expoMo10[3] & 0x30) >> 4));
896 static void setbrightness(struct gspca_dev *gspca_dev)
898 struct sd *sd = (struct sd *) gspca_dev;
902 switch (sd->sensor) {
904 expo = sd->brightness << 4;
905 if (expo > 0x002dc6c0)
907 else if (expo < 0x02a0)
909 sd->exposure = setexposure(gspca_dev, expo);
913 expo = sd->brightness >> 4;
914 sd->exposure = setexposure(gspca_dev, expo);
918 k2 = sd->brightness >> 10;
919 reg_w1(gspca_dev, 0x96, k2);
922 static void setcontrast(struct gspca_dev *gspca_dev)
924 struct sd *sd = (struct sd *) gspca_dev;
926 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
930 contrast[0] = (k2 + 1) >> 1;
931 contrast[4] = (k2 + 1) / 5;
932 reg_w(gspca_dev, 0x84, contrast, 6);
935 static void setcolors(struct gspca_dev *gspca_dev)
937 struct sd *sd = (struct sd *) gspca_dev;
941 colour = sd->colors - 128;
943 data = (colour + 32) & 0x7f; /* blue */
945 data = (-colour + 32) & 0x7f; /* red */
946 reg_w1(gspca_dev, 0x05, data);
949 /* -- start the camera -- */
950 static void sd_start(struct gspca_dev *gspca_dev)
952 struct sd *sd = (struct sd *) gspca_dev;
954 __u8 reg1, reg17, reg18;
957 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
958 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
959 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
960 static const __u8 CE_sn9c325[] =
961 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
963 sn9c1xx = sn_tb[(int) sd->sensor];
964 configure_gpio(gspca_dev, sn9c1xx);
966 /* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
967 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
968 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
969 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
970 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
971 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
972 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
973 reg_w1(gspca_dev, 0xd3, 0x50);
974 reg_w1(gspca_dev, 0xc6, 0x00);
975 reg_w1(gspca_dev, 0xc7, 0x00);
976 reg_w1(gspca_dev, 0xc8, 0x50);
977 reg_w1(gspca_dev, 0xc9, 0x3c);
978 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
979 switch (sd->bridge) {
987 reg_w1(gspca_dev, 0x17, reg17);
988 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
989 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
990 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
991 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
992 switch (sd->bridge) {
994 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
995 sizeof regsn20_sn9c325);
996 for (i = 0; i < 8; i++)
997 reg_w(gspca_dev, 0x84, reg84_sn9c325,
998 sizeof reg84_sn9c325);
999 reg_w1(gspca_dev, 0x9a, 0x0a);
1000 reg_w1(gspca_dev, 0x99, 0x60);
1003 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1004 for (i = 0; i < 8; i++)
1005 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1006 reg_w1(gspca_dev, 0x9a, 0x08);
1007 reg_w1(gspca_dev, 0x99, 0x59);
1011 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1013 reg1 = 0x46; /* 320 clk 48Mhz */
1015 reg1 = 0x06; /* 640 clk 24Mz */
1017 switch (sd->sensor) {
1018 case SENSOR_HV7131R:
1019 hv7131R_InitSensor(gspca_dev);
1022 mi0360_InitSensor(gspca_dev);
1025 mo4000_InitSensor(gspca_dev);
1027 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1028 reg1 = 0x06; /* clk 24Mz */
1030 reg17 = 0x22; /* 640 MCKSIZE */
1031 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1035 ov7648_InitSensor(gspca_dev);
1044 /* case SENSOR_OV7660: */
1045 ov7660_InitSensor(gspca_dev);
1047 /* reg17 = 0x21; * 320 */
1049 /* reg1 = 0x46; (done) */
1051 reg17 = 0x22; /* 640 MCKSIZE */
1056 reg_w(gspca_dev, 0xc0, C0, 6);
1057 reg_w(gspca_dev, 0xca, CA, 4);
1058 switch (sd->bridge) {
1059 case BRIDGE_SN9C325:
1060 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1063 reg_w(gspca_dev, 0xce, CE, 4);
1064 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1068 /* here change size mode 0 -> VGA; 1 -> CIF */
1069 reg18 = sn9c1xx[0x18] | (mode << 4);
1070 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1072 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1073 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1075 reg_w1(gspca_dev, 0x18, reg18);
1077 reg_w1(gspca_dev, 0x17, reg17);
1078 reg_w1(gspca_dev, 0x01, reg1);
1079 setbrightness(gspca_dev);
1080 setcontrast(gspca_dev);
1083 static void sd_stopN(struct gspca_dev *gspca_dev)
1085 struct sd *sd = (struct sd *) gspca_dev;
1086 static const __u8 stophv7131[] =
1087 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1088 static const __u8 stopmi0360[] =
1089 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1091 const __u8 *sn9c1xx;
1094 switch (sd->sensor) {
1095 case SENSOR_HV7131R:
1096 i2c_w8(gspca_dev, stophv7131);
1100 i2c_w8(gspca_dev, stopmi0360);
1107 /* case SENSOR_MO4000: */
1108 /* case SENSOR_OV7660: */
1111 sn9c1xx = sn_tb[(int) sd->sensor];
1112 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1113 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1114 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1115 reg_w1(gspca_dev, 0x01, data);
1116 reg_w1(gspca_dev, 0xf1, 0x01);
1119 static void sd_stop0(struct gspca_dev *gspca_dev)
1123 static void sd_close(struct gspca_dev *gspca_dev)
1127 static void setautogain(struct gspca_dev *gspca_dev)
1129 struct sd *sd = (struct sd *) gspca_dev;
1130 /* Thanks S., without your advice, autobright should not work :) */
1133 __u8 luma_mean = 130;
1134 __u8 luma_delta = 20;
1136 delta = sd->avg_lum;
1137 if (delta < luma_mean - luma_delta ||
1138 delta > luma_mean + luma_delta) {
1139 switch (sd->sensor) {
1140 case SENSOR_HV7131R:
1141 expotimes = sd->exposure >> 8;
1142 expotimes += (luma_mean - delta) >> 4;
1145 sd->exposure = setexposure(gspca_dev,
1146 (unsigned int) (expotimes << 8));
1150 expotimes = sd->exposure;
1151 expotimes += (luma_mean - delta) >> 6;
1154 sd->exposure = setexposure(gspca_dev,
1155 (unsigned int) expotimes);
1156 setcolors(gspca_dev);
1162 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1163 struct gspca_frame *frame, /* target */
1164 __u8 *data, /* isoc packet */
1165 int len) /* iso packet length */
1167 struct sd *sd = (struct sd *) gspca_dev;
1171 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1174 gspca_frame_add(gspca_dev, LAST_PACKET,
1175 frame, data, sof + 2);
1178 if (--sd->ag_cnt >= 0)
1180 sd->ag_cnt = AG_CNT_START;
1185 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1187 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1189 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1191 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1193 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1195 sd->avg_lum = avg_lum;
1196 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1197 setautogain(gspca_dev);
1200 if (gspca_dev->last_packet_type == LAST_PACKET) {
1202 /* put the JPEG 422 header */
1203 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1205 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1208 static unsigned int getexposure(struct gspca_dev *gspca_dev)
1210 struct sd *sd = (struct sd *) gspca_dev;
1211 __u8 hexpo, mexpo, lexpo;
1213 switch (sd->sensor) {
1214 case SENSOR_HV7131R:
1215 /* read sensor exposure */
1216 i2c_r5(gspca_dev, 0x25);
1217 return (gspca_dev->usb_buf[0] << 16)
1218 | (gspca_dev->usb_buf[1] << 8)
1219 | gspca_dev->usb_buf[2];
1221 /* read sensor exposure */
1222 i2c_r5(gspca_dev, 0x09);
1223 return (gspca_dev->usb_buf[0] << 8)
1224 | gspca_dev->usb_buf[1];
1226 i2c_r5(gspca_dev, 0x0e);
1227 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1228 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1229 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1230 PDEBUG(D_CONF, "exposure %d",
1231 (hexpo << 10) | (mexpo << 2) | lexpo);
1232 return (hexpo << 10) | (mexpo << 2) | lexpo;
1234 /* case SENSOR_OV7648: * jfm: is it ok for 7648? */
1235 /* case SENSOR_OV7660: */
1236 /* read sensor exposure */
1237 i2c_r5(gspca_dev, 0x04);
1238 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1239 lexpo = gspca_dev->usb_buf[0] & 0x02;
1240 i2c_r5(gspca_dev, 0x08);
1241 mexpo = gspca_dev->usb_buf[2];
1242 return (hexpo << 10) | (mexpo << 2) | lexpo;
1246 static void getbrightness(struct gspca_dev *gspca_dev)
1248 struct sd *sd = (struct sd *) gspca_dev;
1250 /* hardcoded registers seem not readable */
1251 switch (sd->sensor) {
1252 case SENSOR_HV7131R:
1253 sd->brightness = getexposure(gspca_dev) >> 4;
1256 sd->brightness = getexposure(gspca_dev) << 4;
1259 sd->brightness = getexposure(gspca_dev) << 4;
1264 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1266 struct sd *sd = (struct sd *) gspca_dev;
1268 sd->brightness = val;
1269 if (gspca_dev->streaming)
1270 setbrightness(gspca_dev);
1274 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1276 struct sd *sd = (struct sd *) gspca_dev;
1278 getbrightness(gspca_dev);
1279 *val = sd->brightness;
1283 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1285 struct sd *sd = (struct sd *) gspca_dev;
1288 if (gspca_dev->streaming)
1289 setcontrast(gspca_dev);
1293 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1295 struct sd *sd = (struct sd *) gspca_dev;
1297 *val = sd->contrast;
1301 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1303 struct sd *sd = (struct sd *) gspca_dev;
1306 if (gspca_dev->streaming)
1307 setcolors(gspca_dev);
1311 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1313 struct sd *sd = (struct sd *) gspca_dev;
1319 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1321 struct sd *sd = (struct sd *) gspca_dev;
1325 sd->ag_cnt = AG_CNT_START;
1331 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1333 struct sd *sd = (struct sd *) gspca_dev;
1335 *val = sd->autogain;
1339 /* sub-driver description */
1340 static const struct sd_desc sd_desc = {
1341 .name = MODULE_NAME,
1343 .nctrls = ARRAY_SIZE(sd_ctrls),
1344 .config = sd_config,
1350 .pkt_scan = sd_pkt_scan,
1353 /* -- module initialisation -- */
1354 #define BSI(bridge, sensor, i2c_addr) \
1355 .driver_info = (BRIDGE_ ## bridge << 16) \
1356 | (SENSOR_ ## sensor << 8) \
1358 static const __devinitdata struct usb_device_id device_table[] = {
1359 #ifndef CONFIG_USB_SN9C102
1360 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1361 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1362 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1363 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1364 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1366 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1367 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1369 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1370 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1371 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1372 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1373 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1374 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1375 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1376 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1377 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1378 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1379 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1380 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1381 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1382 /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1383 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1384 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1385 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1386 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1388 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1389 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1390 /* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1391 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1392 #ifndef CONFIG_USB_SN9C102
1393 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1394 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1395 /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1396 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1397 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1398 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1400 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1403 MODULE_DEVICE_TABLE(usb, device_table);
1405 /* -- device connect -- */
1406 static int sd_probe(struct usb_interface *intf,
1407 const struct usb_device_id *id)
1409 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1413 static struct usb_driver sd_driver = {
1414 .name = MODULE_NAME,
1415 .id_table = device_table,
1417 .disconnect = gspca_disconnect,
1420 /* -- module insert / remove -- */
1421 static int __init sd_mod_init(void)
1423 if (usb_register(&sd_driver) < 0)
1428 static void __exit sd_mod_exit(void)
1430 usb_deregister(&sd_driver);
1431 info("deregistered");
1434 module_init(sd_mod_init);
1435 module_exit(sd_mod_exit);