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