blob: d75b1d20b3180e8982db8ca196de42823d1b00c3 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
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.
11 *
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.
16 *
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
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -030035 atomic_t avg_lum;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 unsigned int exposure;
37
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 signed char ag_cnt;
44#define AG_CNT_START 13
45
46 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030047 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
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_MI0360 1
56#define SENSOR_MO4000 2
Jean-Francois Moined2d16e92008-09-03 16:47:23 -030057#define SENSOR_OM6802 3
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -030058#define SENSOR_OV7630 4
59#define SENSOR_OV7648 5
60#define SENSOR_OV7660 6
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030061 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030062};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
73
74static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030075 {
76 {
77 .id = V4L2_CID_BRIGHTNESS,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Brightness",
80 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -030081#define BRIGHTNESS_MAX 0xffff
82 .maximum = BRIGHTNESS_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030084#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030090 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -030096#define CONTRAST_MAX 127
97 .maximum = CONTRAST_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030099#define CONTRAST_DEF 63
100 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 },
102 .set = sd_setcontrast,
103 .get = sd_getcontrast,
104 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 {
106 {
107 .id = V4L2_CID_SATURATION,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Color",
110 .minimum = 0,
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -0300111 .maximum = 64,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300112 .step = 1,
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -0300113#define COLOR_DEF 32
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300114 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 },
116 .set = sd_setcolors,
117 .get = sd_getcolors,
118 },
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -0300119#define AUTOGAIN_IDX 3
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300120 {
121 {
122 .id = V4L2_CID_AUTOGAIN,
123 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 .name = "Auto Gain",
125 .minimum = 0,
126 .maximum = 1,
127 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300128#define AUTOGAIN_DEF 1
129 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 },
131 .set = sd_setautogain,
132 .get = sd_getautogain,
133 },
134};
135
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300136static struct v4l2_pix_format vga_mode[] = {
137 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300139 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 2},
142 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 320,
144 .sizeimage = 320 * 240 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 1},
147 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .bytesperline = 640,
149 .sizeimage = 640 * 480 * 3 / 8 + 590,
150 .colorspace = V4L2_COLORSPACE_JPEG,
151 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152};
153
154/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300155static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300156/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
157 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
158/* reg8 reg9 rega regb regc regd rege regf */
159 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
160/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
161 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
162/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
163 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300164};
165
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300166static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300167/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
168 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
169/* reg8 reg9 rega regb regc regd rege regf */
170 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
171/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
172 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
173/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
174 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175};
176
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300177static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300178/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
179 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
180/* reg8 reg9 rega regb regc regd rege regf */
181 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
183 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
184/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
185 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300186};
187
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300188static const __u8 sn_om6802[] = {
189/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
190 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
191/* reg8 reg9 rega regb regc regd rege regf */
192 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
194 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
195/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
196 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
198 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
199 0xf7
200};
201
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300202static const __u8 sn_ov7630[] = {
203/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
204 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
205/* reg8 reg9 rega regb regc regd rege regf */
206 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
207/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
208 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
209/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
210 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
211};
212
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300213static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300214/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
215 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
216/* reg8 reg9 rega regb regc regd rege regf */
217 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
218/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
219 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
220/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
221 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300222};
223
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300224static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300225/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
226 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
227/* reg8 reg9 rega regb regc regd rege regf */
228 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
229/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
230 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
231/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
232 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300233};
234
235/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300236static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300237 sn_hv7131,
238 sn_mi0360,
239 sn_mo4000,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300240 sn_om6802,
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300241 sn_ov7630,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300242 sn_ov7648,
243 sn_ov7660
244};
245
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300246static const __u8 gamma_def[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300247 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
248 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
249};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300250
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300251static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
253 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300254 0xf7, 0x0f, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300255};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300256static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300257 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
258 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
260 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
262 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
263 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
264
265 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
266 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
268 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
269 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
270 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
271 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
272 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
273
274 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
279
280 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
283 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300285 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300287static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300288 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
290 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
292 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
293 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
294 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
305 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
308 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
310 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
311 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
313 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
315 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
317 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
318 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
319 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
320 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
321
322 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
323 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
324 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
325 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
326 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
327
328 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
329 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
330 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
331 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
332
333 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
334 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
335/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
336/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
337 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
338 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300339 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300341static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
360 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
361 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300362 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363};
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300364static __u8 om6802_sensor_init[][8] = {
365 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
366 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
367 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
368 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
369/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
370 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
371 /* white balance & auto-exposure */
372/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
373 * set color mode */
374/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
375 * max AGC value in AE */
376/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
377 * preset AGC */
378/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
379 * preset brightness */
380/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
381 * preset contrast */
382/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
383 * preset gamma */
384 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
385 /* luminance mode (0x4f = AE) */
386 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
387 /* preset shutter */
388/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
389 * auto frame rate */
390/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
391
392/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
393/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
394/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
395/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
396 {}
397};
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300398static const __u8 ov7630_sensor_init[][8] = {
399 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
400 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
401/* win: delay 20ms */
402 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
403 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
404/* win: delay 20ms */
405 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300406/* win: i2c_r from 00 to 80 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300407 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
408 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
409 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
410 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
411 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
412 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
413 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
414 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
415 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
416 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
417 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
418 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
422 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
423 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
424 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
425 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
426 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
427 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
428 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
429 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
430 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
431 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
432 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
433/* */
434 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
436/*fixme: + 0x12, 0x04*/
437 {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
438 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
439 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300441/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300442 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300445/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300446 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300447/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300448 {}
449};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300450static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300452/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300454 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300456 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 /* GAIN BLUE RED VREF */
458 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
459 /* COM 1 BAVE GEAVE AECHH */
460 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
461 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300462 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 /* AECH CLKRC COM7 COM8 */
464 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
465 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
466 /* HSTART HSTOP VSTRT VSTOP */
467 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
468 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
469 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
470 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300471/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
472 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473 /* AEW AEB VPT BBIAS */
474 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
475 /* GbBIAS RSVD EXHCH EXHCL */
476 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
477 /* RBIAS ADVFL ASDVFH YAVE */
478 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
479 /* HSYST HSYEN HREF */
480 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
481 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
482 /* ADC ACOM OFON TSLB */
483 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
484 /* COM11 COM12 COM13 COM14 */
485 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
486 /* EDGE COM15 COM16 COM17 */
487 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
488 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
489 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
490 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
491 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
492 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
493 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
494 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
495 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
496 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
497 /* LCC1 LCC2 LCC3 LCC4 */
498 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300499 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300501 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300502 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
503 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
504 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
505 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
506 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
507 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
508 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
509 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
510 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300511 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300513 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514 /* bits[3..0]reserved */
515 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
516 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
517 /* VREF vertical frame ctrl */
518 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300519 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
520 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
521 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
522 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
523/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524/****** (some exchanges in the win trace) ******/
525 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300526 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
527 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
528 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
529/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300531/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
533 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
534 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
535 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300536 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300538/* reg 0x04 reg 0x07 reg 0x10 */
539/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300541static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
543 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
544 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
545 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
546 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
547 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
548 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
549 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
550 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
551 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
552 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
553 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
554 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
555 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
556 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
557 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
558 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
559 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
560 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
561 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
562 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
563 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
564 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
565 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
566 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
567 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
568 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
569 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
570 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
571 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
572 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
573 * This is currently setting a
574 * blue tint, and some things more , i leave it here for future test if
575 * somene is having problems with color on this sensor
576 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
577 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
578 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
579 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
580 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
581 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
582 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
583 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
584 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
585 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
586 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
587 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
588 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
589 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
590 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
591 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
592 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
593/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300594 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595};
596
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300597static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
599 0x06, 0x08, 0x0A, 0x11,
600 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
601 0x19, 0x19, 0x17, 0x15,
602 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
603 0x21, 0x2E, 0x21, 0x23,
604 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
605 0x25, 0x29, 0x2C, 0x29,
606 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
607 0x17, 0x1B, 0x29, 0x29,
608 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
609 0x29, 0x29, 0x29, 0x29,
610 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
611 0x29, 0x29, 0x29, 0x29,
612 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
613 0x29, 0x29, 0x29, 0x29
614};
615
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300616/* read <len> bytes to gspca_dev->usb_buf */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617static void reg_r(struct gspca_dev *gspca_dev,
618 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300620#ifdef GSPCA_DEBUG
621 if (len > USB_BUF_SZ) {
622 err("reg_r: buffer overflow");
623 return;
624 }
625#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 usb_control_msg(gspca_dev->dev,
627 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 0,
629 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
630 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300631 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300633 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634}
635
Jean-Francois Moine60017612008-07-18 08:46:19 -0300636static void reg_w1(struct gspca_dev *gspca_dev,
637 __u16 value,
638 __u8 data)
639{
640 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
641 gspca_dev->usb_buf[0] = data;
642 usb_control_msg(gspca_dev->dev,
643 usb_sndctrlpipe(gspca_dev->dev, 0),
644 0x08,
645 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
646 value,
647 0,
648 gspca_dev->usb_buf, 1,
649 500);
650}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300653 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 int len)
655{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300656 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
657 value, buffer[0], buffer[1]);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300658#ifdef GSPCA_DEBUG
659 if (len > USB_BUF_SZ) {
660 err("reg_w: buffer overflow");
661 return;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300662 }
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300663#endif
664 memcpy(gspca_dev->usb_buf, buffer, len);
665 usb_control_msg(gspca_dev->dev,
666 usb_sndctrlpipe(gspca_dev->dev, 0),
667 0x08,
668 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
669 value, 0,
670 gspca_dev->usb_buf, len,
671 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672}
673
Jean-Francois Moine60017612008-07-18 08:46:19 -0300674/* I2C write 1 byte */
675static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676{
677 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678
Jean-Francois Moine60017612008-07-18 08:46:19 -0300679 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
680 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
681 gspca_dev->usb_buf[1] = sd->i2c_base;
682 gspca_dev->usb_buf[2] = reg;
683 gspca_dev->usb_buf[3] = val;
684 gspca_dev->usb_buf[4] = 0;
685 gspca_dev->usb_buf[5] = 0;
686 gspca_dev->usb_buf[6] = 0;
687 gspca_dev->usb_buf[7] = 0x10;
688 usb_control_msg(gspca_dev->dev,
689 usb_sndctrlpipe(gspca_dev->dev, 0),
690 0x08,
691 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
692 0x08, /* value = i2c */
693 0,
694 gspca_dev->usb_buf, 8,
695 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696}
697
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698/* I2C write 8 bytes */
699static void i2c_w8(struct gspca_dev *gspca_dev,
700 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300702 memcpy(gspca_dev->usb_buf, buffer, 8);
703 usb_control_msg(gspca_dev->dev,
704 usb_sndctrlpipe(gspca_dev->dev, 0),
705 0x08,
706 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
707 0x08, 0, /* value, index */
708 gspca_dev->usb_buf, 8,
709 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710}
711
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300712/* read 5 bytes in gspca_dev->usb_buf */
713static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714{
715 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716 __u8 mode[8];
717
Hans de Goede3647fea2008-07-15 05:36:30 -0300718 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 mode[1] = sd->i2c_base;
720 mode[2] = reg;
721 mode[3] = 0;
722 mode[4] = 0;
723 mode[5] = 0;
724 mode[6] = 0;
725 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300726 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300727 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300728 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300729 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300730 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300731 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300732 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300733}
734
735static int probesensor(struct gspca_dev *gspca_dev)
736{
737 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738
Jean-Francois Moine60017612008-07-18 08:46:19 -0300739 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300741 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300743 i2c_r5(gspca_dev, 0); /* read sensor id */
744 if (gspca_dev->usb_buf[0] == 0x02
745 && gspca_dev->usb_buf[1] == 0x09
746 && gspca_dev->usb_buf[2] == 0x01
747 && gspca_dev->usb_buf[3] == 0x00
748 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
750 sd->sensor = SENSOR_HV7131R;
751 return SENSOR_HV7131R;
752 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300753 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300754 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
755 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300756 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
757 return -ENODEV;
758}
759
760static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300761 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762{
763 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300764 const __u8 *reg9a;
765 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300766 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300767 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300768 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300769 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300770
Jean-Francois Moine60017612008-07-18 08:46:19 -0300771 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300772 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773
774 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300775 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
776 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300777 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300778 switch (sd->bridge) {
779 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780 reg9a = reg9a_sn9c325;
781 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 default:
783 reg9a = reg9a_def;
784 break;
785 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300786 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300787
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300788 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300792 switch (sd->sensor) {
793 case SENSOR_OM6802:
Jean-Francois Moine4f30f6c2008-09-03 16:48:05 -0300794 reg_w1(gspca_dev, 0x02, 0x71);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300795 reg_w1(gspca_dev, 0x01, 0x42);
796 reg_w1(gspca_dev, 0x17, 0x64);
797 reg_w1(gspca_dev, 0x01, 0x42);
798 break;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300799/*jfm: from win trace */
800 case SENSOR_OV7630:
801 reg_w1(gspca_dev, 0x01, 0x61);
802 reg_w1(gspca_dev, 0x17, 0xe2);
803 reg_w1(gspca_dev, 0x01, 0x60);
804 reg_w1(gspca_dev, 0x01, 0x40);
805 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300806 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300807 reg_w1(gspca_dev, 0x01, 0x43);
808 reg_w1(gspca_dev, 0x17, 0xae);
809 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810 break;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300811/*jfm: from win trace */
812 case SENSOR_OV7660:
813 reg_w1(gspca_dev, 0x01, 0x61);
814 reg_w1(gspca_dev, 0x17, 0x20);
815 reg_w1(gspca_dev, 0x01, 0x60);
816 reg_w1(gspca_dev, 0x01, 0x40);
817 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300819 reg_w1(gspca_dev, 0x01, 0x43);
820 reg_w1(gspca_dev, 0x17, 0x61);
821 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300822 if (sd->sensor == SENSOR_HV7131R) {
823 if (probesensor(gspca_dev) < 0)
824 return -ENODEV;
825 }
826 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 }
828 return 0;
829}
830
831static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
832{
833 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300834 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
836
837 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300838 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839 i++;
840 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300841 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842}
843
844static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
845{
846 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847
848 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300849 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 i++;
851 }
852}
853
854static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
855{
856 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857
858 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300859 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860 i++;
861 }
862}
863
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300864static void om6802_InitSensor(struct gspca_dev *gspca_dev)
865{
866 int i = 0;
867
868 while (om6802_sensor_init[i][0]) {
869 i2c_w8(gspca_dev, om6802_sensor_init[i]);
870 i++;
871 }
872}
873
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300874static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
875{
876 int i = 0;
877
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300878 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
879 i++;
880 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300881 i++;
882 msleep(20);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300883 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
884 i++;
885 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
886 i++;
887 msleep(20);
888 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
889 i++;
890/*jfm:win i2c_r from 00 to 80*/
891
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300892 while (ov7630_sensor_init[i][0]) {
893 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
894 i++;
895 }
896}
897
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
899{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900 int i = 0;
901
902 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300903 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 i++;
905 }
906}
907
908static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
909{
910 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911
Jean-Francois Moine60017612008-07-18 08:46:19 -0300912 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
913 i++;
914 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300916 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 i++;
918 }
919}
920
921/* this function is called at probe time */
922static int sd_config(struct gspca_dev *gspca_dev,
923 const struct usb_device_id *id)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927
928 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929 cam->epaddr = 0x01;
930 cam->cam_mode = vga_mode;
931 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300932
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300933 sd->bridge = id->driver_info >> 16;
934 sd->sensor = id->driver_info >> 8;
935 sd->i2c_base = id->driver_info;
936
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300938 sd->brightness = BRIGHTNESS_DEF;
939 sd->contrast = CONTRAST_DEF;
940 sd->colors = COLOR_DEF;
941 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300942 sd->ag_cnt = -1;
943
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -0300944 switch (sd->sensor) {
945 case SENSOR_OV7630:
946 case SENSOR_OV7648:
947 case SENSOR_OV7660:
948 gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
949 break;
950 }
951
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952 return 0;
953}
954
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300955/* this function is called at probe and resume time */
956static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957{
958 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300959/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300961 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962
Hans de Goede3647fea2008-07-15 05:36:30 -0300963 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300964 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300965 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300966 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
967 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300968 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300969 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300970 switch (sd->bridge) {
971 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300972 if (regF1 != 0x11)
973 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300974 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300976 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977 if (regF1 != 0x11)
978 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300979 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300981 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982 if (regF1 != 0x12)
983 return -ENODEV;
984 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300985 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 break;
987 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300988/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300989/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990 if (regF1 != 0x12)
991 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300992 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 break;
994 }
995
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -0300996 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997
998 return 0;
999}
1000
1001static unsigned int setexposure(struct gspca_dev *gspca_dev,
1002 unsigned int expo)
1003{
1004 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001005 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001006 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001007 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001008 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001009 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001010 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1011
1012 switch (sd->sensor) {
1013 case SENSOR_HV7131R: {
1014 __u8 Expodoit[] =
1015 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1016
1017 Expodoit[3] = expo >> 16;
1018 Expodoit[4] = expo >> 8;
1019 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001020 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 break;
1022 }
1023 case SENSOR_MI0360: {
1024 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1025 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1026
1027 if (expo > 0x0635)
1028 expo = 0x0635;
1029 else if (expo < 0x0001)
1030 expo = 0x0001;
1031 expoMi[3] = expo >> 8;
1032 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001033 i2c_w8(gspca_dev, expoMi);
1034 i2c_w8(gspca_dev, doit);
1035 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001036 break;
1037 }
1038 case SENSOR_MO4000: {
1039 __u8 expoMof[] =
1040 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1041 __u8 expoMo10[] =
1042 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1043
1044 if (expo > 0x1fff)
1045 expo = 0x1fff;
1046 else if (expo < 0x0001)
1047 expo = 0x0001;
1048 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001049 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050 expoMo10[3] = ((expo & 0x1c00) >> 10)
1051 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001052 i2c_w8(gspca_dev, expoMo10);
1053 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001054 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055 ((expoMo10[3] & 0x07) << 10)
1056 | (expoMof[3] << 2)
1057 | ((expoMo10[3] & 0x30) >> 4));
1058 break;
1059 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001060 case SENSOR_OM6802: {
1061 __u8 gainOm[] =
1062 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1063
1064 if (expo > 0x03ff)
1065 expo = 0x03ff;
1066 if (expo < 0x0001)
1067 expo = 0x0001;
1068 gainOm[3] = expo >> 2;
1069 i2c_w8(gspca_dev, gainOm);
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001070 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001071 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1072 break;
1073 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001074 }
1075 return expo;
1076}
1077
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001078/* this function is used for sensors o76xx only */
1079static void setbrightcont(struct gspca_dev *gspca_dev)
1080{
1081 struct sd *sd = (struct sd *) gspca_dev;
1082 unsigned val;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001083 __u8 reg84_full[0x15];
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001084
1085 memset(reg84_full, 0, sizeof reg84_full);
1086 val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
1087 reg84_full[2] = val;
1088 reg84_full[0] = (val + 1) / 2;
1089 reg84_full[4] = (val + 1) / 5;
1090 if (val > BRIGHTNESS_DEF)
1091 val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
1092 / BRIGHTNESS_MAX;
1093 else
1094 val = 0;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001095 reg84_full[0x12] = val; /* 00..1f */
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001096 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1097}
1098
1099/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001100static void setbrightness(struct gspca_dev *gspca_dev)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103 unsigned int expo;
1104 __u8 k2;
1105
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001106 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001107 switch (sd->sensor) {
1108 case SENSOR_HV7131R:
1109 expo = sd->brightness << 4;
1110 if (expo > 0x002dc6c0)
1111 expo = 0x002dc6c0;
1112 else if (expo < 0x02a0)
1113 expo = 0x02a0;
1114 sd->exposure = setexposure(gspca_dev, expo);
1115 break;
1116 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117 case SENSOR_MO4000:
1118 expo = sd->brightness >> 4;
1119 sd->exposure = setexposure(gspca_dev, expo);
1120 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001121 case SENSOR_OM6802:
1122 expo = sd->brightness >> 6;
1123 sd->exposure = setexposure(gspca_dev, expo);
1124 k2 = sd->brightness >> 11;
1125 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001126 }
1127
Jean-Francois Moine60017612008-07-18 08:46:19 -03001128 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001129}
1130
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001131/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001132static void setcontrast(struct gspca_dev *gspca_dev)
1133{
1134 struct sd *sd = (struct sd *) gspca_dev;
1135 __u8 k2;
1136 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1137
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001138 k2 = sd->contrast;
1139 contrast[2] = k2;
1140 contrast[0] = (k2 + 1) >> 1;
1141 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001142 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143}
1144
1145static void setcolors(struct gspca_dev *gspca_dev)
1146{
1147 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001148 __u8 blue, red;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001149
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001150 if (sd->colors >= 32) {
1151 red = 32 + (sd->colors - 32) / 2;
1152 blue = 64 - sd->colors;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001153 } else {
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001154 red = sd->colors;
1155 blue = 32 + (32 - sd->colors) / 2;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001156 }
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001157 reg_w1(gspca_dev, 0x05, red);
1158/* reg_w1(gspca_dev, 0x07, 32); */
1159 reg_w1(gspca_dev, 0x06, blue);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160}
1161
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001162static void setautogain(struct gspca_dev *gspca_dev)
1163{
1164 struct sd *sd = (struct sd *) gspca_dev;
1165
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001166 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1167 return;
1168 if (sd->autogain)
1169 sd->ag_cnt = AG_CNT_START;
1170 else
1171 sd->ag_cnt = -1;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001172}
1173
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001174/* -- start the camera -- */
1175static void sd_start(struct gspca_dev *gspca_dev)
1176{
1177 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001178 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001179 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001180 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001182 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1183 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001184 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001185 static const __u8 CE_ov76xx[] =
1186 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001187
1188 sn9c1xx = sn_tb[(int) sd->sensor];
1189 configure_gpio(gspca_dev, sn9c1xx);
1190
Jean-Francois Moine60017612008-07-18 08:46:19 -03001191 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1192 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1193 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1194 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1195 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1196 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1197 reg_w1(gspca_dev, 0xd3, 0x50);
1198 reg_w1(gspca_dev, 0xc6, 0x00);
1199 reg_w1(gspca_dev, 0xc7, 0x00);
1200 reg_w1(gspca_dev, 0xc8, 0x50);
1201 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001202 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001203 switch (sd->sensor) {
1204 case SENSOR_OV7630:
1205 reg17 = 0xe2;
1206 break;
1207 case SENSOR_OV7648:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001208 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001209 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001210/*jfm: from win trace */
1211 case SENSOR_OV7660:
1212 reg17 = 0xa0;
1213 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001214 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001215 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001216 break;
1217 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001218 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001219 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1220 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1221 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1222 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001223 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1224 for (i = 0; i < 8; i++)
1225 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001226 reg_w1(gspca_dev, 0x9a, 0x08);
1227 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001228
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001229 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001230 if (mode)
1231 reg1 = 0x46; /* 320 clk 48Mhz */
1232 else
1233 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001234 reg17 = 0x61;
1235 switch (sd->sensor) {
1236 case SENSOR_HV7131R:
1237 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238 break;
1239 case SENSOR_MI0360:
1240 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001241 break;
1242 case SENSOR_MO4000:
1243 mo4000_InitSensor(gspca_dev);
1244 if (mode) {
1245/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1246 reg1 = 0x06; /* clk 24Mz */
1247 } else {
1248 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001249/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001250 }
1251 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001252 case SENSOR_OM6802:
1253 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001254 reg17 = 0x64; /* 640 MCKSIZE */
1255 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001256 case SENSOR_OV7630:
1257 ov7630_InitSensor(gspca_dev);
1258 reg17 = 0xe2;
Jean-Francois Moine5b064da2008-09-03 16:48:08 -03001259 reg1 = 0x44;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001260 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001261 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001262 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001263 reg17 = 0xa2;
1264 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001265/* if (mode)
1266 ; * 320x2...
1267 else
1268 ; * 640x... */
1269 break;
1270 default:
1271/* case SENSOR_OV7660: */
1272 ov7660_InitSensor(gspca_dev);
1273 if (mode) {
1274/* reg17 = 0x21; * 320 */
1275/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001276/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001277 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001278 reg17 = 0x22; /* 640 MCKSIZE */
1279 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001280 }
1281 break;
1282 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001283 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001284 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001285 switch (sd->sensor) {
1286 case SENSOR_OV7630:
1287 case SENSOR_OV7648:
1288 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289 break;
1290 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001292 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1293 break;
1294 }
1295
1296 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001297 reg18 = sn9c1xx[0x18] | (mode << 4);
1298 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001299
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001300 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1301 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001302
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001303 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001304
Jean-Francois Moine60017612008-07-18 08:46:19 -03001305 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001306 switch (sd->sensor) {
1307 case SENSOR_HV7131R:
1308 case SENSOR_MI0360:
1309 case SENSOR_MO4000:
1310 case SENSOR_OM6802:
1311 setbrightness(gspca_dev);
1312 setcontrast(gspca_dev);
1313 break;
1314 default: /* OV76xx */
1315 setbrightcont(gspca_dev);
1316 break;
1317 }
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001318 setautogain(gspca_dev);
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001319 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001320}
1321
1322static void sd_stopN(struct gspca_dev *gspca_dev)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001325 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001326 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001327 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001329 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001330 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001331
1332 data = 0x0b;
1333 switch (sd->sensor) {
1334 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001335 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001336 data = 0x2b;
1337 break;
1338 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001339 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001340 data = 0x29;
1341 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001342 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001343 case SENSOR_OV7648:
1344 data = 0x29;
1345 break;
1346 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001347/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001348/* case SENSOR_OV7660: */
1349 break;
1350 }
1351 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001352 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1353 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1354 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1355 reg_w1(gspca_dev, 0x01, data);
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001356 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001357}
1358
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001359static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001360{
1361 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001362 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001363 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001364 __u8 luma_mean = 130;
1365 __u8 luma_delta = 20;
1366
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001367 /* Thanks S., without your advice, autobright should not work :) */
1368 if (sd->ag_cnt < 0)
1369 return;
1370 if (--sd->ag_cnt >= 0)
1371 return;
1372 sd->ag_cnt = AG_CNT_START;
1373
1374 delta = atomic_read(&sd->avg_lum);
1375 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001376 if (delta < luma_mean - luma_delta ||
1377 delta > luma_mean + luma_delta) {
1378 switch (sd->sensor) {
1379 case SENSOR_HV7131R:
1380 expotimes = sd->exposure >> 8;
1381 expotimes += (luma_mean - delta) >> 4;
1382 if (expotimes < 0)
1383 expotimes = 0;
1384 sd->exposure = setexposure(gspca_dev,
1385 (unsigned int) (expotimes << 8));
1386 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001387 default:
1388/* case SENSOR_MO4000: */
1389/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001390/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001391 expotimes = sd->exposure;
1392 expotimes += (luma_mean - delta) >> 6;
1393 if (expotimes < 0)
1394 expotimes = 0;
1395 sd->exposure = setexposure(gspca_dev,
1396 (unsigned int) expotimes);
1397 setcolors(gspca_dev);
1398 break;
1399 }
1400 }
1401}
1402
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001403/* scan the URB packets */
1404/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001405static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1406 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001407 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001408 int len) /* iso packet length */
1409{
1410 struct sd *sd = (struct sd *) gspca_dev;
1411 int sof, avg_lum;
1412
1413 sof = len - 64;
1414 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1415
1416 /* end of frame */
1417 gspca_frame_add(gspca_dev, LAST_PACKET,
1418 frame, data, sof + 2);
1419 if (sd->ag_cnt < 0)
1420 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001421/* w1 w2 w3 */
1422/* w4 w5 w6 */
1423/* w7 w8 */
1424/* w4 */
1425 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1426/* w6 */
1427 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1428/* w2 */
1429 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1430/* w8 */
1431 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1432/* w5 */
1433 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1434 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001435 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001436 return;
1437 }
1438 if (gspca_dev->last_packet_type == LAST_PACKET) {
1439
1440 /* put the JPEG 422 header */
1441 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1442 }
1443 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1444}
1445
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001446static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1447{
1448 struct sd *sd = (struct sd *) gspca_dev;
1449
1450 sd->brightness = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001451 if (gspca_dev->streaming) {
1452 switch (sd->sensor) {
1453 case SENSOR_HV7131R:
1454 case SENSOR_MI0360:
1455 case SENSOR_MO4000:
1456 case SENSOR_OM6802:
1457 setbrightness(gspca_dev);
1458 break;
1459 default: /* OV76xx */
1460 setbrightcont(gspca_dev);
1461 break;
1462 }
1463 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001464 return 0;
1465}
1466
1467static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1468{
1469 struct sd *sd = (struct sd *) gspca_dev;
1470
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001471 *val = sd->brightness;
1472 return 0;
1473}
1474
1475static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
1478
1479 sd->contrast = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001480 if (gspca_dev->streaming) {
1481 switch (sd->sensor) {
1482 case SENSOR_HV7131R:
1483 case SENSOR_MI0360:
1484 case SENSOR_MO4000:
1485 case SENSOR_OM6802:
1486 setcontrast(gspca_dev);
1487 break;
1488 default: /* OV76xx */
1489 setbrightcont(gspca_dev);
1490 break;
1491 }
1492 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001493 return 0;
1494}
1495
1496static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1497{
1498 struct sd *sd = (struct sd *) gspca_dev;
1499
1500 *val = sd->contrast;
1501 return 0;
1502}
1503
1504static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1505{
1506 struct sd *sd = (struct sd *) gspca_dev;
1507
1508 sd->colors = val;
1509 if (gspca_dev->streaming)
1510 setcolors(gspca_dev);
1511 return 0;
1512}
1513
1514static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1515{
1516 struct sd *sd = (struct sd *) gspca_dev;
1517
1518 *val = sd->colors;
1519 return 0;
1520}
1521
1522static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1523{
1524 struct sd *sd = (struct sd *) gspca_dev;
1525
1526 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001527 if (gspca_dev->streaming)
1528 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001529 return 0;
1530}
1531
1532static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1533{
1534 struct sd *sd = (struct sd *) gspca_dev;
1535
1536 *val = sd->autogain;
1537 return 0;
1538}
1539
1540/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001541static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001542 .name = MODULE_NAME,
1543 .ctrls = sd_ctrls,
1544 .nctrls = ARRAY_SIZE(sd_ctrls),
1545 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001546 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001547 .start = sd_start,
1548 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001549 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001550 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001551};
1552
1553/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001554#define BSI(bridge, sensor, i2c_addr) \
1555 .driver_info = (BRIDGE_ ## bridge << 16) \
1556 | (SENSOR_ ## sensor << 8) \
1557 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001558static const __devinitdata struct usb_device_id device_table[] = {
Hans de Goede222a07f2008-09-03 17:12:20 -03001559#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001560 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1561 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1562 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1563 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1564 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001565#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001566 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1567 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1568/* bw600.inf:
1569 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1570/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1571/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1572 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1573/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1574 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1575/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1576/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1577 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1578/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1579/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1580 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1581 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1582/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1583/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1584/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1585/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001586 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1587/*bw600.inf:*/
1588 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001589 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001590 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001591/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Hans de Goede222a07f2008-09-03 17:12:20 -03001592#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001593 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001594#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001595 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001596#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001597/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1598 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1599 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1600/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001601#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001602 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001603 {}
1604};
1605MODULE_DEVICE_TABLE(usb, device_table);
1606
1607/* -- device connect -- */
1608static int sd_probe(struct usb_interface *intf,
1609 const struct usb_device_id *id)
1610{
1611 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1612 THIS_MODULE);
1613}
1614
1615static struct usb_driver sd_driver = {
1616 .name = MODULE_NAME,
1617 .id_table = device_table,
1618 .probe = sd_probe,
1619 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001620#ifdef CONFIG_PM
1621 .suspend = gspca_suspend,
1622 .resume = gspca_resume,
1623#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001624};
1625
1626/* -- module insert / remove -- */
1627static int __init sd_mod_init(void)
1628{
1629 if (usb_register(&sd_driver) < 0)
1630 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001631 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001632 return 0;
1633}
1634static void __exit sd_mod_exit(void)
1635{
1636 usb_deregister(&sd_driver);
1637 info("deregistered");
1638}
1639
1640module_init(sd_mod_init);
1641module_exit(sd_mod_exit);