blob: 47737bf04c6a9bf7ec22c9880f3bbe9cfe16c783 [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,
81 .maximum = 0xffff,
82 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030083#define BRIGHTNESS_DEF 0x7fff
84 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030085 },
86 .set = sd_setbrightness,
87 .get = sd_getbrightness,
88 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 {
90 {
91 .id = V4L2_CID_CONTRAST,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Contrast",
94 .minimum = 0,
95 .maximum = 127,
96 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030097#define CONTRAST_DEF 63
98 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030099 },
100 .set = sd_setcontrast,
101 .get = sd_getcontrast,
102 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300103 {
104 {
105 .id = V4L2_CID_SATURATION,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Color",
108 .minimum = 0,
109 .maximum = 255,
110 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300111#define COLOR_DEF 127
112 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300113 },
114 .set = sd_setcolors,
115 .get = sd_getcolors,
116 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117 {
118 {
119 .id = V4L2_CID_AUTOGAIN,
120 .type = V4L2_CTRL_TYPE_BOOLEAN,
121 .name = "Auto Gain",
122 .minimum = 0,
123 .maximum = 1,
124 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300125#define AUTOGAIN_DEF 1
126 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127 },
128 .set = sd_setautogain,
129 .get = sd_getautogain,
130 },
131};
132
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300133static struct v4l2_pix_format vga_mode[] = {
134 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
135 .bytesperline = 160,
136 .sizeimage = 160 * 120 * 3 / 8 + 590,
137 .colorspace = V4L2_COLORSPACE_JPEG,
138 .priv = 2},
139 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
140 .bytesperline = 320,
141 .sizeimage = 320 * 240 * 3 / 8 + 590,
142 .colorspace = V4L2_COLORSPACE_JPEG,
143 .priv = 1},
144 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
145 .bytesperline = 640,
146 .sizeimage = 640 * 480 * 3 / 8 + 590,
147 .colorspace = V4L2_COLORSPACE_JPEG,
148 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300149};
150
151/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300152static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300153/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
154 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
155/* reg8 reg9 rega regb regc regd rege regf */
156 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
157/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
158 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
159/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
160 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300161};
162
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300163static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300164/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
165 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
166/* reg8 reg9 rega regb regc regd rege regf */
167 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
168/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
169 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
170/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
171 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172};
173
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300174static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300175/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
176 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
177/* reg8 reg9 rega regb regc regd rege regf */
178 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
180 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
181/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
182 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183};
184
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300185static const __u8 sn_om6802[] = {
186/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
187 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
188/* reg8 reg9 rega regb regc regd rege regf */
189 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
191 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
192/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
193 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
195 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
196 0xf7
197};
198
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300199static const __u8 sn_ov7630[] = {
200/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
201 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
202/* reg8 reg9 rega regb regc regd rege regf */
203 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
204/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
205 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
206/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
207 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
208};
209
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300210static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300211/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
212 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
213/* reg8 reg9 rega regb regc regd rege regf */
214 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
215/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
216 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
217/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
218 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300219};
220
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300221static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300222/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
223 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
224/* reg8 reg9 rega regb regc regd rege regf */
225 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
226/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
227 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
228/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
229 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300230};
231
232/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300233static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300234 sn_hv7131,
235 sn_mi0360,
236 sn_mo4000,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300237 sn_om6802,
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300238 sn_ov7630,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300239 sn_ov7648,
240 sn_ov7660
241};
242
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300243static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300244 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
245 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
246};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300247static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300248 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
249 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
250};
251
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300252static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300253 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
254 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
255/* 0x00, 0x00, 0x00, 0x00, 0x00 */
256 0xf7, 0x0f, 0x0a, 0x00, 0x00
257};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300258static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300259 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
260 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
261 0xf8, 0x0f, 0x00, 0x00, 0x00
262};
263
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300264static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
266 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
267 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
268 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
269 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
270 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
271 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
272
273 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
275 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
276 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
277 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
278 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
279 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
280 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
281
282 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
283 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
285 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
287
288 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
289 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
290 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
291 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300293 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300294};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300295static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300296 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
297 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
298 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
300 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
301 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
302 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
308 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
315 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
318 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
319 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
321 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
322 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
323 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
324 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
325 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
327 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
328 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
329
330 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
331 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
332 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
333 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
334 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
335
336 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
337 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
338 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
339 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
340
341 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
342 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
343/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
344/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
345 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
346 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300347 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300349static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300350 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
360 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
361 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
362 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
363 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
364 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
365 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
366 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
367 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
368 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
369 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300370 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371};
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300372static __u8 om6802_sensor_init[][8] = {
373 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
374 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
375 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
376 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
377/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
378 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
379 /* white balance & auto-exposure */
380/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
381 * set color mode */
382/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
383 * max AGC value in AE */
384/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
385 * preset AGC */
386/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
387 * preset brightness */
388/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
389 * preset contrast */
390/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
391 * preset gamma */
392 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
393 /* luminance mode (0x4f = AE) */
394 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
395 /* preset shutter */
396/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
397 * auto frame rate */
398/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
399
400/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
401/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
402/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
403/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
404 {}
405};
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300406static const __u8 ov7630_sensor_init[][8] = {
407 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
408 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
409/* win: delay 20ms */
410 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
411 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
412/* win: delay 20ms */
413 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
414/* win: loop on 2 wwrite, 1 read */
415 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
416 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
417 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
418 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
419 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
420 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
421 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
422 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
423 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
424 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
425 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
426 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
429 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
430 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
431 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
432 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
433 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
434 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
435 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
436 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
437 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
438 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
439 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
440 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
441/* */
442 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
444/*fixme: + 0x12, 0x04*/
445 {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
448 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
450 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
451 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
452 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
453 {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10},
454 {}
455};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300456static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300458/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300459 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300460 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300462 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 /* GAIN BLUE RED VREF */
464 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
465 /* COM 1 BAVE GEAVE AECHH */
466 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
467 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300468 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469 /* AECH CLKRC COM7 COM8 */
470 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
471 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
472 /* HSTART HSTOP VSTRT VSTOP */
473 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
474 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
475 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
476 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300477/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
478 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300479 /* AEW AEB VPT BBIAS */
480 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
481 /* GbBIAS RSVD EXHCH EXHCL */
482 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
483 /* RBIAS ADVFL ASDVFH YAVE */
484 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
485 /* HSYST HSYEN HREF */
486 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
487 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
488 /* ADC ACOM OFON TSLB */
489 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
490 /* COM11 COM12 COM13 COM14 */
491 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
492 /* EDGE COM15 COM16 COM17 */
493 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
494 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
495 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
496 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
497 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
498 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
499 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
500 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
501 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
502 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
503 /* LCC1 LCC2 LCC3 LCC4 */
504 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300505 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300507 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
509 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
510 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
511 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
512 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
513 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
514 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
515 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
516 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300517 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300518/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300519 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520 /* bits[3..0]reserved */
521 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
522 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
523 /* VREF vertical frame ctrl */
524 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300525 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
526 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
527 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
528 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
529/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530/****** (some exchanges in the win trace) ******/
531 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300532 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
533 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
534 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
535/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300537/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
539 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
540 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
541 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300542 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300544/* reg 0x04 reg 0x07 reg 0x10 */
545/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300547static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
549 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
550 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
551 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
552 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
553 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
554 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
555 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
556 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
557 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
558 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
559 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
560 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
561 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
562 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
563 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
564 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
565 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
566 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
567 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
568 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
569 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
570 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
571 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
572 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
573 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
574 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
575 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
576 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
577 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
578 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
579 * This is currently setting a
580 * blue tint, and some things more , i leave it here for future test if
581 * somene is having problems with color on this sensor
582 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
583 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
584 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
585 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
586 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
587 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
588 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
589 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
590 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
591 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
592 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
593 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
594 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
595 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
596 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
597 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
598 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
599/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300600 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601};
602
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300603static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
605 0x06, 0x08, 0x0A, 0x11,
606 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
607 0x19, 0x19, 0x17, 0x15,
608 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
609 0x21, 0x2E, 0x21, 0x23,
610 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
611 0x25, 0x29, 0x2C, 0x29,
612 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
613 0x17, 0x1B, 0x29, 0x29,
614 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
615 0x29, 0x29, 0x29, 0x29,
616 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
617 0x29, 0x29, 0x29, 0x29,
618 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
619 0x29, 0x29, 0x29, 0x29
620};
621
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
623static void reg_r(struct gspca_dev *gspca_dev,
624 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 usb_control_msg(gspca_dev->dev,
627 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 0,
629 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
630 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300631 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300633 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634}
635
Jean-Francois Moine60017612008-07-18 08:46:19 -0300636static void reg_w1(struct gspca_dev *gspca_dev,
637 __u16 value,
638 __u8 data)
639{
640 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
641 gspca_dev->usb_buf[0] = data;
642 usb_control_msg(gspca_dev->dev,
643 usb_sndctrlpipe(gspca_dev->dev, 0),
644 0x08,
645 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
646 value,
647 0,
648 gspca_dev->usb_buf, 1,
649 500);
650}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300653 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 int len)
655{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300656 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
657 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300658 if (len <= sizeof gspca_dev->usb_buf) {
659 memcpy(gspca_dev->usb_buf, buffer, len);
660 usb_control_msg(gspca_dev->dev,
661 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300662 0x08,
663 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
664 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300665 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300666 500);
667 } else {
668 __u8 *tmpbuf;
669
670 tmpbuf = kmalloc(len, GFP_KERNEL);
671 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 usb_control_msg(gspca_dev->dev,
673 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300674 0x08,
675 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
676 value, 0,
677 tmpbuf, len,
678 500);
679 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300680 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681}
682
Jean-Francois Moine60017612008-07-18 08:46:19 -0300683/* I2C write 1 byte */
684static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685{
686 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687
Jean-Francois Moine60017612008-07-18 08:46:19 -0300688 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
689 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
690 gspca_dev->usb_buf[1] = sd->i2c_base;
691 gspca_dev->usb_buf[2] = reg;
692 gspca_dev->usb_buf[3] = val;
693 gspca_dev->usb_buf[4] = 0;
694 gspca_dev->usb_buf[5] = 0;
695 gspca_dev->usb_buf[6] = 0;
696 gspca_dev->usb_buf[7] = 0x10;
697 usb_control_msg(gspca_dev->dev,
698 usb_sndctrlpipe(gspca_dev->dev, 0),
699 0x08,
700 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
701 0x08, /* value = i2c */
702 0,
703 gspca_dev->usb_buf, 8,
704 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300705}
706
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300707/* I2C write 8 bytes */
708static void i2c_w8(struct gspca_dev *gspca_dev,
709 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300711 memcpy(gspca_dev->usb_buf, buffer, 8);
712 usb_control_msg(gspca_dev->dev,
713 usb_sndctrlpipe(gspca_dev->dev, 0),
714 0x08,
715 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
716 0x08, 0, /* value, index */
717 gspca_dev->usb_buf, 8,
718 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719}
720
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300721/* read 5 bytes in gspca_dev->usb_buf */
722static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723{
724 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725 __u8 mode[8];
726
Hans de Goede3647fea2008-07-15 05:36:30 -0300727 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728 mode[1] = sd->i2c_base;
729 mode[2] = reg;
730 mode[3] = 0;
731 mode[4] = 0;
732 mode[5] = 0;
733 mode[6] = 0;
734 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300735 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300736 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300737 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300740 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300741 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742}
743
744static int probesensor(struct gspca_dev *gspca_dev)
745{
746 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747
Jean-Francois Moine60017612008-07-18 08:46:19 -0300748 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300750 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300752 i2c_r5(gspca_dev, 0); /* read sensor id */
753 if (gspca_dev->usb_buf[0] == 0x02
754 && gspca_dev->usb_buf[1] == 0x09
755 && gspca_dev->usb_buf[2] == 0x01
756 && gspca_dev->usb_buf[3] == 0x00
757 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
759 sd->sensor = SENSOR_HV7131R;
760 return SENSOR_HV7131R;
761 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300762 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
764 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
766 return -ENODEV;
767}
768
769static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300770 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771{
772 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300773 const __u8 *reg9a;
774 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300776 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300777 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300778 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
Jean-Francois Moine60017612008-07-18 08:46:19 -0300780 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300781 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782
783 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300784 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
785 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300786 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300787 switch (sd->bridge) {
788 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789 reg9a = reg9a_sn9c325;
790 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 default:
792 reg9a = reg9a_def;
793 break;
794 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300795 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300796
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300797 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300799 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300801 switch (sd->sensor) {
802 case SENSOR_OM6802:
803 reg_w1(gspca_dev, 0x02, 0x71);
804 reg_w1(gspca_dev, 0x01, 0x42);
805 reg_w1(gspca_dev, 0x17, 0x64);
806 reg_w1(gspca_dev, 0x01, 0x42);
807 break;
808 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
873 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
874 i++;
875 msleep(20);
876 while (ov7630_sensor_init[i][0]) {
877 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
878 i++;
879 }
880}
881
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
883{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 int i = 0;
885
886 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300887 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 i++;
889 }
890}
891
892static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
893{
894 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300895
Jean-Francois Moine60017612008-07-18 08:46:19 -0300896 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
897 i++;
898 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300900 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901 i++;
902 }
903}
904
905/* this function is called at probe time */
906static int sd_config(struct gspca_dev *gspca_dev,
907 const struct usb_device_id *id)
908{
909 struct sd *sd = (struct sd *) gspca_dev;
910 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911
912 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913 cam->epaddr = 0x01;
914 cam->cam_mode = vga_mode;
915 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300916
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300917 sd->bridge = id->driver_info >> 16;
918 sd->sensor = id->driver_info >> 8;
919 sd->i2c_base = id->driver_info;
920
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300922 sd->brightness = BRIGHTNESS_DEF;
923 sd->contrast = CONTRAST_DEF;
924 sd->colors = COLOR_DEF;
925 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300926 sd->ag_cnt = -1;
927
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 return 0;
929}
930
931/* this function is called at open time */
932static int sd_open(struct gspca_dev *gspca_dev)
933{
934 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300935/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300937 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938
Hans de Goede3647fea2008-07-15 05:36:30 -0300939 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300940 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300941 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300942 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
943 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300944 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300945 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300946 switch (sd->bridge) {
947 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300948 if (regF1 != 0x11)
949 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300950 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300952 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 if (regF1 != 0x11)
954 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300955 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300957 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 if (regF1 != 0x12)
959 return -ENODEV;
960 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300961 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 break;
963 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300964/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300965/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 if (regF1 != 0x12)
967 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300968 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 break;
970 }
971
Jean-Francois Moine60017612008-07-18 08:46:19 -0300972 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973
974 return 0;
975}
976
977static unsigned int setexposure(struct gspca_dev *gspca_dev,
978 unsigned int expo)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300981 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300983 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
987
988 switch (sd->sensor) {
989 case SENSOR_HV7131R: {
990 __u8 Expodoit[] =
991 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
992
993 Expodoit[3] = expo >> 16;
994 Expodoit[4] = expo >> 8;
995 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300996 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997 break;
998 }
999 case SENSOR_MI0360: {
1000 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1001 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1002
1003 if (expo > 0x0635)
1004 expo = 0x0635;
1005 else if (expo < 0x0001)
1006 expo = 0x0001;
1007 expoMi[3] = expo >> 8;
1008 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001009 i2c_w8(gspca_dev, expoMi);
1010 i2c_w8(gspca_dev, doit);
1011 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001012 break;
1013 }
1014 case SENSOR_MO4000: {
1015 __u8 expoMof[] =
1016 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1017 __u8 expoMo10[] =
1018 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1019
1020 if (expo > 0x1fff)
1021 expo = 0x1fff;
1022 else if (expo < 0x0001)
1023 expo = 0x0001;
1024 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001025 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 expoMo10[3] = ((expo & 0x1c00) >> 10)
1027 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001028 i2c_w8(gspca_dev, expoMo10);
1029 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001030 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031 ((expoMo10[3] & 0x07) << 10)
1032 | (expoMof[3] << 2)
1033 | ((expoMo10[3] & 0x30) >> 4));
1034 break;
1035 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001036 case SENSOR_OM6802: {
1037 __u8 gainOm[] =
1038 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1039
1040 if (expo > 0x03ff)
1041 expo = 0x03ff;
1042 if (expo < 0x0001)
1043 expo = 0x0001;
1044 gainOm[3] = expo >> 2;
1045 i2c_w8(gspca_dev, gainOm);
1046 reg_w1(gspca_dev, 0x96, expo >> 5);
1047 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1048 break;
1049 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050 }
1051 return expo;
1052}
1053
1054static void setbrightness(struct gspca_dev *gspca_dev)
1055{
1056 struct sd *sd = (struct sd *) gspca_dev;
1057 unsigned int expo;
1058 __u8 k2;
1059
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001060 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001061 switch (sd->sensor) {
1062 case SENSOR_HV7131R:
1063 expo = sd->brightness << 4;
1064 if (expo > 0x002dc6c0)
1065 expo = 0x002dc6c0;
1066 else if (expo < 0x02a0)
1067 expo = 0x02a0;
1068 sd->exposure = setexposure(gspca_dev, expo);
1069 break;
1070 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071 case SENSOR_MO4000:
1072 expo = sd->brightness >> 4;
1073 sd->exposure = setexposure(gspca_dev, expo);
1074 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001075 case SENSOR_OM6802:
1076 expo = sd->brightness >> 6;
1077 sd->exposure = setexposure(gspca_dev, expo);
1078 k2 = sd->brightness >> 11;
1079 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001080 }
1081
Jean-Francois Moine60017612008-07-18 08:46:19 -03001082 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001083}
1084
1085static void setcontrast(struct gspca_dev *gspca_dev)
1086{
1087 struct sd *sd = (struct sd *) gspca_dev;
1088 __u8 k2;
1089 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1090
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 k2 = sd->contrast;
1092 contrast[2] = k2;
1093 contrast[0] = (k2 + 1) >> 1;
1094 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001095 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001096}
1097
1098static void setcolors(struct gspca_dev *gspca_dev)
1099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101 __u8 data;
1102 int colour;
1103
1104 colour = sd->colors - 128;
1105 if (colour > 0)
1106 data = (colour + 32) & 0x7f; /* blue */
1107 else
1108 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001109 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110}
1111
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001112static void setautogain(struct gspca_dev *gspca_dev)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 switch (sd->sensor) {
1117 case SENSOR_HV7131R:
1118 case SENSOR_MO4000:
1119 case SENSOR_MI0360:
1120 if (sd->autogain)
1121 sd->ag_cnt = AG_CNT_START;
1122 else
1123 sd->ag_cnt = -1;
1124 break;
1125 }
1126}
1127
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001128/* -- start the camera -- */
1129static void sd_start(struct gspca_dev *gspca_dev)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001132 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001133 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001134 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001135 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001136 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1137 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001138 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001139 static const __u8 CE_ov76xx[] =
1140 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001141
1142 sn9c1xx = sn_tb[(int) sd->sensor];
1143 configure_gpio(gspca_dev, sn9c1xx);
1144
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001145/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
Jean-Francois Moine60017612008-07-18 08:46:19 -03001146 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1147 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1148 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1149 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1150 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1151 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1152 reg_w1(gspca_dev, 0xd3, 0x50);
1153 reg_w1(gspca_dev, 0xc6, 0x00);
1154 reg_w1(gspca_dev, 0xc7, 0x00);
1155 reg_w1(gspca_dev, 0xc8, 0x50);
1156 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001157 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001158 switch (sd->sensor) {
1159 case SENSOR_OV7630:
1160 reg17 = 0xe2;
1161 break;
1162 case SENSOR_OV7648:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001163 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001164 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001165/*jfm: from win trace */
1166 case SENSOR_OV7660:
1167 reg17 = 0xa0;
1168 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001169 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001170 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001171 break;
1172 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001173 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001174 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1175 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1176 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1177 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001178 switch (sd->bridge) {
1179 case BRIDGE_SN9C325:
1180 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1181 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001183 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1184 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001185 reg_w1(gspca_dev, 0x9a, 0x0a);
1186 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001187 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001188 default:
1189 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001190 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001191 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001192 reg_w1(gspca_dev, 0x9a, 0x08);
1193 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001194 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195 }
1196
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001197 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001198 if (mode)
1199 reg1 = 0x46; /* 320 clk 48Mhz */
1200 else
1201 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001202 reg17 = 0x61;
1203 switch (sd->sensor) {
1204 case SENSOR_HV7131R:
1205 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001206 break;
1207 case SENSOR_MI0360:
1208 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001209 break;
1210 case SENSOR_MO4000:
1211 mo4000_InitSensor(gspca_dev);
1212 if (mode) {
1213/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1214 reg1 = 0x06; /* clk 24Mz */
1215 } else {
1216 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001217/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001218 }
1219 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001220 case SENSOR_OM6802:
1221 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001222 reg17 = 0x64; /* 640 MCKSIZE */
1223 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001224 case SENSOR_OV7630:
1225 ov7630_InitSensor(gspca_dev);
1226 reg17 = 0xe2;
1227 reg1 = 0x40;
1228 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001230 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231 reg17 = 0xa2;
1232 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233/* if (mode)
1234 ; * 320x2...
1235 else
1236 ; * 640x... */
1237 break;
1238 default:
1239/* case SENSOR_OV7660: */
1240 ov7660_InitSensor(gspca_dev);
1241 if (mode) {
1242/* reg17 = 0x21; * 320 */
1243/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001244/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001245 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001246 reg17 = 0x22; /* 640 MCKSIZE */
1247 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001248 }
1249 break;
1250 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001251 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001252 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001253 switch (sd->sensor) {
1254 case SENSOR_OV7630:
1255 case SENSOR_OV7648:
1256 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001257 break;
1258 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001259 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001260 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1261 break;
1262 }
1263
1264 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001265 reg18 = sn9c1xx[0x18] | (mode << 4);
1266 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001267
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001268 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1269 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001270
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001271 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001272
Jean-Francois Moine60017612008-07-18 08:46:19 -03001273 reg_w1(gspca_dev, 0x17, reg17);
1274 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001275 setbrightness(gspca_dev);
1276 setcontrast(gspca_dev);
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001277 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001278}
1279
1280static void sd_stopN(struct gspca_dev *gspca_dev)
1281{
1282 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001283 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001284 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001285 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001286 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001287 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001288 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289
1290 data = 0x0b;
1291 switch (sd->sensor) {
1292 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001293 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001294 data = 0x2b;
1295 break;
1296 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001297 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001298 data = 0x29;
1299 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001300 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001301 case SENSOR_OV7648:
1302 data = 0x29;
1303 break;
1304 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001305/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001306/* case SENSOR_OV7660: */
1307 break;
1308 }
1309 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001310 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1311 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1312 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1313 reg_w1(gspca_dev, 0x01, data);
1314 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001315}
1316
1317static void sd_stop0(struct gspca_dev *gspca_dev)
1318{
1319}
1320
1321static void sd_close(struct gspca_dev *gspca_dev)
1322{
1323}
1324
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001325static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001326{
1327 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001329 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001330 __u8 luma_mean = 130;
1331 __u8 luma_delta = 20;
1332
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001333 /* Thanks S., without your advice, autobright should not work :) */
1334 if (sd->ag_cnt < 0)
1335 return;
1336 if (--sd->ag_cnt >= 0)
1337 return;
1338 sd->ag_cnt = AG_CNT_START;
1339
1340 delta = atomic_read(&sd->avg_lum);
1341 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001342 if (delta < luma_mean - luma_delta ||
1343 delta > luma_mean + luma_delta) {
1344 switch (sd->sensor) {
1345 case SENSOR_HV7131R:
1346 expotimes = sd->exposure >> 8;
1347 expotimes += (luma_mean - delta) >> 4;
1348 if (expotimes < 0)
1349 expotimes = 0;
1350 sd->exposure = setexposure(gspca_dev,
1351 (unsigned int) (expotimes << 8));
1352 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001353 default:
1354/* case SENSOR_MO4000: */
1355/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001356/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001357 expotimes = sd->exposure;
1358 expotimes += (luma_mean - delta) >> 6;
1359 if (expotimes < 0)
1360 expotimes = 0;
1361 sd->exposure = setexposure(gspca_dev,
1362 (unsigned int) expotimes);
1363 setcolors(gspca_dev);
1364 break;
1365 }
1366 }
1367}
1368
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001369/* scan the URB packets */
1370/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001371static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1372 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001373 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001374 int len) /* iso packet length */
1375{
1376 struct sd *sd = (struct sd *) gspca_dev;
1377 int sof, avg_lum;
1378
1379 sof = len - 64;
1380 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1381
1382 /* end of frame */
1383 gspca_frame_add(gspca_dev, LAST_PACKET,
1384 frame, data, sof + 2);
1385 if (sd->ag_cnt < 0)
1386 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001387/* w1 w2 w3 */
1388/* w4 w5 w6 */
1389/* w7 w8 */
1390/* w4 */
1391 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1392/* w6 */
1393 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1394/* w2 */
1395 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1396/* w8 */
1397 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1398/* w5 */
1399 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1400 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001401 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001402 return;
1403 }
1404 if (gspca_dev->last_packet_type == LAST_PACKET) {
1405
1406 /* put the JPEG 422 header */
1407 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1408 }
1409 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1410}
1411
1412static unsigned int getexposure(struct gspca_dev *gspca_dev)
1413{
1414 struct sd *sd = (struct sd *) gspca_dev;
1415 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001416
1417 switch (sd->sensor) {
1418 case SENSOR_HV7131R:
1419 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001420 i2c_r5(gspca_dev, 0x25);
1421 return (gspca_dev->usb_buf[0] << 16)
1422 | (gspca_dev->usb_buf[1] << 8)
1423 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001424 case SENSOR_MI0360:
1425 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001426 i2c_r5(gspca_dev, 0x09);
1427 return (gspca_dev->usb_buf[0] << 8)
1428 | gspca_dev->usb_buf[1];
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001429 default:
1430/* case SENSOR_MO4000: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001431 i2c_r5(gspca_dev, 0x0e);
1432 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1433 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1434 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001435 PDEBUG(D_CONF, "exposure %d",
1436 (hexpo << 10) | (mexpo << 2) | lexpo);
1437 return (hexpo << 10) | (mexpo << 2) | lexpo;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001438#if 0
1439/*jfm: not called*/
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001440/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001441/* case SENSOR_OV7660: */
1442 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001443 i2c_r5(gspca_dev, 0x04);
1444 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1445 lexpo = gspca_dev->usb_buf[0] & 0x02;
1446 i2c_r5(gspca_dev, 0x08);
1447 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001448 return (hexpo << 10) | (mexpo << 2) | lexpo;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001449#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001450 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001451 /* not reached */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001452}
1453
1454static void getbrightness(struct gspca_dev *gspca_dev)
1455{
1456 struct sd *sd = (struct sd *) gspca_dev;
1457
1458 /* hardcoded registers seem not readable */
1459 switch (sd->sensor) {
1460 case SENSOR_HV7131R:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001461 sd->brightness = getexposure(gspca_dev) >> 4;
1462 break;
1463 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001464 case SENSOR_MO4000:
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001465 case SENSOR_OM6802:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001466 sd->brightness = getexposure(gspca_dev) << 4;
1467 break;
1468 }
1469}
1470
1471static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1472{
1473 struct sd *sd = (struct sd *) gspca_dev;
1474
1475 sd->brightness = val;
1476 if (gspca_dev->streaming)
1477 setbrightness(gspca_dev);
1478 return 0;
1479}
1480
1481static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1482{
1483 struct sd *sd = (struct sd *) gspca_dev;
1484
1485 getbrightness(gspca_dev);
1486 *val = sd->brightness;
1487 return 0;
1488}
1489
1490static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1491{
1492 struct sd *sd = (struct sd *) gspca_dev;
1493
1494 sd->contrast = val;
1495 if (gspca_dev->streaming)
1496 setcontrast(gspca_dev);
1497 return 0;
1498}
1499
1500static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1501{
1502 struct sd *sd = (struct sd *) gspca_dev;
1503
1504 *val = sd->contrast;
1505 return 0;
1506}
1507
1508static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1509{
1510 struct sd *sd = (struct sd *) gspca_dev;
1511
1512 sd->colors = val;
1513 if (gspca_dev->streaming)
1514 setcolors(gspca_dev);
1515 return 0;
1516}
1517
1518static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1519{
1520 struct sd *sd = (struct sd *) gspca_dev;
1521
1522 *val = sd->colors;
1523 return 0;
1524}
1525
1526static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1527{
1528 struct sd *sd = (struct sd *) gspca_dev;
1529
1530 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001531 if (gspca_dev->streaming)
1532 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001533 return 0;
1534}
1535
1536static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1537{
1538 struct sd *sd = (struct sd *) gspca_dev;
1539
1540 *val = sd->autogain;
1541 return 0;
1542}
1543
1544/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001545static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001546 .name = MODULE_NAME,
1547 .ctrls = sd_ctrls,
1548 .nctrls = ARRAY_SIZE(sd_ctrls),
1549 .config = sd_config,
1550 .open = sd_open,
1551 .start = sd_start,
1552 .stopN = sd_stopN,
1553 .stop0 = sd_stop0,
1554 .close = sd_close,
1555 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001556 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001557};
1558
1559/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001560#define BSI(bridge, sensor, i2c_addr) \
1561 .driver_info = (BRIDGE_ ## bridge << 16) \
1562 | (SENSOR_ ## sensor << 8) \
1563 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001564static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001565#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001566 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1567 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1568 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1569 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1570 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001571#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001572 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1573 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1574/* bw600.inf:
1575 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1576/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1577/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1578 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1579/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1580 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1581/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1582/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1583 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1584/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1585/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1586 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1587 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1588/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1589/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1590/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1591/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001592 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1593/*bw600.inf:*/
1594 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001595 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001596 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001597/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001598#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001599 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1600 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1601/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1602 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1603 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1604/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001605#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001606 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001607 {}
1608};
1609MODULE_DEVICE_TABLE(usb, device_table);
1610
1611/* -- device connect -- */
1612static int sd_probe(struct usb_interface *intf,
1613 const struct usb_device_id *id)
1614{
1615 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1616 THIS_MODULE);
1617}
1618
1619static struct usb_driver sd_driver = {
1620 .name = MODULE_NAME,
1621 .id_table = device_table,
1622 .probe = sd_probe,
1623 .disconnect = gspca_disconnect,
1624};
1625
1626/* -- module insert / remove -- */
1627static int __init sd_mod_init(void)
1628{
1629 if (usb_register(&sd_driver) < 0)
1630 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001631 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001632 return 0;
1633}
1634static void __exit sd_mod_exit(void)
1635{
1636 usb_deregister(&sd_driver);
1637 info("deregistered");
1638}
1639
1640module_init(sd_mod_init);
1641module_exit(sd_mod_exit);