blob: 6673a3edf1908b79a18f08a7ea5a806813458f09 [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,
111 .maximum = 255,
112 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300113#define COLOR_DEF 127
114 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 },
116 .set = sd_setcolors,
117 .get = sd_getcolors,
118 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119 {
120 {
121 .id = V4L2_CID_AUTOGAIN,
122 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 .name = "Auto Gain",
124 .minimum = 0,
125 .maximum = 1,
126 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300127#define AUTOGAIN_DEF 1
128 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300129 },
130 .set = sd_setautogain,
131 .get = sd_getautogain,
132 },
133};
134
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300135static struct v4l2_pix_format vga_mode[] = {
136 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .bytesperline = 160,
138 .sizeimage = 160 * 120 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
140 .priv = 2},
141 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
142 .bytesperline = 320,
143 .sizeimage = 320 * 240 * 3 / 8 + 590,
144 .colorspace = V4L2_COLORSPACE_JPEG,
145 .priv = 1},
146 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
147 .bytesperline = 640,
148 .sizeimage = 640 * 480 * 3 / 8 + 590,
149 .colorspace = V4L2_COLORSPACE_JPEG,
150 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151};
152
153/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300154static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300155/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
156 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
157/* reg8 reg9 rega regb regc regd rege regf */
158 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
159/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
160 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
161/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
162 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300163};
164
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300165static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300166/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
167 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
168/* reg8 reg9 rega regb regc regd rege regf */
169 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
170/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
171 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
172/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
173 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300174};
175
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300176static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300177/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
178 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
179/* reg8 reg9 rega regb regc regd rege regf */
180 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
182 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
183/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
184 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300185};
186
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300187static const __u8 sn_om6802[] = {
188/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
189 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
190/* reg8 reg9 rega regb regc regd rege regf */
191 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
193 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
194/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
195 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
197 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
198 0xf7
199};
200
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300201static const __u8 sn_ov7630[] = {
202/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
203 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
204/* reg8 reg9 rega regb regc regd rege regf */
205 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
206/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
207 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
208/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
209 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
210};
211
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300212static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300213/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
214 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
215/* reg8 reg9 rega regb regc regd rege regf */
216 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
217/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
218 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
219/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
220 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300221};
222
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300223static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300224/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
225 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
226/* reg8 reg9 rega regb regc regd rege regf */
227 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
228/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
229 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
230/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
231 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300232};
233
234/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300235static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 sn_hv7131,
237 sn_mi0360,
238 sn_mo4000,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300239 sn_om6802,
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300240 sn_ov7630,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300241 sn_ov7648,
242 sn_ov7660
243};
244
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300245static const __u8 gamma_def[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300246 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
247 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
248};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300249
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300250static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
252 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300253 0xf7, 0x0f, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300255static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300256 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
257 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
258 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
259 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
262 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
263
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
266 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
267 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
268 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
269 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
270 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
271 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
272
273 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
278
279 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300284 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300285};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300286static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300287 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
291 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
292 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
293 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
308 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
309 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
310 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
312 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
314 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
315 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
316 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
318 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
319 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
320
321 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
323 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
324 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
325 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
326
327 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
328 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
330 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
331
332 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
333 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
334/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
335/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
336 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
337 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300338 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300339};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300340static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300341 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
360 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300361 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362};
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300363static __u8 om6802_sensor_init[][8] = {
364 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
365 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
366 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
367 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
368/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
369 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
370 /* white balance & auto-exposure */
371/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
372 * set color mode */
373/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
374 * max AGC value in AE */
375/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
376 * preset AGC */
377/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
378 * preset brightness */
379/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
380 * preset contrast */
381/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
382 * preset gamma */
383 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
384 /* luminance mode (0x4f = AE) */
385 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
386 /* preset shutter */
387/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
388 * auto frame rate */
389/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
390
391/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
392/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
393/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
394/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
395 {}
396};
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300397static const __u8 ov7630_sensor_init[][8] = {
398 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
399 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
400/* win: delay 20ms */
401 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
402 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
403/* win: delay 20ms */
404 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300405/* win: i2c_r from 00 to 80 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300406 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
407 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
408 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
409 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
410 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
411 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
412 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
413 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
414 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
415 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
416 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
417 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
418 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
421 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
422 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
423 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
424 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
425 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
426 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
427 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
428 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
429 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
430 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
431 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
432/* */
433 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
435/*fixme: + 0x12, 0x04*/
436 {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
437 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
438 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
439 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300440/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300441 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300444/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300445 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
446 {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10},
447 {}
448};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300449static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300451/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300453 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300454 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300455 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456 /* GAIN BLUE RED VREF */
457 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
458 /* COM 1 BAVE GEAVE AECHH */
459 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
460 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300461 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300462 /* AECH CLKRC COM7 COM8 */
463 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
464 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
465 /* HSTART HSTOP VSTRT VSTOP */
466 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
467 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
468 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
469 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300470/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
471 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472 /* AEW AEB VPT BBIAS */
473 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
474 /* GbBIAS RSVD EXHCH EXHCL */
475 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
476 /* RBIAS ADVFL ASDVFH YAVE */
477 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
478 /* HSYST HSYEN HREF */
479 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
480 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
481 /* ADC ACOM OFON TSLB */
482 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
483 /* COM11 COM12 COM13 COM14 */
484 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
485 /* EDGE COM15 COM16 COM17 */
486 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
487 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
488 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
489 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
490 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
491 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
492 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
493 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
494 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
495 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
496 /* LCC1 LCC2 LCC3 LCC4 */
497 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300498 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300500 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300501 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
502 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
503 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
504 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
505 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
506 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
507 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
508 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
509 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300510 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300512 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513 /* bits[3..0]reserved */
514 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
515 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
516 /* VREF vertical frame ctrl */
517 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300518 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
519 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
520 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
521 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
522/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300523/****** (some exchanges in the win trace) ******/
524 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300525 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
526 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
527 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
528/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300530/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300531 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
532 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
533 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
534 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300535 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300537/* reg 0x04 reg 0x07 reg 0x10 */
538/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300540static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
542 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
543 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
544 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
545 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
546 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
547 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
548 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
549 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
550 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
551 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
552 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
553 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
554 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
555 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
556 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
557 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
558 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
559 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
560 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
561 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
562 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
563 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
564 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
565 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
566 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
567 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
568 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
569 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
570 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
571 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
572 * This is currently setting a
573 * blue tint, and some things more , i leave it here for future test if
574 * somene is having problems with color on this sensor
575 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
576 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
577 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
578 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
579 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
580 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
581 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
582 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
583 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
584 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
585 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
586 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
587 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
588 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
589 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
590 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
591 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
592/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300593 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594};
595
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300596static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
598 0x06, 0x08, 0x0A, 0x11,
599 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
600 0x19, 0x19, 0x17, 0x15,
601 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
602 0x21, 0x2E, 0x21, 0x23,
603 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
604 0x25, 0x29, 0x2C, 0x29,
605 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
606 0x17, 0x1B, 0x29, 0x29,
607 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
608 0x29, 0x29, 0x29, 0x29,
609 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
610 0x29, 0x29, 0x29, 0x29,
611 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
612 0x29, 0x29, 0x29, 0x29
613};
614
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
616static void reg_r(struct gspca_dev *gspca_dev,
617 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619 usb_control_msg(gspca_dev->dev,
620 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 0,
622 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
623 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300624 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300626 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627}
628
Jean-Francois Moine60017612008-07-18 08:46:19 -0300629static void reg_w1(struct gspca_dev *gspca_dev,
630 __u16 value,
631 __u8 data)
632{
633 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
634 gspca_dev->usb_buf[0] = data;
635 usb_control_msg(gspca_dev->dev,
636 usb_sndctrlpipe(gspca_dev->dev, 0),
637 0x08,
638 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
639 value,
640 0,
641 gspca_dev->usb_buf, 1,
642 500);
643}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300644static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300646 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647 int len)
648{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300649 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
650 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651 if (len <= sizeof gspca_dev->usb_buf) {
652 memcpy(gspca_dev->usb_buf, buffer, len);
653 usb_control_msg(gspca_dev->dev,
654 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300655 0x08,
656 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
657 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300658 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300659 500);
660 } else {
661 __u8 *tmpbuf;
662
663 tmpbuf = kmalloc(len, GFP_KERNEL);
664 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300665 usb_control_msg(gspca_dev->dev,
666 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300667 0x08,
668 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
669 value, 0,
670 tmpbuf, len,
671 500);
672 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300673 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300674}
675
Jean-Francois Moine60017612008-07-18 08:46:19 -0300676/* I2C write 1 byte */
677static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678{
679 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680
Jean-Francois Moine60017612008-07-18 08:46:19 -0300681 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
682 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
683 gspca_dev->usb_buf[1] = sd->i2c_base;
684 gspca_dev->usb_buf[2] = reg;
685 gspca_dev->usb_buf[3] = val;
686 gspca_dev->usb_buf[4] = 0;
687 gspca_dev->usb_buf[5] = 0;
688 gspca_dev->usb_buf[6] = 0;
689 gspca_dev->usb_buf[7] = 0x10;
690 usb_control_msg(gspca_dev->dev,
691 usb_sndctrlpipe(gspca_dev->dev, 0),
692 0x08,
693 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
694 0x08, /* value = i2c */
695 0,
696 gspca_dev->usb_buf, 8,
697 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698}
699
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700/* I2C write 8 bytes */
701static void i2c_w8(struct gspca_dev *gspca_dev,
702 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300704 memcpy(gspca_dev->usb_buf, buffer, 8);
705 usb_control_msg(gspca_dev->dev,
706 usb_sndctrlpipe(gspca_dev->dev, 0),
707 0x08,
708 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
709 0x08, 0, /* value, index */
710 gspca_dev->usb_buf, 8,
711 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712}
713
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714/* read 5 bytes in gspca_dev->usb_buf */
715static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716{
717 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718 __u8 mode[8];
719
Hans de Goede3647fea2008-07-15 05:36:30 -0300720 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300721 mode[1] = sd->i2c_base;
722 mode[2] = reg;
723 mode[3] = 0;
724 mode[4] = 0;
725 mode[5] = 0;
726 mode[6] = 0;
727 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300728 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300729 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300730 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300732 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300733 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300734 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300735}
736
737static int probesensor(struct gspca_dev *gspca_dev)
738{
739 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740
Jean-Francois Moine60017612008-07-18 08:46:19 -0300741 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300743 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300745 i2c_r5(gspca_dev, 0); /* read sensor id */
746 if (gspca_dev->usb_buf[0] == 0x02
747 && gspca_dev->usb_buf[1] == 0x09
748 && gspca_dev->usb_buf[2] == 0x01
749 && gspca_dev->usb_buf[3] == 0x00
750 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
752 sd->sensor = SENSOR_HV7131R;
753 return SENSOR_HV7131R;
754 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300755 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300756 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
757 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
759 return -ENODEV;
760}
761
762static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300763 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764{
765 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300766 const __u8 *reg9a;
767 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300768 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300769 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300770 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300771 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772
Jean-Francois Moine60017612008-07-18 08:46:19 -0300773 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300774 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775
776 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
778 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300779 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300780 switch (sd->bridge) {
781 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 reg9a = reg9a_sn9c325;
783 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 default:
785 reg9a = reg9a_def;
786 break;
787 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300788 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300790 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300792 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300793
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300794 switch (sd->sensor) {
795 case SENSOR_OM6802:
Jean-Francois Moined55b83d2008-09-03 16:48:01 -0300796 reg_w1(gspca_dev, 0x02, 0x73); /* was 71 */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300797 reg_w1(gspca_dev, 0x01, 0x42);
798 reg_w1(gspca_dev, 0x17, 0x64);
799 reg_w1(gspca_dev, 0x01, 0x42);
800 break;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300801/*jfm: from win trace */
802 case SENSOR_OV7630:
803 reg_w1(gspca_dev, 0x01, 0x61);
804 reg_w1(gspca_dev, 0x17, 0xe2);
805 reg_w1(gspca_dev, 0x01, 0x60);
806 reg_w1(gspca_dev, 0x01, 0x40);
807 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300808 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300809 reg_w1(gspca_dev, 0x01, 0x43);
810 reg_w1(gspca_dev, 0x17, 0xae);
811 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812 break;
813 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300814 reg_w1(gspca_dev, 0x01, 0x43);
815 reg_w1(gspca_dev, 0x17, 0x61);
816 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300817 if (sd->sensor == SENSOR_HV7131R) {
818 if (probesensor(gspca_dev) < 0)
819 return -ENODEV;
820 }
821 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822 }
823 return 0;
824}
825
826static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
827{
828 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300829 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300830 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
831
832 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300833 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834 i++;
835 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300836 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837}
838
839static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
840{
841 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842
843 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 i++;
846 }
847}
848
849static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
850{
851 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852
853 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300854 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 i++;
856 }
857}
858
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300859static void om6802_InitSensor(struct gspca_dev *gspca_dev)
860{
861 int i = 0;
862
863 while (om6802_sensor_init[i][0]) {
864 i2c_w8(gspca_dev, om6802_sensor_init[i]);
865 i++;
866 }
867}
868
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300869static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
870{
871 int i = 0;
872
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300873 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
874 i++;
875 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300876 i++;
877 msleep(20);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300878 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
879 i++;
880 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
881 i++;
882 msleep(20);
883 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
884 i++;
885/*jfm:win i2c_r from 00 to 80*/
886
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300887 while (ov7630_sensor_init[i][0]) {
888 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
889 i++;
890 }
891}
892
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
894{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300895 int i = 0;
896
897 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300898 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 i++;
900 }
901}
902
903static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
904{
905 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906
Jean-Francois Moine60017612008-07-18 08:46:19 -0300907 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
908 i++;
909 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300911 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 i++;
913 }
914}
915
916/* this function is called at probe time */
917static int sd_config(struct gspca_dev *gspca_dev,
918 const struct usb_device_id *id)
919{
920 struct sd *sd = (struct sd *) gspca_dev;
921 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922
923 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924 cam->epaddr = 0x01;
925 cam->cam_mode = vga_mode;
926 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300927
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300928 sd->bridge = id->driver_info >> 16;
929 sd->sensor = id->driver_info >> 8;
930 sd->i2c_base = id->driver_info;
931
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300933 sd->brightness = BRIGHTNESS_DEF;
934 sd->contrast = CONTRAST_DEF;
935 sd->colors = COLOR_DEF;
936 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300937 sd->ag_cnt = -1;
938
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939 return 0;
940}
941
942/* this function is called at open time */
943static int sd_open(struct gspca_dev *gspca_dev)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300946/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300947 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300948 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300949
Hans de Goede3647fea2008-07-15 05:36:30 -0300950 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300951 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300952 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300953 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
954 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300955 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300956 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300957 switch (sd->bridge) {
958 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959 if (regF1 != 0x11)
960 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300961 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300963 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964 if (regF1 != 0x11)
965 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300966 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300967 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300968 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 if (regF1 != 0x12)
970 return -ENODEV;
971 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300972 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 break;
974 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300975/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300976/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977 if (regF1 != 0x12)
978 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300979 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300980 break;
981 }
982
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -0300983 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984
985 return 0;
986}
987
988static unsigned int setexposure(struct gspca_dev *gspca_dev,
989 unsigned int expo)
990{
991 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300992 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300994 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300996 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
998
999 switch (sd->sensor) {
1000 case SENSOR_HV7131R: {
1001 __u8 Expodoit[] =
1002 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1003
1004 Expodoit[3] = expo >> 16;
1005 Expodoit[4] = expo >> 8;
1006 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001007 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001008 break;
1009 }
1010 case SENSOR_MI0360: {
1011 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1012 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1013
1014 if (expo > 0x0635)
1015 expo = 0x0635;
1016 else if (expo < 0x0001)
1017 expo = 0x0001;
1018 expoMi[3] = expo >> 8;
1019 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001020 i2c_w8(gspca_dev, expoMi);
1021 i2c_w8(gspca_dev, doit);
1022 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 break;
1024 }
1025 case SENSOR_MO4000: {
1026 __u8 expoMof[] =
1027 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1028 __u8 expoMo10[] =
1029 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1030
1031 if (expo > 0x1fff)
1032 expo = 0x1fff;
1033 else if (expo < 0x0001)
1034 expo = 0x0001;
1035 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001036 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001037 expoMo10[3] = ((expo & 0x1c00) >> 10)
1038 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001039 i2c_w8(gspca_dev, expoMo10);
1040 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001041 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001042 ((expoMo10[3] & 0x07) << 10)
1043 | (expoMof[3] << 2)
1044 | ((expoMo10[3] & 0x30) >> 4));
1045 break;
1046 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001047 case SENSOR_OM6802: {
1048 __u8 gainOm[] =
1049 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1050
1051 if (expo > 0x03ff)
1052 expo = 0x03ff;
1053 if (expo < 0x0001)
1054 expo = 0x0001;
1055 gainOm[3] = expo >> 2;
1056 i2c_w8(gspca_dev, gainOm);
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001057 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001058 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1059 break;
1060 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001061 }
1062 return expo;
1063}
1064
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001065/* this function is used for sensors o76xx only */
1066static void setbrightcont(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069 unsigned val;
1070 __u8 reg84_full[13];
1071
1072 memset(reg84_full, 0, sizeof reg84_full);
1073 val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
1074 reg84_full[2] = val;
1075 reg84_full[0] = (val + 1) / 2;
1076 reg84_full[4] = (val + 1) / 5;
1077 if (val > BRIGHTNESS_DEF)
1078 val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
1079 / BRIGHTNESS_MAX;
1080 else
1081 val = 0;
1082 reg84_full[10] = val; /* 00..1f */
1083 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1084}
1085
1086/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001087static void setbrightness(struct gspca_dev *gspca_dev)
1088{
1089 struct sd *sd = (struct sd *) gspca_dev;
1090 unsigned int expo;
1091 __u8 k2;
1092
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001093 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001094 switch (sd->sensor) {
1095 case SENSOR_HV7131R:
1096 expo = sd->brightness << 4;
1097 if (expo > 0x002dc6c0)
1098 expo = 0x002dc6c0;
1099 else if (expo < 0x02a0)
1100 expo = 0x02a0;
1101 sd->exposure = setexposure(gspca_dev, expo);
1102 break;
1103 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001104 case SENSOR_MO4000:
1105 expo = sd->brightness >> 4;
1106 sd->exposure = setexposure(gspca_dev, expo);
1107 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001108 case SENSOR_OM6802:
1109 expo = sd->brightness >> 6;
1110 sd->exposure = setexposure(gspca_dev, expo);
1111 k2 = sd->brightness >> 11;
1112 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001113 }
1114
Jean-Francois Moine60017612008-07-18 08:46:19 -03001115 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001116}
1117
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001118/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119static void setcontrast(struct gspca_dev *gspca_dev)
1120{
1121 struct sd *sd = (struct sd *) gspca_dev;
1122 __u8 k2;
1123 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1124
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001125 k2 = sd->contrast;
1126 contrast[2] = k2;
1127 contrast[0] = (k2 + 1) >> 1;
1128 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001129 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001130}
1131
1132static void setcolors(struct gspca_dev *gspca_dev)
1133{
1134 struct sd *sd = (struct sd *) gspca_dev;
1135 __u8 data;
1136 int colour;
1137
1138 colour = sd->colors - 128;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001139 if (colour > 0) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140 data = (colour + 32) & 0x7f; /* blue */
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001141 reg_w1(gspca_dev, 0x06, data);
1142 } else {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001144 reg_w1(gspca_dev, 0x05, data);
1145 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001146}
1147
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001148static void setautogain(struct gspca_dev *gspca_dev)
1149{
1150 struct sd *sd = (struct sd *) gspca_dev;
1151
1152 switch (sd->sensor) {
1153 case SENSOR_HV7131R:
1154 case SENSOR_MO4000:
1155 case SENSOR_MI0360:
1156 if (sd->autogain)
1157 sd->ag_cnt = AG_CNT_START;
1158 else
1159 sd->ag_cnt = -1;
1160 break;
1161 }
1162}
1163
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001164/* -- start the camera -- */
1165static void sd_start(struct gspca_dev *gspca_dev)
1166{
1167 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001168 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001169 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001170 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001171 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001172 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1173 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001174 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001175 static const __u8 CE_ov76xx[] =
1176 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001177
1178 sn9c1xx = sn_tb[(int) sd->sensor];
1179 configure_gpio(gspca_dev, sn9c1xx);
1180
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001181/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
Jean-Francois Moine60017612008-07-18 08:46:19 -03001182 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1183 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1184 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1185 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1186 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1187 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1188 reg_w1(gspca_dev, 0xd3, 0x50);
1189 reg_w1(gspca_dev, 0xc6, 0x00);
1190 reg_w1(gspca_dev, 0xc7, 0x00);
1191 reg_w1(gspca_dev, 0xc8, 0x50);
1192 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001193 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001194 switch (sd->sensor) {
1195 case SENSOR_OV7630:
1196 reg17 = 0xe2;
1197 break;
1198 case SENSOR_OV7648:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001199 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001200 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001201/*jfm: from win trace */
1202 case SENSOR_OV7660:
1203 reg17 = 0xa0;
1204 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001205 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001206 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001207 break;
1208 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001209 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001210 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1211 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1212 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1213 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001214 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1215 for (i = 0; i < 8; i++)
1216 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001217 reg_w1(gspca_dev, 0x9a, 0x08);
1218 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001220 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001221 if (mode)
1222 reg1 = 0x46; /* 320 clk 48Mhz */
1223 else
1224 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225 reg17 = 0x61;
1226 switch (sd->sensor) {
1227 case SENSOR_HV7131R:
1228 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229 break;
1230 case SENSOR_MI0360:
1231 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001232 break;
1233 case SENSOR_MO4000:
1234 mo4000_InitSensor(gspca_dev);
1235 if (mode) {
1236/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1237 reg1 = 0x06; /* clk 24Mz */
1238 } else {
1239 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001240/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001241 }
1242 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001243 case SENSOR_OM6802:
1244 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001245 reg17 = 0x64; /* 640 MCKSIZE */
1246 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001247 case SENSOR_OV7630:
1248 ov7630_InitSensor(gspca_dev);
1249 reg17 = 0xe2;
1250 reg1 = 0x40;
1251 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001252 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001253 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001254 reg17 = 0xa2;
1255 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001256/* if (mode)
1257 ; * 320x2...
1258 else
1259 ; * 640x... */
1260 break;
1261 default:
1262/* case SENSOR_OV7660: */
1263 ov7660_InitSensor(gspca_dev);
1264 if (mode) {
1265/* reg17 = 0x21; * 320 */
1266/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001267/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001268 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001269 reg17 = 0x22; /* 640 MCKSIZE */
1270 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001271 }
1272 break;
1273 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001274 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001275 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001276 switch (sd->sensor) {
1277 case SENSOR_OV7630:
1278 case SENSOR_OV7648:
1279 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001280 break;
1281 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001282 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001283 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1284 break;
1285 }
1286
1287 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001288 reg18 = sn9c1xx[0x18] | (mode << 4);
1289 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001290
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1292 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001293
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001294 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001295
Jean-Francois Moine60017612008-07-18 08:46:19 -03001296 reg_w1(gspca_dev, 0x17, reg17);
1297 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001298 switch (sd->sensor) {
1299 case SENSOR_HV7131R:
1300 case SENSOR_MI0360:
1301 case SENSOR_MO4000:
1302 case SENSOR_OM6802:
1303 setbrightness(gspca_dev);
1304 setcontrast(gspca_dev);
1305 break;
1306 default: /* OV76xx */
1307 setbrightcont(gspca_dev);
1308 break;
1309 }
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001310 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001311}
1312
1313static void sd_stopN(struct gspca_dev *gspca_dev)
1314{
1315 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001316 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001317 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001318 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001319 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001320 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001321 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001322
1323 data = 0x0b;
1324 switch (sd->sensor) {
1325 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001326 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001327 data = 0x2b;
1328 break;
1329 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001330 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001331 data = 0x29;
1332 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001333 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001334 case SENSOR_OV7648:
1335 data = 0x29;
1336 break;
1337 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001338/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001339/* case SENSOR_OV7660: */
1340 break;
1341 }
1342 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001343 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1344 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1345 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1346 reg_w1(gspca_dev, 0x01, data);
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001347 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001348}
1349
1350static void sd_stop0(struct gspca_dev *gspca_dev)
1351{
1352}
1353
1354static void sd_close(struct gspca_dev *gspca_dev)
1355{
1356}
1357
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001358static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001359{
1360 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001361 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001362 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001363 __u8 luma_mean = 130;
1364 __u8 luma_delta = 20;
1365
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001366 /* Thanks S., without your advice, autobright should not work :) */
1367 if (sd->ag_cnt < 0)
1368 return;
1369 if (--sd->ag_cnt >= 0)
1370 return;
1371 sd->ag_cnt = AG_CNT_START;
1372
1373 delta = atomic_read(&sd->avg_lum);
1374 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001375 if (delta < luma_mean - luma_delta ||
1376 delta > luma_mean + luma_delta) {
1377 switch (sd->sensor) {
1378 case SENSOR_HV7131R:
1379 expotimes = sd->exposure >> 8;
1380 expotimes += (luma_mean - delta) >> 4;
1381 if (expotimes < 0)
1382 expotimes = 0;
1383 sd->exposure = setexposure(gspca_dev,
1384 (unsigned int) (expotimes << 8));
1385 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001386 default:
1387/* case SENSOR_MO4000: */
1388/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001389/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001390 expotimes = sd->exposure;
1391 expotimes += (luma_mean - delta) >> 6;
1392 if (expotimes < 0)
1393 expotimes = 0;
1394 sd->exposure = setexposure(gspca_dev,
1395 (unsigned int) expotimes);
1396 setcolors(gspca_dev);
1397 break;
1398 }
1399 }
1400}
1401
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001402/* scan the URB packets */
1403/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001404static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1405 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001406 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001407 int len) /* iso packet length */
1408{
1409 struct sd *sd = (struct sd *) gspca_dev;
1410 int sof, avg_lum;
1411
1412 sof = len - 64;
1413 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1414
1415 /* end of frame */
1416 gspca_frame_add(gspca_dev, LAST_PACKET,
1417 frame, data, sof + 2);
1418 if (sd->ag_cnt < 0)
1419 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001420/* w1 w2 w3 */
1421/* w4 w5 w6 */
1422/* w7 w8 */
1423/* w4 */
1424 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1425/* w6 */
1426 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1427/* w2 */
1428 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1429/* w8 */
1430 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1431/* w5 */
1432 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1433 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001434 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001435 return;
1436 }
1437 if (gspca_dev->last_packet_type == LAST_PACKET) {
1438
1439 /* put the JPEG 422 header */
1440 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1441 }
1442 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1443}
1444
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001445static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1446{
1447 struct sd *sd = (struct sd *) gspca_dev;
1448
1449 sd->brightness = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001450 if (gspca_dev->streaming) {
1451 switch (sd->sensor) {
1452 case SENSOR_HV7131R:
1453 case SENSOR_MI0360:
1454 case SENSOR_MO4000:
1455 case SENSOR_OM6802:
1456 setbrightness(gspca_dev);
1457 break;
1458 default: /* OV76xx */
1459 setbrightcont(gspca_dev);
1460 break;
1461 }
1462 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001463 return 0;
1464}
1465
1466static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001470 *val = sd->brightness;
1471 return 0;
1472}
1473
1474static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1475{
1476 struct sd *sd = (struct sd *) gspca_dev;
1477
1478 sd->contrast = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001479 if (gspca_dev->streaming) {
1480 switch (sd->sensor) {
1481 case SENSOR_HV7131R:
1482 case SENSOR_MI0360:
1483 case SENSOR_MO4000:
1484 case SENSOR_OM6802:
1485 setcontrast(gspca_dev);
1486 break;
1487 default: /* OV76xx */
1488 setbrightcont(gspca_dev);
1489 break;
1490 }
1491 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001492 return 0;
1493}
1494
1495static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1496{
1497 struct sd *sd = (struct sd *) gspca_dev;
1498
1499 *val = sd->contrast;
1500 return 0;
1501}
1502
1503static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1504{
1505 struct sd *sd = (struct sd *) gspca_dev;
1506
1507 sd->colors = val;
1508 if (gspca_dev->streaming)
1509 setcolors(gspca_dev);
1510 return 0;
1511}
1512
1513static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1514{
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 *val = sd->colors;
1518 return 0;
1519}
1520
1521static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1522{
1523 struct sd *sd = (struct sd *) gspca_dev;
1524
1525 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001526 if (gspca_dev->streaming)
1527 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001528 return 0;
1529}
1530
1531static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1532{
1533 struct sd *sd = (struct sd *) gspca_dev;
1534
1535 *val = sd->autogain;
1536 return 0;
1537}
1538
1539/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001540static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001541 .name = MODULE_NAME,
1542 .ctrls = sd_ctrls,
1543 .nctrls = ARRAY_SIZE(sd_ctrls),
1544 .config = sd_config,
1545 .open = sd_open,
1546 .start = sd_start,
1547 .stopN = sd_stopN,
1548 .stop0 = sd_stop0,
1549 .close = sd_close,
1550 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001551 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001552};
1553
1554/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001555#define BSI(bridge, sensor, i2c_addr) \
1556 .driver_info = (BRIDGE_ ## bridge << 16) \
1557 | (SENSOR_ ## sensor << 8) \
1558 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001559static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001560#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001561 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1562 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1563 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1564 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1565 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001566#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001567 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1568 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1569/* bw600.inf:
1570 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1571/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1572/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1573 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1574/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1575 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1576/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1577/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1578 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1579/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1580/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1581 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1582 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1583/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1584/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1585/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1586/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001587 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1588/*bw600.inf:*/
1589 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001590 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001591 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001592/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001593#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001594 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1595 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1596/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1597 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1598 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1599/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001600#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001601 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001602 {}
1603};
1604MODULE_DEVICE_TABLE(usb, device_table);
1605
1606/* -- device connect -- */
1607static int sd_probe(struct usb_interface *intf,
1608 const struct usb_device_id *id)
1609{
1610 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1611 THIS_MODULE);
1612}
1613
1614static struct usb_driver sd_driver = {
1615 .name = MODULE_NAME,
1616 .id_table = device_table,
1617 .probe = sd_probe,
1618 .disconnect = gspca_disconnect,
1619};
1620
1621/* -- module insert / remove -- */
1622static int __init sd_mod_init(void)
1623{
1624 if (usb_register(&sd_driver) < 0)
1625 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001626 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001627 return 0;
1628}
1629static void __exit sd_mod_exit(void)
1630{
1631 usb_deregister(&sd_driver);
1632 info("deregistered");
1633}
1634
1635module_init(sd_mod_init);
1636module_exit(sd_mod_exit);