blob: feb17dbdd7b33daaf8952ab0da94e058024d247e [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 Moine739570b2008-07-14 09:38:29 -0300616/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
617static void reg_r(struct gspca_dev *gspca_dev,
618 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300620 usb_control_msg(gspca_dev->dev,
621 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622 0,
623 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
624 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300625 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300627 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628}
629
Jean-Francois Moine60017612008-07-18 08:46:19 -0300630static void reg_w1(struct gspca_dev *gspca_dev,
631 __u16 value,
632 __u8 data)
633{
634 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
635 gspca_dev->usb_buf[0] = data;
636 usb_control_msg(gspca_dev->dev,
637 usb_sndctrlpipe(gspca_dev->dev, 0),
638 0x08,
639 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
640 value,
641 0,
642 gspca_dev->usb_buf, 1,
643 500);
644}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300645static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300647 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 int len)
649{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300650 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
651 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300652 if (len <= sizeof gspca_dev->usb_buf) {
653 memcpy(gspca_dev->usb_buf, buffer, len);
654 usb_control_msg(gspca_dev->dev,
655 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300656 0x08,
657 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
658 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300659 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300660 500);
661 } else {
662 __u8 *tmpbuf;
663
664 tmpbuf = kmalloc(len, GFP_KERNEL);
665 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300666 usb_control_msg(gspca_dev->dev,
667 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300668 0x08,
669 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
670 value, 0,
671 tmpbuf, len,
672 500);
673 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300674 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675}
676
Jean-Francois Moine60017612008-07-18 08:46:19 -0300677/* I2C write 1 byte */
678static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679{
680 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681
Jean-Francois Moine60017612008-07-18 08:46:19 -0300682 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
683 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
684 gspca_dev->usb_buf[1] = sd->i2c_base;
685 gspca_dev->usb_buf[2] = reg;
686 gspca_dev->usb_buf[3] = val;
687 gspca_dev->usb_buf[4] = 0;
688 gspca_dev->usb_buf[5] = 0;
689 gspca_dev->usb_buf[6] = 0;
690 gspca_dev->usb_buf[7] = 0x10;
691 usb_control_msg(gspca_dev->dev,
692 usb_sndctrlpipe(gspca_dev->dev, 0),
693 0x08,
694 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
695 0x08, /* value = i2c */
696 0,
697 gspca_dev->usb_buf, 8,
698 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699}
700
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300701/* I2C write 8 bytes */
702static void i2c_w8(struct gspca_dev *gspca_dev,
703 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300705 memcpy(gspca_dev->usb_buf, buffer, 8);
706 usb_control_msg(gspca_dev->dev,
707 usb_sndctrlpipe(gspca_dev->dev, 0),
708 0x08,
709 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
710 0x08, 0, /* value, index */
711 gspca_dev->usb_buf, 8,
712 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713}
714
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300715/* read 5 bytes in gspca_dev->usb_buf */
716static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717{
718 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 __u8 mode[8];
720
Hans de Goede3647fea2008-07-15 05:36:30 -0300721 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722 mode[1] = sd->i2c_base;
723 mode[2] = reg;
724 mode[3] = 0;
725 mode[4] = 0;
726 mode[5] = 0;
727 mode[6] = 0;
728 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300729 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300730 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300731 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300733 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300734 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300735 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736}
737
738static int probesensor(struct gspca_dev *gspca_dev)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741
Jean-Francois Moine60017612008-07-18 08:46:19 -0300742 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300744 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300746 i2c_r5(gspca_dev, 0); /* read sensor id */
747 if (gspca_dev->usb_buf[0] == 0x02
748 && gspca_dev->usb_buf[1] == 0x09
749 && gspca_dev->usb_buf[2] == 0x01
750 && gspca_dev->usb_buf[3] == 0x00
751 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
753 sd->sensor = SENSOR_HV7131R;
754 return SENSOR_HV7131R;
755 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300756 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300757 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
758 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
760 return -ENODEV;
761}
762
763static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300764 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765{
766 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300767 const __u8 *reg9a;
768 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300770 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300772 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773
Jean-Francois Moine60017612008-07-18 08:46:19 -0300774 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300775 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300776
777 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300778 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
779 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300780 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300781 switch (sd->bridge) {
782 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 reg9a = reg9a_sn9c325;
784 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300785 default:
786 reg9a = reg9a_def;
787 break;
788 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300789 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300790
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300791 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300793 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300795 switch (sd->sensor) {
796 case SENSOR_OM6802:
Jean-Francois Moine4f30f6c2008-09-03 16:48:05 -0300797 reg_w1(gspca_dev, 0x02, 0x71);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300798 reg_w1(gspca_dev, 0x01, 0x42);
799 reg_w1(gspca_dev, 0x17, 0x64);
800 reg_w1(gspca_dev, 0x01, 0x42);
801 break;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300802/*jfm: from win trace */
803 case SENSOR_OV7630:
804 reg_w1(gspca_dev, 0x01, 0x61);
805 reg_w1(gspca_dev, 0x17, 0xe2);
806 reg_w1(gspca_dev, 0x01, 0x60);
807 reg_w1(gspca_dev, 0x01, 0x40);
808 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300809 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300810 reg_w1(gspca_dev, 0x01, 0x43);
811 reg_w1(gspca_dev, 0x17, 0xae);
812 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813 break;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300814/*jfm: from win trace */
815 case SENSOR_OV7660:
816 reg_w1(gspca_dev, 0x01, 0x61);
817 reg_w1(gspca_dev, 0x17, 0x20);
818 reg_w1(gspca_dev, 0x01, 0x60);
819 reg_w1(gspca_dev, 0x01, 0x40);
820 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300821 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300822 reg_w1(gspca_dev, 0x01, 0x43);
823 reg_w1(gspca_dev, 0x17, 0x61);
824 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300825 if (sd->sensor == SENSOR_HV7131R) {
826 if (probesensor(gspca_dev) < 0)
827 return -ENODEV;
828 }
829 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830 }
831 return 0;
832}
833
834static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
835{
836 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300837 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
839
840 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300841 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 i++;
843 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845}
846
847static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
848{
849 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850
851 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300852 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 i++;
854 }
855}
856
857static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
858{
859 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860
861 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300862 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 i++;
864 }
865}
866
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300867static void om6802_InitSensor(struct gspca_dev *gspca_dev)
868{
869 int i = 0;
870
871 while (om6802_sensor_init[i][0]) {
872 i2c_w8(gspca_dev, om6802_sensor_init[i]);
873 i++;
874 }
875}
876
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300877static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
878{
879 int i = 0;
880
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300881 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
882 i++;
883 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300884 i++;
885 msleep(20);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300886 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
887 i++;
888 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
889 i++;
890 msleep(20);
891 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
892 i++;
893/*jfm:win i2c_r from 00 to 80*/
894
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300895 while (ov7630_sensor_init[i][0]) {
896 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
897 i++;
898 }
899}
900
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
902{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903 int i = 0;
904
905 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300906 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 i++;
908 }
909}
910
911static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
912{
913 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300914
Jean-Francois Moine60017612008-07-18 08:46:19 -0300915 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
916 i++;
917 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300919 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 i++;
921 }
922}
923
924/* this function is called at probe time */
925static int sd_config(struct gspca_dev *gspca_dev,
926 const struct usb_device_id *id)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930
931 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 cam->epaddr = 0x01;
933 cam->cam_mode = vga_mode;
934 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300935
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300936 sd->bridge = id->driver_info >> 16;
937 sd->sensor = id->driver_info >> 8;
938 sd->i2c_base = id->driver_info;
939
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300941 sd->brightness = BRIGHTNESS_DEF;
942 sd->contrast = CONTRAST_DEF;
943 sd->colors = COLOR_DEF;
944 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300945 sd->ag_cnt = -1;
946
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -0300947 switch (sd->sensor) {
948 case SENSOR_OV7630:
949 case SENSOR_OV7648:
950 case SENSOR_OV7660:
951 gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
952 break;
953 }
954
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 return 0;
956}
957
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300958/* this function is called at probe and resume time */
959static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960{
961 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300962/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300964 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965
Hans de Goede3647fea2008-07-15 05:36:30 -0300966 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300967 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300968 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300969 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
970 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300971 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300972 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300973 switch (sd->bridge) {
974 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 if (regF1 != 0x11)
976 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300977 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300979 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980 if (regF1 != 0x11)
981 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300982 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300984 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 if (regF1 != 0x12)
986 return -ENODEV;
987 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300988 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989 break;
990 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300991/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300992/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 if (regF1 != 0x12)
994 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300995 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 break;
997 }
998
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -0300999 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001000
1001 return 0;
1002}
1003
1004static unsigned int setexposure(struct gspca_dev *gspca_dev,
1005 unsigned int expo)
1006{
1007 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001008 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001010 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001012 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1014
1015 switch (sd->sensor) {
1016 case SENSOR_HV7131R: {
1017 __u8 Expodoit[] =
1018 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1019
1020 Expodoit[3] = expo >> 16;
1021 Expodoit[4] = expo >> 8;
1022 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001023 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001024 break;
1025 }
1026 case SENSOR_MI0360: {
1027 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1028 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1029
1030 if (expo > 0x0635)
1031 expo = 0x0635;
1032 else if (expo < 0x0001)
1033 expo = 0x0001;
1034 expoMi[3] = expo >> 8;
1035 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001036 i2c_w8(gspca_dev, expoMi);
1037 i2c_w8(gspca_dev, doit);
1038 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001039 break;
1040 }
1041 case SENSOR_MO4000: {
1042 __u8 expoMof[] =
1043 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1044 __u8 expoMo10[] =
1045 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1046
1047 if (expo > 0x1fff)
1048 expo = 0x1fff;
1049 else if (expo < 0x0001)
1050 expo = 0x0001;
1051 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001052 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 expoMo10[3] = ((expo & 0x1c00) >> 10)
1054 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001055 i2c_w8(gspca_dev, expoMo10);
1056 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001057 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001058 ((expoMo10[3] & 0x07) << 10)
1059 | (expoMof[3] << 2)
1060 | ((expoMo10[3] & 0x30) >> 4));
1061 break;
1062 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001063 case SENSOR_OM6802: {
1064 __u8 gainOm[] =
1065 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1066
1067 if (expo > 0x03ff)
1068 expo = 0x03ff;
1069 if (expo < 0x0001)
1070 expo = 0x0001;
1071 gainOm[3] = expo >> 2;
1072 i2c_w8(gspca_dev, gainOm);
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001073 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001074 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1075 break;
1076 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001077 }
1078 return expo;
1079}
1080
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001081/* this function is used for sensors o76xx only */
1082static void setbrightcont(struct gspca_dev *gspca_dev)
1083{
1084 struct sd *sd = (struct sd *) gspca_dev;
1085 unsigned val;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001086 __u8 reg84_full[0x15];
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001087
1088 memset(reg84_full, 0, sizeof reg84_full);
1089 val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
1090 reg84_full[2] = val;
1091 reg84_full[0] = (val + 1) / 2;
1092 reg84_full[4] = (val + 1) / 5;
1093 if (val > BRIGHTNESS_DEF)
1094 val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
1095 / BRIGHTNESS_MAX;
1096 else
1097 val = 0;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001098 reg84_full[0x12] = val; /* 00..1f */
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001099 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1100}
1101
1102/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001103static void setbrightness(struct gspca_dev *gspca_dev)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106 unsigned int expo;
1107 __u8 k2;
1108
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001109 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110 switch (sd->sensor) {
1111 case SENSOR_HV7131R:
1112 expo = sd->brightness << 4;
1113 if (expo > 0x002dc6c0)
1114 expo = 0x002dc6c0;
1115 else if (expo < 0x02a0)
1116 expo = 0x02a0;
1117 sd->exposure = setexposure(gspca_dev, expo);
1118 break;
1119 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001120 case SENSOR_MO4000:
1121 expo = sd->brightness >> 4;
1122 sd->exposure = setexposure(gspca_dev, expo);
1123 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001124 case SENSOR_OM6802:
1125 expo = sd->brightness >> 6;
1126 sd->exposure = setexposure(gspca_dev, expo);
1127 k2 = sd->brightness >> 11;
1128 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001129 }
1130
Jean-Francois Moine60017612008-07-18 08:46:19 -03001131 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001132}
1133
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001134/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001135static void setcontrast(struct gspca_dev *gspca_dev)
1136{
1137 struct sd *sd = (struct sd *) gspca_dev;
1138 __u8 k2;
1139 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1140
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001141 k2 = sd->contrast;
1142 contrast[2] = k2;
1143 contrast[0] = (k2 + 1) >> 1;
1144 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001145 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001146}
1147
1148static void setcolors(struct gspca_dev *gspca_dev)
1149{
1150 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001151 __u8 blue, red;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001152
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001153 if (sd->colors >= 32) {
1154 red = 32 + (sd->colors - 32) / 2;
1155 blue = 64 - sd->colors;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001156 } else {
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001157 red = sd->colors;
1158 blue = 32 + (32 - sd->colors) / 2;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001159 }
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001160 reg_w1(gspca_dev, 0x05, red);
1161/* reg_w1(gspca_dev, 0x07, 32); */
1162 reg_w1(gspca_dev, 0x06, blue);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001163}
1164
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001165static void setautogain(struct gspca_dev *gspca_dev)
1166{
1167 struct sd *sd = (struct sd *) gspca_dev;
1168
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001169 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1170 return;
1171 if (sd->autogain)
1172 sd->ag_cnt = AG_CNT_START;
1173 else
1174 sd->ag_cnt = -1;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001175}
1176
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001177/* -- start the camera -- */
1178static void sd_start(struct gspca_dev *gspca_dev)
1179{
1180 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001182 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001183 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001185 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1186 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001187 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001188 static const __u8 CE_ov76xx[] =
1189 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001190
1191 sn9c1xx = sn_tb[(int) sd->sensor];
1192 configure_gpio(gspca_dev, sn9c1xx);
1193
Jean-Francois Moine60017612008-07-18 08:46:19 -03001194 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1195 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1196 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1197 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1198 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1199 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1200 reg_w1(gspca_dev, 0xd3, 0x50);
1201 reg_w1(gspca_dev, 0xc6, 0x00);
1202 reg_w1(gspca_dev, 0xc7, 0x00);
1203 reg_w1(gspca_dev, 0xc8, 0x50);
1204 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001205 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001206 switch (sd->sensor) {
1207 case SENSOR_OV7630:
1208 reg17 = 0xe2;
1209 break;
1210 case SENSOR_OV7648:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001211 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001212 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001213/*jfm: from win trace */
1214 case SENSOR_OV7660:
1215 reg17 = 0xa0;
1216 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001217 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001218 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001219 break;
1220 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001221 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001222 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1223 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1224 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1225 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001226 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1227 for (i = 0; i < 8; i++)
1228 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001229 reg_w1(gspca_dev, 0x9a, 0x08);
1230 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001232 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001233 if (mode)
1234 reg1 = 0x46; /* 320 clk 48Mhz */
1235 else
1236 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001237 reg17 = 0x61;
1238 switch (sd->sensor) {
1239 case SENSOR_HV7131R:
1240 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001241 break;
1242 case SENSOR_MI0360:
1243 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001244 break;
1245 case SENSOR_MO4000:
1246 mo4000_InitSensor(gspca_dev);
1247 if (mode) {
1248/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1249 reg1 = 0x06; /* clk 24Mz */
1250 } else {
1251 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001252/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 }
1254 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001255 case SENSOR_OM6802:
1256 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001257 reg17 = 0x64; /* 640 MCKSIZE */
1258 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001259 case SENSOR_OV7630:
1260 ov7630_InitSensor(gspca_dev);
1261 reg17 = 0xe2;
Jean-Francois Moine5b064da2008-09-03 16:48:08 -03001262 reg1 = 0x44;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001263 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001264 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001265 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001266 reg17 = 0xa2;
1267 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001268/* if (mode)
1269 ; * 320x2...
1270 else
1271 ; * 640x... */
1272 break;
1273 default:
1274/* case SENSOR_OV7660: */
1275 ov7660_InitSensor(gspca_dev);
1276 if (mode) {
1277/* reg17 = 0x21; * 320 */
1278/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001279/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001280 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001281 reg17 = 0x22; /* 640 MCKSIZE */
1282 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001283 }
1284 break;
1285 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001286 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001287 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001288 switch (sd->sensor) {
1289 case SENSOR_OV7630:
1290 case SENSOR_OV7648:
1291 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001292 break;
1293 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001294 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001295 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1296 break;
1297 }
1298
1299 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001300 reg18 = sn9c1xx[0x18] | (mode << 4);
1301 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001302
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001303 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1304 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001305
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001306 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001307
Jean-Francois Moine60017612008-07-18 08:46:19 -03001308 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001309 switch (sd->sensor) {
1310 case SENSOR_HV7131R:
1311 case SENSOR_MI0360:
1312 case SENSOR_MO4000:
1313 case SENSOR_OM6802:
1314 setbrightness(gspca_dev);
1315 setcontrast(gspca_dev);
1316 break;
1317 default: /* OV76xx */
1318 setbrightcont(gspca_dev);
1319 break;
1320 }
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001321 setautogain(gspca_dev);
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001322 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001323}
1324
1325static void sd_stopN(struct gspca_dev *gspca_dev)
1326{
1327 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001328 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001329 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001330 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001331 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001332 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001333 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001334
1335 data = 0x0b;
1336 switch (sd->sensor) {
1337 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001338 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001339 data = 0x2b;
1340 break;
1341 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001342 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001343 data = 0x29;
1344 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001345 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001346 case SENSOR_OV7648:
1347 data = 0x29;
1348 break;
1349 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001350/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001351/* case SENSOR_OV7660: */
1352 break;
1353 }
1354 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001355 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1356 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1357 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1358 reg_w1(gspca_dev, 0x01, data);
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001359 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001360}
1361
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001362static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001363{
1364 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001365 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001366 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001367 __u8 luma_mean = 130;
1368 __u8 luma_delta = 20;
1369
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001370 /* Thanks S., without your advice, autobright should not work :) */
1371 if (sd->ag_cnt < 0)
1372 return;
1373 if (--sd->ag_cnt >= 0)
1374 return;
1375 sd->ag_cnt = AG_CNT_START;
1376
1377 delta = atomic_read(&sd->avg_lum);
1378 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001379 if (delta < luma_mean - luma_delta ||
1380 delta > luma_mean + luma_delta) {
1381 switch (sd->sensor) {
1382 case SENSOR_HV7131R:
1383 expotimes = sd->exposure >> 8;
1384 expotimes += (luma_mean - delta) >> 4;
1385 if (expotimes < 0)
1386 expotimes = 0;
1387 sd->exposure = setexposure(gspca_dev,
1388 (unsigned int) (expotimes << 8));
1389 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001390 default:
1391/* case SENSOR_MO4000: */
1392/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001393/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001394 expotimes = sd->exposure;
1395 expotimes += (luma_mean - delta) >> 6;
1396 if (expotimes < 0)
1397 expotimes = 0;
1398 sd->exposure = setexposure(gspca_dev,
1399 (unsigned int) expotimes);
1400 setcolors(gspca_dev);
1401 break;
1402 }
1403 }
1404}
1405
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001406/* scan the URB packets */
1407/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001408static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1409 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001410 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001411 int len) /* iso packet length */
1412{
1413 struct sd *sd = (struct sd *) gspca_dev;
1414 int sof, avg_lum;
1415
1416 sof = len - 64;
1417 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1418
1419 /* end of frame */
1420 gspca_frame_add(gspca_dev, LAST_PACKET,
1421 frame, data, sof + 2);
1422 if (sd->ag_cnt < 0)
1423 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001424/* w1 w2 w3 */
1425/* w4 w5 w6 */
1426/* w7 w8 */
1427/* w4 */
1428 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1429/* w6 */
1430 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1431/* w2 */
1432 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1433/* w8 */
1434 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1435/* w5 */
1436 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1437 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001438 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001439 return;
1440 }
1441 if (gspca_dev->last_packet_type == LAST_PACKET) {
1442
1443 /* put the JPEG 422 header */
1444 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1445 }
1446 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1447}
1448
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001449static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1450{
1451 struct sd *sd = (struct sd *) gspca_dev;
1452
1453 sd->brightness = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001454 if (gspca_dev->streaming) {
1455 switch (sd->sensor) {
1456 case SENSOR_HV7131R:
1457 case SENSOR_MI0360:
1458 case SENSOR_MO4000:
1459 case SENSOR_OM6802:
1460 setbrightness(gspca_dev);
1461 break;
1462 default: /* OV76xx */
1463 setbrightcont(gspca_dev);
1464 break;
1465 }
1466 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001467 return 0;
1468}
1469
1470static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1471{
1472 struct sd *sd = (struct sd *) gspca_dev;
1473
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001474 *val = sd->brightness;
1475 return 0;
1476}
1477
1478static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1479{
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 sd->contrast = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001483 if (gspca_dev->streaming) {
1484 switch (sd->sensor) {
1485 case SENSOR_HV7131R:
1486 case SENSOR_MI0360:
1487 case SENSOR_MO4000:
1488 case SENSOR_OM6802:
1489 setcontrast(gspca_dev);
1490 break;
1491 default: /* OV76xx */
1492 setbrightcont(gspca_dev);
1493 break;
1494 }
1495 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001496 return 0;
1497}
1498
1499static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1500{
1501 struct sd *sd = (struct sd *) gspca_dev;
1502
1503 *val = sd->contrast;
1504 return 0;
1505}
1506
1507static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1508{
1509 struct sd *sd = (struct sd *) gspca_dev;
1510
1511 sd->colors = val;
1512 if (gspca_dev->streaming)
1513 setcolors(gspca_dev);
1514 return 0;
1515}
1516
1517static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1518{
1519 struct sd *sd = (struct sd *) gspca_dev;
1520
1521 *val = sd->colors;
1522 return 0;
1523}
1524
1525static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528
1529 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001530 if (gspca_dev->streaming)
1531 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001532 return 0;
1533}
1534
1535static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1536{
1537 struct sd *sd = (struct sd *) gspca_dev;
1538
1539 *val = sd->autogain;
1540 return 0;
1541}
1542
1543/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001544static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001545 .name = MODULE_NAME,
1546 .ctrls = sd_ctrls,
1547 .nctrls = ARRAY_SIZE(sd_ctrls),
1548 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001549 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001550 .start = sd_start,
1551 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001552 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001553 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001554};
1555
1556/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001557#define BSI(bridge, sensor, i2c_addr) \
1558 .driver_info = (BRIDGE_ ## bridge << 16) \
1559 | (SENSOR_ ## sensor << 8) \
1560 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001561static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001562#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001563 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1564 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1565 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1566 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1567 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001568#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001569 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1570 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1571/* bw600.inf:
1572 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1573/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1574/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1575 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1576/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1577 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1578/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1579/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1580 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1581/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1582/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1583 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1584 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1585/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1586/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1587/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1588/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001589 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1590/*bw600.inf:*/
1591 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001592 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001593 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001594/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001595#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001596 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1597 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1598/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1599 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1600 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1601/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001602#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001603 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001604 {}
1605};
1606MODULE_DEVICE_TABLE(usb, device_table);
1607
1608/* -- device connect -- */
1609static int sd_probe(struct usb_interface *intf,
1610 const struct usb_device_id *id)
1611{
1612 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1613 THIS_MODULE);
1614}
1615
1616static struct usb_driver sd_driver = {
1617 .name = MODULE_NAME,
1618 .id_table = device_table,
1619 .probe = sd_probe,
1620 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001621#ifdef CONFIG_PM
1622 .suspend = gspca_suspend,
1623 .resume = gspca_resume,
1624#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001625};
1626
1627/* -- module insert / remove -- */
1628static int __init sd_mod_init(void)
1629{
1630 if (usb_register(&sd_driver) < 0)
1631 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001632 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001633 return 0;
1634}
1635static void __exit sd_mod_exit(void)
1636{
1637 usb_deregister(&sd_driver);
1638 info("deregistered");
1639}
1640
1641module_init(sd_mod_init);
1642module_exit(sd_mod_exit);