V4L/DVB (8673): gspca: Bad frame scanning again and bad init in pac7311.
[deliverable/linux.git] / drivers / media / video / gspca / sonixj.c
CommitLineData
6a7eba24
JFM
1/*
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
6a7eba24
JFM
27MODULE_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
cebf3b67 35 atomic_t avg_lum;
6a7eba24
JFM
36 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;
3647fea8
HG
47 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
6a7eba24
JFM
53 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_MI0360 1
56#define SENSOR_MO4000 2
d2d16e90
JFM
57#define SENSOR_OM6802 3
58#define SENSOR_OV7648 4
59#define SENSOR_OV7660 5
6a7eba24 60 unsigned char i2c_base;
6a7eba24
JFM
61};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
72
73static struct ctrl sd_ctrls[] = {
6a7eba24
JFM
74 {
75 {
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "Brightness",
79 .minimum = 0,
80 .maximum = 0xffff,
81 .step = 1,
a5ae2062
JFM
82#define BRIGHTNESS_DEF 0x7fff
83 .default_value = BRIGHTNESS_DEF,
6a7eba24
JFM
84 },
85 .set = sd_setbrightness,
86 .get = sd_getbrightness,
87 },
6a7eba24
JFM
88 {
89 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
94 .maximum = 127,
95 .step = 1,
a5ae2062
JFM
96#define CONTRAST_DEF 63
97 .default_value = CONTRAST_DEF,
6a7eba24
JFM
98 },
99 .set = sd_setcontrast,
100 .get = sd_getcontrast,
101 },
6a7eba24
JFM
102 {
103 {
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Color",
107 .minimum = 0,
108 .maximum = 255,
109 .step = 1,
a5ae2062
JFM
110#define COLOR_DEF 127
111 .default_value = COLOR_DEF,
6a7eba24
JFM
112 },
113 .set = sd_setcolors,
114 .get = sd_getcolors,
115 },
6a7eba24
JFM
116 {
117 {
118 .id = V4L2_CID_AUTOGAIN,
119 .type = V4L2_CTRL_TYPE_BOOLEAN,
120 .name = "Auto Gain",
121 .minimum = 0,
122 .maximum = 1,
123 .step = 1,
a5ae2062
JFM
124#define AUTOGAIN_DEF 1
125 .default_value = AUTOGAIN_DEF,
6a7eba24
JFM
126 },
127 .set = sd_setautogain,
128 .get = sd_getautogain,
129 },
130};
131
c2446b3e
JFM
132static struct v4l2_pix_format vga_mode[] = {
133 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .bytesperline = 160,
135 .sizeimage = 160 * 120 * 3 / 8 + 590,
136 .colorspace = V4L2_COLORSPACE_JPEG,
137 .priv = 2},
138 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .bytesperline = 320,
140 .sizeimage = 320 * 240 * 3 / 8 + 590,
141 .colorspace = V4L2_COLORSPACE_JPEG,
142 .priv = 1},
143 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 640,
145 .sizeimage = 640 * 480 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 0},
6a7eba24
JFM
148};
149
150/*Data from sn9c102p+hv71331r */
a5ae2062 151static const __u8 sn_hv7131[] = {
8f47a3ce
JFM
152/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
153 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
154/* reg8 reg9 rega regb regc regd rege regf */
155 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
156/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
157 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
158/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
159 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6a7eba24
JFM
160};
161
a5ae2062 162static const __u8 sn_mi0360[] = {
8f47a3ce
JFM
163/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
164 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
165/* reg8 reg9 rega regb regc regd rege regf */
166 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
167/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
168 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
169/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
170 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6a7eba24
JFM
171};
172
a5ae2062 173static const __u8 sn_mo4000[] = {
8f47a3ce
JFM
174/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
175 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
176/* reg8 reg9 rega regb regc regd rege regf */
177 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
179 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
180/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
181 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6a7eba24
JFM
182};
183
d2d16e90
JFM
184static const __u8 sn_om6802[] = {
185/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
186 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
187/* reg8 reg9 rega regb regc regd rege regf */
188 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
190 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
191/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
192 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
194 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
195 0xf7
196};
197
a5ae2062 198static const __u8 sn_ov7648[] = {
8f47a3ce
JFM
199/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
200 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
201/* reg8 reg9 rega regb regc regd rege regf */
202 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
203/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
204 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
205/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
206 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
6a7eba24
JFM
207};
208
a5ae2062 209static const __u8 sn_ov7660[] = {
8f47a3ce
JFM
210/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
211 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
212/* reg8 reg9 rega regb regc regd rege regf */
213 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
214/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
215 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
216/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
217 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6a7eba24
JFM
218};
219
220/* sequence specific to the sensors - !! index = SENSOR_xxx */
a5ae2062 221static const __u8 *sn_tb[] = {
6a7eba24
JFM
222 sn_hv7131,
223 sn_mi0360,
224 sn_mo4000,
d2d16e90 225 sn_om6802,
6a7eba24
JFM
226 sn_ov7648,
227 sn_ov7660
228};
229
a5ae2062 230static const __u8 regsn20[] = {
6a7eba24
JFM
231 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
232 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
233};
a5ae2062 234static const __u8 regsn20_sn9c325[] = {
6a7eba24
JFM
235 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
236 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
237};
238
a5ae2062 239static const __u8 reg84[] = {
6a7eba24
JFM
240 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
241 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
242/* 0x00, 0x00, 0x00, 0x00, 0x00 */
243 0xf7, 0x0f, 0x0a, 0x00, 0x00
244};
a5ae2062 245static const __u8 reg84_sn9c325[] = {
6a7eba24
JFM
246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
248 0xf8, 0x0f, 0x00, 0x00, 0x00
249};
250
a5ae2062 251static const __u8 hv7131r_sensor_init[][8] = {
6a7eba24
JFM
252 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
253 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
254 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
255 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
258 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
259
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
262 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
263 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
264 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
267 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
268
269 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
270 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
272 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
274
275 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
a5ae2062 280 {}
6a7eba24 281};
a5ae2062 282static const __u8 mi0360_sensor_init[][8] = {
6a7eba24
JFM
283 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
287 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
288 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
305 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
306 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
308 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
310 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
312 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
315 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
316
317 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
318 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
319 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
321 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
322
323 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
324 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
325 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
326 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
327
328 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
329 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
330/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
331/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
332 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
333 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
a5ae2062 334 {}
6a7eba24 335};
a5ae2062 336static const __u8 mo4000_sensor_init[][8] = {
6a7eba24
JFM
337 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
a5ae2062 357 {}
6a7eba24 358};
d2d16e90
JFM
359static __u8 om6802_sensor_init[][8] = {
360 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
361 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
362 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
363 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
364/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
365 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
366 /* white balance & auto-exposure */
367/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
368 * set color mode */
369/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
370 * max AGC value in AE */
371/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
372 * preset AGC */
373/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
374 * preset brightness */
375/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
376 * preset contrast */
377/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
378 * preset gamma */
379 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
380 /* luminance mode (0x4f = AE) */
381 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
382 /* preset shutter */
383/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
384 * auto frame rate */
385/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
386
387/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
388/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
389/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
390/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
391 {}
392};
a5ae2062 393static const __u8 ov7660_sensor_init[][8] = {
6a7eba24 394 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
60017617 395/* (delay 20ms) */
6a7eba24 396 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
738608ae 397 /* Outformat = rawRGB */
6a7eba24 398 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
738608ae 399 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
6a7eba24
JFM
400 /* GAIN BLUE RED VREF */
401 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
402 /* COM 1 BAVE GEAVE AECHH */
403 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
404 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
738608ae 405 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
6a7eba24
JFM
406 /* AECH CLKRC COM7 COM8 */
407 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
408 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
409 /* HSTART HSTOP VSTRT VSTOP */
410 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
411 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
412 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
413 /* BOS GBOS GROS ROS (BGGR offset) */
738608ae
JFM
414/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
415 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
6a7eba24
JFM
416 /* AEW AEB VPT BBIAS */
417 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
418 /* GbBIAS RSVD EXHCH EXHCL */
419 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
420 /* RBIAS ADVFL ASDVFH YAVE */
421 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
422 /* HSYST HSYEN HREF */
423 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
424 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
425 /* ADC ACOM OFON TSLB */
426 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
427 /* COM11 COM12 COM13 COM14 */
428 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
429 /* EDGE COM15 COM16 COM17 */
430 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
431 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
432 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
433 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
434 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
435 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
436 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
437 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
438 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
439 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
440 /* LCC1 LCC2 LCC3 LCC4 */
441 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
738608ae 442 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
6a7eba24 443 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
738608ae 444 /* band gap reference [0:3] DBLV */
6a7eba24
JFM
445 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
446 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
447 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
448 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
449 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
450 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
451 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
452 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
453 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
738608ae 454 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
6a7eba24 455/****** (some exchanges in the win trace) ******/
738608ae 456 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
6a7eba24
JFM
457 /* bits[3..0]reserved */
458 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
459 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
460 /* VREF vertical frame ctrl */
461 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
738608ae
JFM
462 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
463 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
464 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
465 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
466/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
6a7eba24
JFM
467/****** (some exchanges in the win trace) ******/
468 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
738608ae
JFM
469 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
470 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
471 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
472/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
6a7eba24 473/****** (some exchanges in the win trace) ******/
738608ae 474/******!! startsensor KO if changed !!****/
6a7eba24
JFM
475 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
477 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
478 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
a5ae2062 479 {}
6a7eba24 480};
738608ae
JFM
481/* reg 0x04 reg 0x07 reg 0x10 */
482/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
6a7eba24 483
a5ae2062 484static const __u8 ov7648_sensor_init[][8] = {
6a7eba24
JFM
485 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
486 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
487 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
488 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
489 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
492 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
493 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
494 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
495 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
496 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
497 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
498 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
499 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
500 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
501 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
502 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
503 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
504 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
505 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
506 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
507 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
508 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
509 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
510 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
511 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
512 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
513 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
514 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
515 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
516 * This is currently setting a
517 * blue tint, and some things more , i leave it here for future test if
518 * somene is having problems with color on this sensor
519 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
520 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
521 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
522 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
523 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
524 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
525 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
526 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
527 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
528 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
529 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
530 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
531 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
532 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
533 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
534 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
535 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
536/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
a5ae2062 537 {}
6a7eba24
JFM
538};
539
a5ae2062 540static const __u8 qtable4[] = {
6a7eba24
JFM
541 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
542 0x06, 0x08, 0x0A, 0x11,
543 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
544 0x19, 0x19, 0x17, 0x15,
545 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
546 0x21, 0x2E, 0x21, 0x23,
547 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
548 0x25, 0x29, 0x2C, 0x29,
549 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
550 0x17, 0x1B, 0x29, 0x29,
551 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
552 0x29, 0x29, 0x29, 0x29,
553 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
554 0x29, 0x29, 0x29, 0x29,
555 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
556 0x29, 0x29, 0x29, 0x29
557};
558
739570bb
JFM
559/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
560static void reg_r(struct gspca_dev *gspca_dev,
561 __u16 value, int len)
6a7eba24 562{
739570bb
JFM
563 usb_control_msg(gspca_dev->dev,
564 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
565 0,
566 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
739570bb 568 gspca_dev->usb_buf, len,
6a7eba24 569 500);
60017617 570 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
6a7eba24
JFM
571}
572
60017617
JFM
573static void reg_w1(struct gspca_dev *gspca_dev,
574 __u16 value,
575 __u8 data)
576{
577 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
578 gspca_dev->usb_buf[0] = data;
579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
581 0x08,
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
583 value,
584 0,
585 gspca_dev->usb_buf, 1,
586 500);
587}
739570bb 588static void reg_w(struct gspca_dev *gspca_dev,
6a7eba24 589 __u16 value,
bf7f0b98 590 const __u8 *buffer,
6a7eba24
JFM
591 int len)
592{
60017617
JFM
593 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
594 value, buffer[0], buffer[1]);
739570bb
JFM
595 if (len <= sizeof gspca_dev->usb_buf) {
596 memcpy(gspca_dev->usb_buf, buffer, len);
597 usb_control_msg(gspca_dev->dev,
598 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062
JFM
599 0x08,
600 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
601 value, 0,
739570bb 602 gspca_dev->usb_buf, len,
a5ae2062
JFM
603 500);
604 } else {
605 __u8 *tmpbuf;
606
607 tmpbuf = kmalloc(len, GFP_KERNEL);
608 memcpy(tmpbuf, buffer, len);
739570bb
JFM
609 usb_control_msg(gspca_dev->dev,
610 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062
JFM
611 0x08,
612 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
613 value, 0,
614 tmpbuf, len,
615 500);
616 kfree(tmpbuf);
bf7f0b98 617 }
6a7eba24
JFM
618}
619
60017617
JFM
620/* I2C write 1 byte */
621static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
6a7eba24
JFM
622{
623 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 624
60017617
JFM
625 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
626 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
627 gspca_dev->usb_buf[1] = sd->i2c_base;
628 gspca_dev->usb_buf[2] = reg;
629 gspca_dev->usb_buf[3] = val;
630 gspca_dev->usb_buf[4] = 0;
631 gspca_dev->usb_buf[5] = 0;
632 gspca_dev->usb_buf[6] = 0;
633 gspca_dev->usb_buf[7] = 0x10;
634 usb_control_msg(gspca_dev->dev,
635 usb_sndctrlpipe(gspca_dev->dev, 0),
636 0x08,
637 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
638 0x08, /* value = i2c */
639 0,
640 gspca_dev->usb_buf, 8,
641 500);
6a7eba24
JFM
642}
643
739570bb
JFM
644/* I2C write 8 bytes */
645static void i2c_w8(struct gspca_dev *gspca_dev,
646 const __u8 *buffer)
6a7eba24 647{
60017617
JFM
648 memcpy(gspca_dev->usb_buf, buffer, 8);
649 usb_control_msg(gspca_dev->dev,
650 usb_sndctrlpipe(gspca_dev->dev, 0),
651 0x08,
652 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
653 0x08, 0, /* value, index */
654 gspca_dev->usb_buf, 8,
655 500);
6a7eba24
JFM
656}
657
739570bb
JFM
658/* read 5 bytes in gspca_dev->usb_buf */
659static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
6a7eba24
JFM
660{
661 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
662 __u8 mode[8];
663
3647fea8 664 mode[0] = 0x81 | 0x10;
6a7eba24
JFM
665 mode[1] = sd->i2c_base;
666 mode[2] = reg;
667 mode[3] = 0;
668 mode[4] = 0;
669 mode[5] = 0;
670 mode[6] = 0;
671 mode[7] = 0x10;
739570bb 672 i2c_w8(gspca_dev, mode);
60017617 673 msleep(2);
3647fea8 674 mode[0] = 0x81 | (5 << 4) | 0x02;
6a7eba24 675 mode[2] = 0;
739570bb 676 i2c_w8(gspca_dev, mode);
60017617 677 msleep(2);
739570bb 678 reg_r(gspca_dev, 0x0a, 5);
6a7eba24
JFM
679}
680
681static int probesensor(struct gspca_dev *gspca_dev)
682{
683 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 684
60017617 685 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
6a7eba24 686 msleep(10);
60017617 687 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
6a7eba24 688 msleep(10);
739570bb
JFM
689 i2c_r5(gspca_dev, 0); /* read sensor id */
690 if (gspca_dev->usb_buf[0] == 0x02
691 && gspca_dev->usb_buf[1] == 0x09
692 && gspca_dev->usb_buf[2] == 0x01
693 && gspca_dev->usb_buf[3] == 0x00
694 && gspca_dev->usb_buf[4] == 0x00) {
6a7eba24
JFM
695 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
696 sd->sensor = SENSOR_HV7131R;
697 return SENSOR_HV7131R;
698 }
60017617 699 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
739570bb
JFM
700 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
701 gspca_dev->usb_buf[2]);
6a7eba24
JFM
702 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
703 return -ENODEV;
704}
705
706static int configure_gpio(struct gspca_dev *gspca_dev,
a5ae2062 707 const __u8 *sn9c1xx)
6a7eba24
JFM
708{
709 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062
JFM
710 const __u8 *reg9a;
711 static const __u8 reg9a_def[] =
6a7eba24 712 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
a5ae2062 713 static const __u8 reg9a_sn9c325[] =
6a7eba24 714 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
8f47a3ce 715 static const __u8 regd4[] = {0x60, 0x00, 0x00};
6a7eba24 716
60017617 717 reg_w1(gspca_dev, 0xf1, 0x00);
8f47a3ce 718 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
6a7eba24
JFM
719
720 /* configure gpio */
739570bb
JFM
721 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
722 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
60017617 723 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
3647fea8
HG
724 switch (sd->bridge) {
725 case BRIDGE_SN9C325:
6a7eba24
JFM
726 reg9a = reg9a_sn9c325;
727 break;
6a7eba24
JFM
728 default:
729 reg9a = reg9a_def;
730 break;
731 }
739570bb 732 reg_w(gspca_dev, 0x9a, reg9a, 6);
6a7eba24 733
8f47a3ce 734 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
6a7eba24 735
739570bb 736 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
6a7eba24 737
d2d16e90
JFM
738 switch (sd->sensor) {
739 case SENSOR_OM6802:
740 reg_w1(gspca_dev, 0x02, 0x71);
741 reg_w1(gspca_dev, 0x01, 0x42);
742 reg_w1(gspca_dev, 0x17, 0x64);
743 reg_w1(gspca_dev, 0x01, 0x42);
744 break;
745 case SENSOR_OV7648:
60017617
JFM
746 reg_w1(gspca_dev, 0x01, 0x43);
747 reg_w1(gspca_dev, 0x17, 0xae);
748 reg_w1(gspca_dev, 0x01, 0x42);
6a7eba24
JFM
749 break;
750 default:
60017617
JFM
751 reg_w1(gspca_dev, 0x01, 0x43);
752 reg_w1(gspca_dev, 0x17, 0x61);
753 reg_w1(gspca_dev, 0x01, 0x42);
d2d16e90
JFM
754 if (sd->sensor == SENSOR_HV7131R) {
755 if (probesensor(gspca_dev) < 0)
756 return -ENODEV;
757 }
758 break;
6a7eba24
JFM
759 }
760 return 0;
761}
762
763static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
764{
765 int i = 0;
a5ae2062 766 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
6a7eba24
JFM
767 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
768
769 while (hv7131r_sensor_init[i][0]) {
739570bb 770 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
6a7eba24
JFM
771 i++;
772 }
739570bb 773 i2c_w8(gspca_dev, SetSensorClk);
6a7eba24
JFM
774}
775
776static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
777{
778 int i = 0;
6a7eba24
JFM
779
780 while (mi0360_sensor_init[i][0]) {
739570bb 781 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
6a7eba24
JFM
782 i++;
783 }
784}
785
786static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
787{
788 int i = 0;
6a7eba24
JFM
789
790 while (mo4000_sensor_init[i][0]) {
739570bb 791 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
6a7eba24
JFM
792 i++;
793 }
794}
795
d2d16e90
JFM
796static void om6802_InitSensor(struct gspca_dev *gspca_dev)
797{
798 int i = 0;
799
800 while (om6802_sensor_init[i][0]) {
801 i2c_w8(gspca_dev, om6802_sensor_init[i]);
802 i++;
803 }
804}
805
6a7eba24
JFM
806static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
807{
6a7eba24
JFM
808 int i = 0;
809
810 while (ov7648_sensor_init[i][0]) {
739570bb 811 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
6a7eba24
JFM
812 i++;
813 }
814}
815
816static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
817{
818 int i = 0;
6a7eba24 819
60017617
JFM
820 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
821 i++;
822 msleep(20);
6a7eba24 823 while (ov7660_sensor_init[i][0]) {
739570bb 824 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
6a7eba24
JFM
825 i++;
826 }
827}
828
829/* this function is called at probe time */
830static int sd_config(struct gspca_dev *gspca_dev,
831 const struct usb_device_id *id)
832{
833 struct sd *sd = (struct sd *) gspca_dev;
834 struct cam *cam;
6a7eba24
JFM
835
836 cam = &gspca_dev->cam;
6a7eba24
JFM
837 cam->epaddr = 0x01;
838 cam->cam_mode = vga_mode;
839 cam->nmodes = ARRAY_SIZE(vga_mode);
a5ae2062 840
9d64fdb1
JFM
841 sd->bridge = id->driver_info >> 16;
842 sd->sensor = id->driver_info >> 8;
843 sd->i2c_base = id->driver_info;
844
6a7eba24 845 sd->qindex = 4; /* set the quantization table */
a5ae2062
JFM
846 sd->brightness = BRIGHTNESS_DEF;
847 sd->contrast = CONTRAST_DEF;
848 sd->colors = COLOR_DEF;
849 sd->autogain = AUTOGAIN_DEF;
cebf3b67
JFM
850 sd->ag_cnt = -1;
851
6a7eba24
JFM
852 return 0;
853}
854
855/* this function is called at open time */
856static int sd_open(struct gspca_dev *gspca_dev)
857{
858 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 859/* const __u8 *sn9c1xx; */
6a7eba24 860 __u8 regGpio[] = { 0x29, 0x74 };
60017617 861 __u8 regF1;
6a7eba24 862
3647fea8 863 /* setup a selector by bridge */
60017617 864 reg_w1(gspca_dev, 0xf1, 0x01);
739570bb 865 reg_r(gspca_dev, 0x00, 1);
8f47a3ce
JFM
866 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
867 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
739570bb 868 regF1 = gspca_dev->usb_buf[0];
8f47a3ce 869 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
3647fea8
HG
870 switch (sd->bridge) {
871 case BRIDGE_SN9C102P:
6a7eba24
JFM
872 if (regF1 != 0x11)
873 return -ENODEV;
60017617 874 reg_w1(gspca_dev, 0x02, regGpio[1]);
6a7eba24 875 break;
3647fea8 876 case BRIDGE_SN9C105:
6a7eba24
JFM
877 if (regF1 != 0x11)
878 return -ENODEV;
739570bb 879 reg_w(gspca_dev, 0x02, regGpio, 2);
6a7eba24 880 break;
3647fea8 881 case BRIDGE_SN9C120:
6a7eba24
JFM
882 if (regF1 != 0x12)
883 return -ENODEV;
884 regGpio[1] = 0x70;
739570bb 885 reg_w(gspca_dev, 0x02, regGpio, 2);
6a7eba24
JFM
886 break;
887 default:
60017617 888/* case BRIDGE_SN9C110: */
3647fea8 889/* case BRIDGE_SN9C325: */
6a7eba24
JFM
890 if (regF1 != 0x12)
891 return -ENODEV;
60017617 892 reg_w1(gspca_dev, 0x02, 0x62);
6a7eba24
JFM
893 break;
894 }
895
60017617 896 reg_w1(gspca_dev, 0xf1, 0x01);
6a7eba24
JFM
897
898 return 0;
899}
900
901static unsigned int setexposure(struct gspca_dev *gspca_dev,
902 unsigned int expo)
903{
904 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 905 static const __u8 doit[] = /* update sensor */
6a7eba24 906 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
a5ae2062 907 static const __u8 sensorgo[] = /* sensor on */
6a7eba24 908 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
a5ae2062 909 static const __u8 gainMo[] =
6a7eba24
JFM
910 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
911
912 switch (sd->sensor) {
913 case SENSOR_HV7131R: {
914 __u8 Expodoit[] =
915 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
916
917 Expodoit[3] = expo >> 16;
918 Expodoit[4] = expo >> 8;
919 Expodoit[5] = expo;
739570bb 920 i2c_w8(gspca_dev, Expodoit);
6a7eba24
JFM
921 break;
922 }
923 case SENSOR_MI0360: {
924 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
925 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
926
927 if (expo > 0x0635)
928 expo = 0x0635;
929 else if (expo < 0x0001)
930 expo = 0x0001;
931 expoMi[3] = expo >> 8;
932 expoMi[4] = expo;
739570bb
JFM
933 i2c_w8(gspca_dev, expoMi);
934 i2c_w8(gspca_dev, doit);
935 i2c_w8(gspca_dev, sensorgo);
6a7eba24
JFM
936 break;
937 }
938 case SENSOR_MO4000: {
939 __u8 expoMof[] =
940 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
941 __u8 expoMo10[] =
942 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
943
944 if (expo > 0x1fff)
945 expo = 0x1fff;
946 else if (expo < 0x0001)
947 expo = 0x0001;
948 expoMof[3] = (expo & 0x03fc) >> 2;
739570bb 949 i2c_w8(gspca_dev, expoMof);
6a7eba24
JFM
950 expoMo10[3] = ((expo & 0x1c00) >> 10)
951 | ((expo & 0x0003) << 4);
739570bb
JFM
952 i2c_w8(gspca_dev, expoMo10);
953 i2c_w8(gspca_dev, gainMo);
956e42d2 954 PDEBUG(D_CONF, "set exposure %d",
6a7eba24
JFM
955 ((expoMo10[3] & 0x07) << 10)
956 | (expoMof[3] << 2)
957 | ((expoMo10[3] & 0x30) >> 4));
958 break;
959 }
d2d16e90
JFM
960 case SENSOR_OM6802: {
961 __u8 gainOm[] =
962 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
963
964 if (expo > 0x03ff)
965 expo = 0x03ff;
966 if (expo < 0x0001)
967 expo = 0x0001;
968 gainOm[3] = expo >> 2;
969 i2c_w8(gspca_dev, gainOm);
970 reg_w1(gspca_dev, 0x96, expo >> 5);
971 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
972 break;
973 }
6a7eba24
JFM
974 }
975 return expo;
976}
977
978static void setbrightness(struct gspca_dev *gspca_dev)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981 unsigned int expo;
982 __u8 k2;
983
d2d16e90 984 k2 = sd->brightness >> 10;
6a7eba24
JFM
985 switch (sd->sensor) {
986 case SENSOR_HV7131R:
987 expo = sd->brightness << 4;
988 if (expo > 0x002dc6c0)
989 expo = 0x002dc6c0;
990 else if (expo < 0x02a0)
991 expo = 0x02a0;
992 sd->exposure = setexposure(gspca_dev, expo);
993 break;
994 case SENSOR_MI0360:
6a7eba24
JFM
995 case SENSOR_MO4000:
996 expo = sd->brightness >> 4;
997 sd->exposure = setexposure(gspca_dev, expo);
998 break;
d2d16e90
JFM
999 case SENSOR_OM6802:
1000 expo = sd->brightness >> 6;
1001 sd->exposure = setexposure(gspca_dev, expo);
1002 k2 = sd->brightness >> 11;
1003 break;
6a7eba24
JFM
1004 }
1005
60017617 1006 reg_w1(gspca_dev, 0x96, k2);
6a7eba24
JFM
1007}
1008
1009static void setcontrast(struct gspca_dev *gspca_dev)
1010{
1011 struct sd *sd = (struct sd *) gspca_dev;
1012 __u8 k2;
1013 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1014
6a7eba24
JFM
1015 k2 = sd->contrast;
1016 contrast[2] = k2;
1017 contrast[0] = (k2 + 1) >> 1;
1018 contrast[4] = (k2 + 1) / 5;
739570bb 1019 reg_w(gspca_dev, 0x84, contrast, 6);
6a7eba24
JFM
1020}
1021
1022static void setcolors(struct gspca_dev *gspca_dev)
1023{
1024 struct sd *sd = (struct sd *) gspca_dev;
1025 __u8 data;
1026 int colour;
1027
1028 colour = sd->colors - 128;
1029 if (colour > 0)
1030 data = (colour + 32) & 0x7f; /* blue */
1031 else
1032 data = (-colour + 32) & 0x7f; /* red */
60017617 1033 reg_w1(gspca_dev, 0x05, data);
6a7eba24
JFM
1034}
1035
cebf3b67
JFM
1036static void setautogain(struct gspca_dev *gspca_dev)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039
1040 switch (sd->sensor) {
1041 case SENSOR_HV7131R:
1042 case SENSOR_MO4000:
1043 case SENSOR_MI0360:
1044 if (sd->autogain)
1045 sd->ag_cnt = AG_CNT_START;
1046 else
1047 sd->ag_cnt = -1;
1048 break;
1049 }
1050}
1051
6a7eba24
JFM
1052/* -- start the camera -- */
1053static void sd_start(struct gspca_dev *gspca_dev)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 1056 int i;
8f47a3ce 1057 __u8 reg1, reg17, reg18;
a5ae2062 1058 const __u8 *sn9c1xx;
6a7eba24 1059 int mode;
a5ae2062
JFM
1060 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1061 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
a5ae2062
JFM
1062 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1063 static const __u8 CE_sn9c325[] =
6a7eba24
JFM
1064 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1065
1066 sn9c1xx = sn_tb[(int) sd->sensor];
1067 configure_gpio(gspca_dev, sn9c1xx);
1068
8f47a3ce 1069/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
60017617
JFM
1070 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1071 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1072 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1073 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1074 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1075 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1076 reg_w1(gspca_dev, 0xd3, 0x50);
1077 reg_w1(gspca_dev, 0xc6, 0x00);
1078 reg_w1(gspca_dev, 0xc7, 0x00);
1079 reg_w1(gspca_dev, 0xc8, 0x50);
1080 reg_w1(gspca_dev, 0xc9, 0x3c);
60017617 1081 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
568788a7
JFM
1082 switch (sd->bridge) {
1083 case BRIDGE_SN9C325:
8f47a3ce 1084 reg17 = 0xae;
568788a7
JFM
1085 break;
1086 default:
8f47a3ce 1087 reg17 = 0x60;
568788a7
JFM
1088 break;
1089 }
8f47a3ce 1090 reg_w1(gspca_dev, 0x17, reg17);
60017617
JFM
1091 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1092 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1093 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1094 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
568788a7
JFM
1095 switch (sd->bridge) {
1096 case BRIDGE_SN9C325:
1097 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1098 sizeof regsn20_sn9c325);
6a7eba24 1099 for (i = 0; i < 8; i++)
568788a7
JFM
1100 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1101 sizeof reg84_sn9c325);
60017617
JFM
1102 reg_w1(gspca_dev, 0x9a, 0x0a);
1103 reg_w1(gspca_dev, 0x99, 0x60);
568788a7 1104 break;
568788a7
JFM
1105 default:
1106 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
6a7eba24 1107 for (i = 0; i < 8; i++)
568788a7 1108 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
60017617
JFM
1109 reg_w1(gspca_dev, 0x9a, 0x08);
1110 reg_w1(gspca_dev, 0x99, 0x59);
568788a7 1111 break;
6a7eba24
JFM
1112 }
1113
c2446b3e 1114 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
60017617
JFM
1115 if (mode)
1116 reg1 = 0x46; /* 320 clk 48Mhz */
1117 else
1118 reg1 = 0x06; /* 640 clk 24Mz */
6a7eba24
JFM
1119 reg17 = 0x61;
1120 switch (sd->sensor) {
1121 case SENSOR_HV7131R:
1122 hv7131R_InitSensor(gspca_dev);
6a7eba24
JFM
1123 break;
1124 case SENSOR_MI0360:
1125 mi0360_InitSensor(gspca_dev);
6a7eba24
JFM
1126 break;
1127 case SENSOR_MO4000:
1128 mo4000_InitSensor(gspca_dev);
1129 if (mode) {
1130/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1131 reg1 = 0x06; /* clk 24Mz */
1132 } else {
1133 reg17 = 0x22; /* 640 MCKSIZE */
60017617 1134/* reg1 = 0x06; * 640 clk 24Mz (done) */
6a7eba24
JFM
1135 }
1136 break;
d2d16e90
JFM
1137 case SENSOR_OM6802:
1138 om6802_InitSensor(gspca_dev);
d2d16e90
JFM
1139 reg17 = 0x64; /* 640 MCKSIZE */
1140 break;
6a7eba24 1141 case SENSOR_OV7648:
60017617 1142 ov7648_InitSensor(gspca_dev);
6a7eba24
JFM
1143 reg17 = 0xa2;
1144 reg1 = 0x44;
6a7eba24
JFM
1145/* if (mode)
1146 ; * 320x2...
1147 else
1148 ; * 640x... */
1149 break;
1150 default:
1151/* case SENSOR_OV7660: */
1152 ov7660_InitSensor(gspca_dev);
1153 if (mode) {
1154/* reg17 = 0x21; * 320 */
1155/* reg1 = 0x44; */
60017617 1156/* reg1 = 0x46; (done) */
6a7eba24 1157 } else {
8f47a3ce
JFM
1158 reg17 = 0x22; /* 640 MCKSIZE */
1159 reg1 = 0x06;
6a7eba24
JFM
1160 }
1161 break;
1162 }
739570bb 1163 reg_w(gspca_dev, 0xc0, C0, 6);
8f47a3ce 1164 reg_w(gspca_dev, 0xca, CA, 4);
3647fea8 1165 switch (sd->bridge) {
3647fea8 1166 case BRIDGE_SN9C325:
739570bb 1167 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
6a7eba24
JFM
1168 break;
1169 default:
739570bb 1170 reg_w(gspca_dev, 0xce, CE, 4);
6a7eba24
JFM
1171 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1172 break;
1173 }
1174
1175 /* here change size mode 0 -> VGA; 1 -> CIF */
8f47a3ce
JFM
1176 reg18 = sn9c1xx[0x18] | (mode << 4);
1177 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
6a7eba24 1178
739570bb
JFM
1179 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1180 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
6a7eba24 1181
8f47a3ce 1182 reg_w1(gspca_dev, 0x18, reg18);
6a7eba24 1183
60017617
JFM
1184 reg_w1(gspca_dev, 0x17, reg17);
1185 reg_w1(gspca_dev, 0x01, reg1);
6a7eba24
JFM
1186 setbrightness(gspca_dev);
1187 setcontrast(gspca_dev);
cebf3b67 1188 setautogain(gspca_dev);
6a7eba24
JFM
1189}
1190
1191static void sd_stopN(struct gspca_dev *gspca_dev)
1192{
1193 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1194 static const __u8 stophv7131[] =
6a7eba24 1195 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
a5ae2062 1196 static const __u8 stopmi0360[] =
6a7eba24 1197 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
6a7eba24 1198 __u8 data;
a5ae2062 1199 const __u8 *sn9c1xx;
6a7eba24
JFM
1200
1201 data = 0x0b;
1202 switch (sd->sensor) {
1203 case SENSOR_HV7131R:
739570bb 1204 i2c_w8(gspca_dev, stophv7131);
6a7eba24
JFM
1205 data = 0x2b;
1206 break;
1207 case SENSOR_MI0360:
739570bb 1208 i2c_w8(gspca_dev, stopmi0360);
6a7eba24
JFM
1209 data = 0x29;
1210 break;
6a7eba24
JFM
1211 case SENSOR_OV7648:
1212 data = 0x29;
1213 break;
1214 default:
8f47a3ce 1215/* case SENSOR_MO4000: */
6a7eba24
JFM
1216/* case SENSOR_OV7660: */
1217 break;
1218 }
1219 sn9c1xx = sn_tb[(int) sd->sensor];
60017617
JFM
1220 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1221 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1222 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1223 reg_w1(gspca_dev, 0x01, data);
1224 reg_w1(gspca_dev, 0xf1, 0x01);
6a7eba24
JFM
1225}
1226
1227static void sd_stop0(struct gspca_dev *gspca_dev)
1228{
1229}
1230
1231static void sd_close(struct gspca_dev *gspca_dev)
1232{
1233}
1234
cebf3b67 1235static void do_autogain(struct gspca_dev *gspca_dev)
6a7eba24
JFM
1236{
1237 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 1238 int delta;
cebf3b67 1239 int expotimes;
6a7eba24
JFM
1240 __u8 luma_mean = 130;
1241 __u8 luma_delta = 20;
1242
cebf3b67
JFM
1243 /* Thanks S., without your advice, autobright should not work :) */
1244 if (sd->ag_cnt < 0)
1245 return;
1246 if (--sd->ag_cnt >= 0)
1247 return;
1248 sd->ag_cnt = AG_CNT_START;
1249
1250 delta = atomic_read(&sd->avg_lum);
1251 PDEBUG(D_FRAM, "mean lum %d", delta);
6a7eba24
JFM
1252 if (delta < luma_mean - luma_delta ||
1253 delta > luma_mean + luma_delta) {
1254 switch (sd->sensor) {
1255 case SENSOR_HV7131R:
1256 expotimes = sd->exposure >> 8;
1257 expotimes += (luma_mean - delta) >> 4;
1258 if (expotimes < 0)
1259 expotimes = 0;
1260 sd->exposure = setexposure(gspca_dev,
1261 (unsigned int) (expotimes << 8));
1262 break;
cebf3b67
JFM
1263 default:
1264/* case SENSOR_MO4000: */
1265/* case SENSOR_MI0360: */
d2d16e90 1266/* case SENSOR_OM6802: */
6a7eba24
JFM
1267 expotimes = sd->exposure;
1268 expotimes += (luma_mean - delta) >> 6;
1269 if (expotimes < 0)
1270 expotimes = 0;
1271 sd->exposure = setexposure(gspca_dev,
1272 (unsigned int) expotimes);
1273 setcolors(gspca_dev);
1274 break;
1275 }
1276 }
1277}
1278
cebf3b67
JFM
1279/* scan the URB packets */
1280/* This function is run at interrupt level. */
6a7eba24
JFM
1281static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1282 struct gspca_frame *frame, /* target */
a5ae2062 1283 __u8 *data, /* isoc packet */
6a7eba24
JFM
1284 int len) /* iso packet length */
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287 int sof, avg_lum;
1288
1289 sof = len - 64;
1290 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1291
1292 /* end of frame */
1293 gspca_frame_add(gspca_dev, LAST_PACKET,
1294 frame, data, sof + 2);
1295 if (sd->ag_cnt < 0)
1296 return;
6a7eba24
JFM
1297/* w1 w2 w3 */
1298/* w4 w5 w6 */
1299/* w7 w8 */
1300/* w4 */
1301 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1302/* w6 */
1303 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1304/* w2 */
1305 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1306/* w8 */
1307 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1308/* w5 */
1309 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1310 avg_lum >>= 4;
cebf3b67 1311 atomic_set(&sd->avg_lum, avg_lum);
6a7eba24
JFM
1312 return;
1313 }
1314 if (gspca_dev->last_packet_type == LAST_PACKET) {
1315
1316 /* put the JPEG 422 header */
1317 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1318 }
1319 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1320}
1321
1322static unsigned int getexposure(struct gspca_dev *gspca_dev)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
1325 __u8 hexpo, mexpo, lexpo;
6a7eba24
JFM
1326
1327 switch (sd->sensor) {
1328 case SENSOR_HV7131R:
1329 /* read sensor exposure */
739570bb
JFM
1330 i2c_r5(gspca_dev, 0x25);
1331 return (gspca_dev->usb_buf[0] << 16)
1332 | (gspca_dev->usb_buf[1] << 8)
1333 | gspca_dev->usb_buf[2];
6a7eba24
JFM
1334 case SENSOR_MI0360:
1335 /* read sensor exposure */
739570bb
JFM
1336 i2c_r5(gspca_dev, 0x09);
1337 return (gspca_dev->usb_buf[0] << 8)
1338 | gspca_dev->usb_buf[1];
d2d16e90
JFM
1339 default:
1340/* case SENSOR_MO4000: */
739570bb
JFM
1341 i2c_r5(gspca_dev, 0x0e);
1342 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1343 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1344 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
6a7eba24
JFM
1345 PDEBUG(D_CONF, "exposure %d",
1346 (hexpo << 10) | (mexpo << 2) | lexpo);
1347 return (hexpo << 10) | (mexpo << 2) | lexpo;
d2d16e90
JFM
1348#if 0
1349/*jfm: not called*/
8f47a3ce 1350/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
6a7eba24
JFM
1351/* case SENSOR_OV7660: */
1352 /* read sensor exposure */
739570bb
JFM
1353 i2c_r5(gspca_dev, 0x04);
1354 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1355 lexpo = gspca_dev->usb_buf[0] & 0x02;
1356 i2c_r5(gspca_dev, 0x08);
1357 mexpo = gspca_dev->usb_buf[2];
6a7eba24 1358 return (hexpo << 10) | (mexpo << 2) | lexpo;
d2d16e90 1359#endif
6a7eba24 1360 }
d2d16e90 1361 /* not reached */
6a7eba24
JFM
1362}
1363
1364static void getbrightness(struct gspca_dev *gspca_dev)
1365{
1366 struct sd *sd = (struct sd *) gspca_dev;
1367
1368 /* hardcoded registers seem not readable */
1369 switch (sd->sensor) {
1370 case SENSOR_HV7131R:
6a7eba24
JFM
1371 sd->brightness = getexposure(gspca_dev) >> 4;
1372 break;
1373 case SENSOR_MI0360:
6a7eba24 1374 case SENSOR_MO4000:
d2d16e90 1375 case SENSOR_OM6802:
6a7eba24
JFM
1376 sd->brightness = getexposure(gspca_dev) << 4;
1377 break;
1378 }
1379}
1380
1381static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1382{
1383 struct sd *sd = (struct sd *) gspca_dev;
1384
1385 sd->brightness = val;
1386 if (gspca_dev->streaming)
1387 setbrightness(gspca_dev);
1388 return 0;
1389}
1390
1391static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1392{
1393 struct sd *sd = (struct sd *) gspca_dev;
1394
1395 getbrightness(gspca_dev);
1396 *val = sd->brightness;
1397 return 0;
1398}
1399
1400static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1401{
1402 struct sd *sd = (struct sd *) gspca_dev;
1403
1404 sd->contrast = val;
1405 if (gspca_dev->streaming)
1406 setcontrast(gspca_dev);
1407 return 0;
1408}
1409
1410static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1411{
1412 struct sd *sd = (struct sd *) gspca_dev;
1413
1414 *val = sd->contrast;
1415 return 0;
1416}
1417
1418static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1419{
1420 struct sd *sd = (struct sd *) gspca_dev;
1421
1422 sd->colors = val;
1423 if (gspca_dev->streaming)
1424 setcolors(gspca_dev);
1425 return 0;
1426}
1427
1428static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1429{
1430 struct sd *sd = (struct sd *) gspca_dev;
1431
1432 *val = sd->colors;
1433 return 0;
1434}
1435
1436static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1437{
1438 struct sd *sd = (struct sd *) gspca_dev;
1439
1440 sd->autogain = val;
cebf3b67
JFM
1441 if (gspca_dev->streaming)
1442 setautogain(gspca_dev);
6a7eba24
JFM
1443 return 0;
1444}
1445
1446static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1447{
1448 struct sd *sd = (struct sd *) gspca_dev;
1449
1450 *val = sd->autogain;
1451 return 0;
1452}
1453
1454/* sub-driver description */
a5ae2062 1455static const struct sd_desc sd_desc = {
6a7eba24
JFM
1456 .name = MODULE_NAME,
1457 .ctrls = sd_ctrls,
1458 .nctrls = ARRAY_SIZE(sd_ctrls),
1459 .config = sd_config,
1460 .open = sd_open,
1461 .start = sd_start,
1462 .stopN = sd_stopN,
1463 .stop0 = sd_stop0,
1464 .close = sd_close,
1465 .pkt_scan = sd_pkt_scan,
cebf3b67 1466 .dq_callback = do_autogain,
6a7eba24
JFM
1467};
1468
1469/* -- module initialisation -- */
9d64fdb1
JFM
1470#define BSI(bridge, sensor, i2c_addr) \
1471 .driver_info = (BRIDGE_ ## bridge << 16) \
1472 | (SENSOR_ ## sensor << 8) \
1473 | (i2c_addr)
a5ae2062 1474static const __devinitdata struct usb_device_id device_table[] = {
c41492c8 1475#ifndef CONFIG_USB_SN9C102
9d64fdb1
JFM
1476 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1477 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1478 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1479 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1480 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
c41492c8 1481#endif
9d64fdb1
JFM
1482 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1483 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1484/* bw600.inf:
1485 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1486/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1487/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1488 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1489/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1490 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1491/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1492/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1493 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1494/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1495/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1496 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1497 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1498/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1499/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1500/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1501/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
d2d16e90
JFM
1502 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1503/*bw600.inf:*/
1504 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
9d64fdb1
JFM
1505 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1506/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1507/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
c41492c8 1508#ifndef CONFIG_USB_SN9C102
9d64fdb1
JFM
1509 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1510 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1511/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1512 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1513 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1514/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
c41492c8 1515#endif
e546f4bb 1516 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
6a7eba24
JFM
1517 {}
1518};
1519MODULE_DEVICE_TABLE(usb, device_table);
1520
1521/* -- device connect -- */
1522static int sd_probe(struct usb_interface *intf,
1523 const struct usb_device_id *id)
1524{
1525 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1526 THIS_MODULE);
1527}
1528
1529static struct usb_driver sd_driver = {
1530 .name = MODULE_NAME,
1531 .id_table = device_table,
1532 .probe = sd_probe,
1533 .disconnect = gspca_disconnect,
1534};
1535
1536/* -- module insert / remove -- */
1537static int __init sd_mod_init(void)
1538{
1539 if (usb_register(&sd_driver) < 0)
1540 return -1;
10b0e96e 1541 info("registered");
6a7eba24
JFM
1542 return 0;
1543}
1544static void __exit sd_mod_exit(void)
1545{
1546 usb_deregister(&sd_driver);
1547 info("deregistered");
1548}
1549
1550module_init(sd_mod_init);
1551module_exit(sd_mod_exit);
This page took 0.133848 seconds and 5 git commands to generate.