V4L/DVB (8567): gspca: hflip and vflip controls added for ov519 - ov7670 plus init...
[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
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 362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
738608ae 363 /* Outformat = rawRGB */
6a7eba24 364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
738608ae 365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
6a7eba24
JFM
366 /* GAIN BLUE RED VREF */
367 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
368 /* COM 1 BAVE GEAVE AECHH */
369 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
370 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
738608ae 371 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
6a7eba24
JFM
372 /* AECH CLKRC COM7 COM8 */
373 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
374 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
375 /* HSTART HSTOP VSTRT VSTOP */
376 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
377 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
378 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
379 /* BOS GBOS GROS ROS (BGGR offset) */
738608ae
JFM
380/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
381 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
6a7eba24
JFM
382 /* AEW AEB VPT BBIAS */
383 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
384 /* GbBIAS RSVD EXHCH EXHCL */
385 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
386 /* RBIAS ADVFL ASDVFH YAVE */
387 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
388 /* HSYST HSYEN HREF */
389 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
390 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
391 /* ADC ACOM OFON TSLB */
392 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
393 /* COM11 COM12 COM13 COM14 */
394 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
395 /* EDGE COM15 COM16 COM17 */
396 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
397 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
398 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
400 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
401 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
402 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
404 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
406 /* LCC1 LCC2 LCC3 LCC4 */
407 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
738608ae 408 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
6a7eba24 409 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
738608ae 410 /* band gap reference [0:3] DBLV */
6a7eba24
JFM
411 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
412 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
413 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
418 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
419 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
738608ae 420 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
6a7eba24 421/****** (some exchanges in the win trace) ******/
738608ae 422 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
6a7eba24
JFM
423 /* bits[3..0]reserved */
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
426 /* VREF vertical frame ctrl */
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
738608ae
JFM
428 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
429 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
430 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
431 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
432/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
6a7eba24
JFM
433/****** (some exchanges in the win trace) ******/
434 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
738608ae
JFM
435 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
436 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
437 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
438/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
6a7eba24 439/****** (some exchanges in the win trace) ******/
738608ae 440/******!! startsensor KO if changed !!****/
6a7eba24
JFM
441 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
a5ae2062 445 {}
6a7eba24 446};
738608ae
JFM
447/* reg 0x04 reg 0x07 reg 0x10 */
448/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
6a7eba24 449
a5ae2062 450static const __u8 ov7648_sensor_init[][8] = {
6a7eba24
JFM
451 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
452 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
453 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
454 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
455 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
456 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
457 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
458 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
459 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
460 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
461 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
462 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
464 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
465 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
466 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
467 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
468 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
469 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
470 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
471 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
472 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
473 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
474 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
475 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
476 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
477 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
478 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
479 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
480 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
481 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
482 * This is currently setting a
483 * blue tint, and some things more , i leave it here for future test if
484 * somene is having problems with color on this sensor
485 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
486 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
487 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
488 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
489 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
490 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
491 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
492 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
494 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
498 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
499 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
500 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
501 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
502/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
a5ae2062 503 {}
6a7eba24
JFM
504};
505
a5ae2062 506static const __u8 qtable4[] = {
6a7eba24
JFM
507 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
508 0x06, 0x08, 0x0A, 0x11,
509 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
510 0x19, 0x19, 0x17, 0x15,
511 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
512 0x21, 0x2E, 0x21, 0x23,
513 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
514 0x25, 0x29, 0x2C, 0x29,
515 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
516 0x17, 0x1B, 0x29, 0x29,
517 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
518 0x29, 0x29, 0x29, 0x29,
519 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
520 0x29, 0x29, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29
523};
524
739570bb
JFM
525/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
526static void reg_r(struct gspca_dev *gspca_dev,
527 __u16 value, int len)
6a7eba24 528{
739570bb
JFM
529 usb_control_msg(gspca_dev->dev,
530 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
531 0,
532 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
533 value, 0,
739570bb 534 gspca_dev->usb_buf, len,
6a7eba24 535 500);
60017617 536 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
6a7eba24
JFM
537}
538
60017617
JFM
539static void reg_w1(struct gspca_dev *gspca_dev,
540 __u16 value,
541 __u8 data)
542{
543 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
544 gspca_dev->usb_buf[0] = data;
545 usb_control_msg(gspca_dev->dev,
546 usb_sndctrlpipe(gspca_dev->dev, 0),
547 0x08,
548 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
549 value,
550 0,
551 gspca_dev->usb_buf, 1,
552 500);
553}
739570bb 554static void reg_w(struct gspca_dev *gspca_dev,
6a7eba24 555 __u16 value,
bf7f0b98 556 const __u8 *buffer,
6a7eba24
JFM
557 int len)
558{
60017617
JFM
559 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
560 value, buffer[0], buffer[1]);
739570bb
JFM
561 if (len <= sizeof gspca_dev->usb_buf) {
562 memcpy(gspca_dev->usb_buf, buffer, len);
563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062
JFM
565 0x08,
566 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
739570bb 568 gspca_dev->usb_buf, len,
a5ae2062
JFM
569 500);
570 } else {
571 __u8 *tmpbuf;
572
573 tmpbuf = kmalloc(len, GFP_KERNEL);
574 memcpy(tmpbuf, buffer, len);
739570bb
JFM
575 usb_control_msg(gspca_dev->dev,
576 usb_sndctrlpipe(gspca_dev->dev, 0),
a5ae2062
JFM
577 0x08,
578 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
579 value, 0,
580 tmpbuf, len,
581 500);
582 kfree(tmpbuf);
bf7f0b98 583 }
6a7eba24
JFM
584}
585
60017617
JFM
586/* I2C write 1 byte */
587static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
6a7eba24
JFM
588{
589 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 590
60017617
JFM
591 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
592 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
593 gspca_dev->usb_buf[1] = sd->i2c_base;
594 gspca_dev->usb_buf[2] = reg;
595 gspca_dev->usb_buf[3] = val;
596 gspca_dev->usb_buf[4] = 0;
597 gspca_dev->usb_buf[5] = 0;
598 gspca_dev->usb_buf[6] = 0;
599 gspca_dev->usb_buf[7] = 0x10;
600 usb_control_msg(gspca_dev->dev,
601 usb_sndctrlpipe(gspca_dev->dev, 0),
602 0x08,
603 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
604 0x08, /* value = i2c */
605 0,
606 gspca_dev->usb_buf, 8,
607 500);
6a7eba24
JFM
608}
609
739570bb
JFM
610/* I2C write 8 bytes */
611static void i2c_w8(struct gspca_dev *gspca_dev,
612 const __u8 *buffer)
6a7eba24 613{
60017617
JFM
614 memcpy(gspca_dev->usb_buf, buffer, 8);
615 usb_control_msg(gspca_dev->dev,
616 usb_sndctrlpipe(gspca_dev->dev, 0),
617 0x08,
618 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
619 0x08, 0, /* value, index */
620 gspca_dev->usb_buf, 8,
621 500);
6a7eba24
JFM
622}
623
739570bb
JFM
624/* read 5 bytes in gspca_dev->usb_buf */
625static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
6a7eba24
JFM
626{
627 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
628 __u8 mode[8];
629
3647fea8 630 mode[0] = 0x81 | 0x10;
6a7eba24
JFM
631 mode[1] = sd->i2c_base;
632 mode[2] = reg;
633 mode[3] = 0;
634 mode[4] = 0;
635 mode[5] = 0;
636 mode[6] = 0;
637 mode[7] = 0x10;
739570bb 638 i2c_w8(gspca_dev, mode);
60017617 639 msleep(2);
3647fea8 640 mode[0] = 0x81 | (5 << 4) | 0x02;
6a7eba24 641 mode[2] = 0;
739570bb 642 i2c_w8(gspca_dev, mode);
60017617 643 msleep(2);
739570bb 644 reg_r(gspca_dev, 0x0a, 5);
6a7eba24
JFM
645}
646
647static int probesensor(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 650
60017617 651 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
6a7eba24 652 msleep(10);
60017617 653 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
6a7eba24 654 msleep(10);
739570bb
JFM
655 i2c_r5(gspca_dev, 0); /* read sensor id */
656 if (gspca_dev->usb_buf[0] == 0x02
657 && gspca_dev->usb_buf[1] == 0x09
658 && gspca_dev->usb_buf[2] == 0x01
659 && gspca_dev->usb_buf[3] == 0x00
660 && gspca_dev->usb_buf[4] == 0x00) {
6a7eba24
JFM
661 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
662 sd->sensor = SENSOR_HV7131R;
663 return SENSOR_HV7131R;
664 }
60017617 665 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
739570bb
JFM
666 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
667 gspca_dev->usb_buf[2]);
6a7eba24
JFM
668 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
669 return -ENODEV;
670}
671
672static int configure_gpio(struct gspca_dev *gspca_dev,
a5ae2062 673 const __u8 *sn9c1xx)
6a7eba24
JFM
674{
675 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062
JFM
676 const __u8 *reg9a;
677 static const __u8 reg9a_def[] =
6a7eba24 678 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
a5ae2062 679 static const __u8 reg9a_sn9c120[] = /* from win trace */
6a7eba24 680 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
a5ae2062 681 static const __u8 reg9a_sn9c325[] =
6a7eba24
JFM
682 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
683
60017617
JFM
684 reg_w1(gspca_dev, 0xf1, 0x00);
685 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
6a7eba24
JFM
686
687 /* configure gpio */
739570bb
JFM
688 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
689 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
60017617 690 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
3647fea8
HG
691 switch (sd->bridge) {
692 case BRIDGE_SN9C325:
6a7eba24
JFM
693 reg9a = reg9a_sn9c325;
694 break;
3647fea8 695 case BRIDGE_SN9C120:
6a7eba24
JFM
696 reg9a = reg9a_sn9c120;
697 break;
698 default:
699 reg9a = reg9a_def;
700 break;
701 }
739570bb 702 reg_w(gspca_dev, 0x9a, reg9a, 6);
6a7eba24 703
60017617 704 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
6a7eba24 705
739570bb 706 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
6a7eba24 707
3647fea8
HG
708 switch (sd->bridge) {
709 case BRIDGE_SN9C120: /* from win trace */
60017617
JFM
710 reg_w1(gspca_dev, 0x01, 0x61);
711 reg_w1(gspca_dev, 0x17, 0x20);
712 reg_w1(gspca_dev, 0x01, 0x60);
6a7eba24 713 break;
3647fea8 714 case BRIDGE_SN9C325:
60017617
JFM
715 reg_w1(gspca_dev, 0x01, 0x43);
716 reg_w1(gspca_dev, 0x17, 0xae);
717 reg_w1(gspca_dev, 0x01, 0x42);
6a7eba24
JFM
718 break;
719 default:
60017617
JFM
720 reg_w1(gspca_dev, 0x01, 0x43);
721 reg_w1(gspca_dev, 0x17, 0x61);
722 reg_w1(gspca_dev, 0x01, 0x42);
6a7eba24
JFM
723 }
724
725 if (sd->sensor == SENSOR_HV7131R) {
726 if (probesensor(gspca_dev) < 0)
727 return -ENODEV;
728 }
729 return 0;
730}
731
732static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
733{
734 int i = 0;
a5ae2062 735 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
6a7eba24
JFM
736 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
737
738 while (hv7131r_sensor_init[i][0]) {
739570bb 739 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
6a7eba24
JFM
740 i++;
741 }
739570bb 742 i2c_w8(gspca_dev, SetSensorClk);
6a7eba24
JFM
743}
744
745static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
746{
747 int i = 0;
6a7eba24
JFM
748
749 while (mi0360_sensor_init[i][0]) {
739570bb 750 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
6a7eba24
JFM
751 i++;
752 }
753}
754
755static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
756{
757 int i = 0;
6a7eba24
JFM
758
759 while (mo4000_sensor_init[i][0]) {
739570bb 760 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
6a7eba24
JFM
761 i++;
762 }
763}
764
765static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
766{
6a7eba24
JFM
767 int i = 0;
768
769 while (ov7648_sensor_init[i][0]) {
739570bb 770 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
6a7eba24
JFM
771 i++;
772 }
773}
774
775static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
776{
777 int i = 0;
6a7eba24 778
60017617
JFM
779 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
780 i++;
781 msleep(20);
6a7eba24 782 while (ov7660_sensor_init[i][0]) {
739570bb 783 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
6a7eba24
JFM
784 i++;
785 }
786}
787
788/* this function is called at probe time */
789static int sd_config(struct gspca_dev *gspca_dev,
790 const struct usb_device_id *id)
791{
792 struct sd *sd = (struct sd *) gspca_dev;
793 struct cam *cam;
6a7eba24
JFM
794
795 cam = &gspca_dev->cam;
6a7eba24
JFM
796 cam->epaddr = 0x01;
797 cam->cam_mode = vga_mode;
798 cam->nmodes = ARRAY_SIZE(vga_mode);
a5ae2062 799
9d64fdb1
JFM
800 sd->bridge = id->driver_info >> 16;
801 sd->sensor = id->driver_info >> 8;
802 sd->i2c_base = id->driver_info;
803
6a7eba24 804 sd->qindex = 4; /* set the quantization table */
a5ae2062
JFM
805 sd->brightness = BRIGHTNESS_DEF;
806 sd->contrast = CONTRAST_DEF;
807 sd->colors = COLOR_DEF;
808 sd->autogain = AUTOGAIN_DEF;
6a7eba24
JFM
809 return 0;
810}
811
812/* this function is called at open time */
813static int sd_open(struct gspca_dev *gspca_dev)
814{
815 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 816/* const __u8 *sn9c1xx; */
6a7eba24 817 __u8 regGpio[] = { 0x29, 0x74 };
60017617 818 __u8 regF1;
6a7eba24 819
3647fea8 820 /* setup a selector by bridge */
60017617 821 reg_w1(gspca_dev, 0xf1, 0x01);
739570bb 822 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
60017617 823 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
739570bb
JFM
824 reg_r(gspca_dev, 0x00, 1);
825 regF1 = gspca_dev->usb_buf[0];
3647fea8
HG
826 switch (sd->bridge) {
827 case BRIDGE_SN9C102P:
6a7eba24
JFM
828 if (regF1 != 0x11)
829 return -ENODEV;
60017617 830 reg_w1(gspca_dev, 0x02, regGpio[1]);
6a7eba24 831 break;
3647fea8 832 case BRIDGE_SN9C105:
6a7eba24
JFM
833 if (regF1 != 0x11)
834 return -ENODEV;
739570bb 835 reg_w(gspca_dev, 0x02, regGpio, 2);
6a7eba24 836 break;
3647fea8 837 case BRIDGE_SN9C120:
6a7eba24
JFM
838 if (regF1 != 0x12)
839 return -ENODEV;
840 regGpio[1] = 0x70;
739570bb 841 reg_w(gspca_dev, 0x02, regGpio, 2);
6a7eba24
JFM
842 break;
843 default:
60017617 844/* case BRIDGE_SN9C110: */
3647fea8 845/* case BRIDGE_SN9C325: */
6a7eba24
JFM
846 if (regF1 != 0x12)
847 return -ENODEV;
60017617 848 reg_w1(gspca_dev, 0x02, 0x62);
6a7eba24
JFM
849 break;
850 }
851
60017617 852 reg_w1(gspca_dev, 0xf1, 0x01);
6a7eba24
JFM
853
854 return 0;
855}
856
857static unsigned int setexposure(struct gspca_dev *gspca_dev,
858 unsigned int expo)
859{
860 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 861 static const __u8 doit[] = /* update sensor */
6a7eba24 862 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
a5ae2062 863 static const __u8 sensorgo[] = /* sensor on */
6a7eba24 864 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
a5ae2062 865 static const __u8 gainMo[] =
6a7eba24
JFM
866 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
867
868 switch (sd->sensor) {
869 case SENSOR_HV7131R: {
870 __u8 Expodoit[] =
871 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
872
873 Expodoit[3] = expo >> 16;
874 Expodoit[4] = expo >> 8;
875 Expodoit[5] = expo;
739570bb 876 i2c_w8(gspca_dev, Expodoit);
6a7eba24
JFM
877 break;
878 }
879 case SENSOR_MI0360: {
880 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
881 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
882
883 if (expo > 0x0635)
884 expo = 0x0635;
885 else if (expo < 0x0001)
886 expo = 0x0001;
887 expoMi[3] = expo >> 8;
888 expoMi[4] = expo;
739570bb
JFM
889 i2c_w8(gspca_dev, expoMi);
890 i2c_w8(gspca_dev, doit);
891 i2c_w8(gspca_dev, sensorgo);
6a7eba24
JFM
892 break;
893 }
894 case SENSOR_MO4000: {
895 __u8 expoMof[] =
896 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
897 __u8 expoMo10[] =
898 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
899
900 if (expo > 0x1fff)
901 expo = 0x1fff;
902 else if (expo < 0x0001)
903 expo = 0x0001;
904 expoMof[3] = (expo & 0x03fc) >> 2;
739570bb 905 i2c_w8(gspca_dev, expoMof);
6a7eba24
JFM
906 expoMo10[3] = ((expo & 0x1c00) >> 10)
907 | ((expo & 0x0003) << 4);
739570bb
JFM
908 i2c_w8(gspca_dev, expoMo10);
909 i2c_w8(gspca_dev, gainMo);
956e42d2 910 PDEBUG(D_CONF, "set exposure %d",
6a7eba24
JFM
911 ((expoMo10[3] & 0x07) << 10)
912 | (expoMof[3] << 2)
913 | ((expoMo10[3] & 0x30) >> 4));
914 break;
915 }
916 }
917 return expo;
918}
919
920static void setbrightness(struct gspca_dev *gspca_dev)
921{
922 struct sd *sd = (struct sd *) gspca_dev;
923 unsigned int expo;
924 __u8 k2;
925
926 switch (sd->sensor) {
927 case SENSOR_HV7131R:
928 expo = sd->brightness << 4;
929 if (expo > 0x002dc6c0)
930 expo = 0x002dc6c0;
931 else if (expo < 0x02a0)
932 expo = 0x02a0;
933 sd->exposure = setexposure(gspca_dev, expo);
934 break;
935 case SENSOR_MI0360:
936 expo = sd->brightness >> 4;
937 sd->exposure = setexposure(gspca_dev, expo);
938 break;
939 case SENSOR_MO4000:
940 expo = sd->brightness >> 4;
941 sd->exposure = setexposure(gspca_dev, expo);
942 break;
943 case SENSOR_OV7660:
944 return; /*jfm??*/
945 }
946
947 k2 = sd->brightness >> 10;
60017617 948 reg_w1(gspca_dev, 0x96, k2);
6a7eba24
JFM
949}
950
951static void setcontrast(struct gspca_dev *gspca_dev)
952{
953 struct sd *sd = (struct sd *) gspca_dev;
954 __u8 k2;
955 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
956
957 if (sd->sensor == SENSOR_OV7660)
958 return; /*jfm??*/
959 k2 = sd->contrast;
960 contrast[2] = k2;
961 contrast[0] = (k2 + 1) >> 1;
962 contrast[4] = (k2 + 1) / 5;
739570bb 963 reg_w(gspca_dev, 0x84, contrast, 6);
6a7eba24
JFM
964}
965
966static void setcolors(struct gspca_dev *gspca_dev)
967{
968 struct sd *sd = (struct sd *) gspca_dev;
969 __u8 data;
970 int colour;
971
972 colour = sd->colors - 128;
973 if (colour > 0)
974 data = (colour + 32) & 0x7f; /* blue */
975 else
976 data = (-colour + 32) & 0x7f; /* red */
60017617 977 reg_w1(gspca_dev, 0x05, data);
6a7eba24
JFM
978}
979
980/* -- start the camera -- */
981static void sd_start(struct gspca_dev *gspca_dev)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
984 int i;
985 __u8 data;
986 __u8 reg1;
987 __u8 reg17;
a5ae2062 988 const __u8 *sn9c1xx;
6a7eba24 989 int mode;
a5ae2062
JFM
990 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
991 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
992 static const __u8 CA_sn9c120[] =
993 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
994 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
995 static const __u8 CE_sn9c325[] =
6a7eba24
JFM
996 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
997
998 sn9c1xx = sn_tb[(int) sd->sensor];
999 configure_gpio(gspca_dev, sn9c1xx);
1000
1001/*fixme:jfm this sequence should appear at end of sd_start */
1002/* with
60017617
JFM
1003 reg_w1(gspca_dev, 0x01, 0x44); */
1004 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1005 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1006 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1007 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1008 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1009 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1010 reg_w1(gspca_dev, 0xd3, 0x50);
1011 reg_w1(gspca_dev, 0xc6, 0x00);
1012 reg_w1(gspca_dev, 0xc7, 0x00);
1013 reg_w1(gspca_dev, 0xc8, 0x50);
1014 reg_w1(gspca_dev, 0xc9, 0x3c);
6a7eba24 1015/*fixme:jfm end of ending sequence */
60017617 1016 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
568788a7
JFM
1017 switch (sd->bridge) {
1018 case BRIDGE_SN9C325:
6a7eba24 1019 data = 0xae;
568788a7
JFM
1020 break;
1021 case BRIDGE_SN9C120:
1022 data = 0xa0;
1023 break;
1024 default:
6a7eba24 1025 data = 0x60;
568788a7
JFM
1026 break;
1027 }
60017617
JFM
1028 reg_w1(gspca_dev, 0x17, data);
1029 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1030 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1031 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1032 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
568788a7
JFM
1033 switch (sd->bridge) {
1034 case BRIDGE_SN9C325:
1035 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1036 sizeof regsn20_sn9c325);
6a7eba24 1037 for (i = 0; i < 8; i++)
568788a7
JFM
1038 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1039 sizeof reg84_sn9c325);
60017617
JFM
1040 reg_w1(gspca_dev, 0x9a, 0x0a);
1041 reg_w1(gspca_dev, 0x99, 0x60);
568788a7
JFM
1042 break;
1043 case BRIDGE_SN9C120:
1044 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1045 sizeof regsn20_sn9c120);
1046 for (i = 0; i < 2; i++)
1047 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1048 sizeof reg84_sn9c120_1);
1049 for (i = 0; i < 6; i++)
1050 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1051 sizeof reg84_sn9c120_2);
1052 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1053 sizeof reg84_sn9c120_3);
60017617
JFM
1054 reg_w1(gspca_dev, 0x9a, 0x05);
1055 reg_w1(gspca_dev, 0x99, 0x5b);
568788a7
JFM
1056 break;
1057 default:
1058 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
6a7eba24 1059 for (i = 0; i < 8; i++)
568788a7 1060 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
60017617
JFM
1061 reg_w1(gspca_dev, 0x9a, 0x08);
1062 reg_w1(gspca_dev, 0x99, 0x59);
568788a7 1063 break;
6a7eba24
JFM
1064 }
1065
c2446b3e 1066 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
60017617
JFM
1067 if (mode)
1068 reg1 = 0x46; /* 320 clk 48Mhz */
1069 else
1070 reg1 = 0x06; /* 640 clk 24Mz */
6a7eba24
JFM
1071 reg17 = 0x61;
1072 switch (sd->sensor) {
1073 case SENSOR_HV7131R:
1074 hv7131R_InitSensor(gspca_dev);
6a7eba24
JFM
1075 break;
1076 case SENSOR_MI0360:
1077 mi0360_InitSensor(gspca_dev);
6a7eba24
JFM
1078 break;
1079 case SENSOR_MO4000:
1080 mo4000_InitSensor(gspca_dev);
1081 if (mode) {
1082/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1083 reg1 = 0x06; /* clk 24Mz */
1084 } else {
1085 reg17 = 0x22; /* 640 MCKSIZE */
60017617 1086/* reg1 = 0x06; * 640 clk 24Mz (done) */
6a7eba24
JFM
1087 }
1088 break;
1089 case SENSOR_OV7648:
60017617 1090 ov7648_InitSensor(gspca_dev);
6a7eba24
JFM
1091 reg17 = 0xa2;
1092 reg1 = 0x44;
6a7eba24
JFM
1093/* if (mode)
1094 ; * 320x2...
1095 else
1096 ; * 640x... */
1097 break;
1098 default:
1099/* case SENSOR_OV7660: */
1100 ov7660_InitSensor(gspca_dev);
1101 if (mode) {
1102/* reg17 = 0x21; * 320 */
1103/* reg1 = 0x44; */
60017617 1104/* reg1 = 0x46; (done) */
6a7eba24
JFM
1105 } else {
1106 reg17 = 0xa2; /* 640 */
1107 reg1 = 0x40;
1108 }
1109 break;
1110 }
739570bb 1111 reg_w(gspca_dev, 0xc0, C0, 6);
3647fea8
HG
1112 switch (sd->bridge) {
1113 case BRIDGE_SN9C120: /*jfm ?? */
739570bb 1114 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
6a7eba24
JFM
1115 break;
1116 default:
739570bb 1117 reg_w(gspca_dev, 0xca, CA, 4);
6a7eba24
JFM
1118 break;
1119 }
3647fea8
HG
1120 switch (sd->bridge) {
1121 case BRIDGE_SN9C120: /*jfm ?? */
1122 case BRIDGE_SN9C325:
739570bb 1123 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
6a7eba24
JFM
1124 break;
1125 default:
739570bb 1126 reg_w(gspca_dev, 0xce, CE, 4);
6a7eba24
JFM
1127 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1128 break;
1129 }
1130
1131 /* here change size mode 0 -> VGA; 1 -> CIF */
1132 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
60017617 1133 reg_w1(gspca_dev, 0x18, data);
6a7eba24 1134
739570bb
JFM
1135 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1136 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
6a7eba24
JFM
1137
1138 data = sn9c1xx[0x18] | (mode << 4);
60017617 1139 reg_w1(gspca_dev, 0x18, data);
6a7eba24 1140
60017617
JFM
1141 reg_w1(gspca_dev, 0x17, reg17);
1142 reg_w1(gspca_dev, 0x01, reg1);
6a7eba24
JFM
1143 setbrightness(gspca_dev);
1144 setcontrast(gspca_dev);
1145}
1146
1147static void sd_stopN(struct gspca_dev *gspca_dev)
1148{
1149 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1150 static const __u8 stophv7131[] =
6a7eba24 1151 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
a5ae2062 1152 static const __u8 stopmi0360[] =
6a7eba24 1153 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
6a7eba24 1154 __u8 data;
a5ae2062 1155 const __u8 *sn9c1xx;
6a7eba24
JFM
1156
1157 data = 0x0b;
1158 switch (sd->sensor) {
1159 case SENSOR_HV7131R:
739570bb 1160 i2c_w8(gspca_dev, stophv7131);
6a7eba24
JFM
1161 data = 0x2b;
1162 break;
1163 case SENSOR_MI0360:
739570bb 1164 i2c_w8(gspca_dev, stopmi0360);
6a7eba24
JFM
1165 data = 0x29;
1166 break;
1167 case SENSOR_MO4000:
1168 break;
1169 case SENSOR_OV7648:
1170 data = 0x29;
1171 break;
1172 default:
1173/* case SENSOR_OV7660: */
1174 break;
1175 }
1176 sn9c1xx = sn_tb[(int) sd->sensor];
60017617
JFM
1177 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1178 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1179 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1180 reg_w1(gspca_dev, 0x01, data);
1181 reg_w1(gspca_dev, 0xf1, 0x01);
6a7eba24
JFM
1182}
1183
1184static void sd_stop0(struct gspca_dev *gspca_dev)
1185{
1186}
1187
1188static void sd_close(struct gspca_dev *gspca_dev)
1189{
1190}
1191
1192static void setautogain(struct gspca_dev *gspca_dev)
1193{
1194 struct sd *sd = (struct sd *) gspca_dev;
1195 /* Thanks S., without your advice, autobright should not work :) */
1196 int delta;
1197 int expotimes = 0;
1198 __u8 luma_mean = 130;
1199 __u8 luma_delta = 20;
1200
1201 delta = sd->avg_lum;
1202 if (delta < luma_mean - luma_delta ||
1203 delta > luma_mean + luma_delta) {
1204 switch (sd->sensor) {
1205 case SENSOR_HV7131R:
1206 expotimes = sd->exposure >> 8;
1207 expotimes += (luma_mean - delta) >> 4;
1208 if (expotimes < 0)
1209 expotimes = 0;
1210 sd->exposure = setexposure(gspca_dev,
1211 (unsigned int) (expotimes << 8));
1212 break;
1213 case SENSOR_MO4000:
1214 case SENSOR_MI0360:
1215 expotimes = sd->exposure;
1216 expotimes += (luma_mean - delta) >> 6;
1217 if (expotimes < 0)
1218 expotimes = 0;
1219 sd->exposure = setexposure(gspca_dev,
1220 (unsigned int) expotimes);
1221 setcolors(gspca_dev);
1222 break;
1223 }
1224 }
1225}
1226
1227static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1228 struct gspca_frame *frame, /* target */
a5ae2062 1229 __u8 *data, /* isoc packet */
6a7eba24
JFM
1230 int len) /* iso packet length */
1231{
1232 struct sd *sd = (struct sd *) gspca_dev;
1233 int sof, avg_lum;
1234
1235 sof = len - 64;
1236 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1237
1238 /* end of frame */
1239 gspca_frame_add(gspca_dev, LAST_PACKET,
1240 frame, data, sof + 2);
1241 if (sd->ag_cnt < 0)
1242 return;
1243 if (--sd->ag_cnt >= 0)
1244 return;
1245 sd->ag_cnt = AG_CNT_START;
1246/* w1 w2 w3 */
1247/* w4 w5 w6 */
1248/* w7 w8 */
1249/* w4 */
1250 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1251/* w6 */
1252 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1253/* w2 */
1254 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1255/* w8 */
1256 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1257/* w5 */
1258 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1259 avg_lum >>= 4;
1260 sd->avg_lum = avg_lum;
1261 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1262 setautogain(gspca_dev);
1263 return;
1264 }
1265 if (gspca_dev->last_packet_type == LAST_PACKET) {
1266
1267 /* put the JPEG 422 header */
1268 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1269 }
1270 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1271}
1272
1273static unsigned int getexposure(struct gspca_dev *gspca_dev)
1274{
1275 struct sd *sd = (struct sd *) gspca_dev;
1276 __u8 hexpo, mexpo, lexpo;
6a7eba24
JFM
1277
1278 switch (sd->sensor) {
1279 case SENSOR_HV7131R:
1280 /* read sensor exposure */
739570bb
JFM
1281 i2c_r5(gspca_dev, 0x25);
1282 return (gspca_dev->usb_buf[0] << 16)
1283 | (gspca_dev->usb_buf[1] << 8)
1284 | gspca_dev->usb_buf[2];
6a7eba24
JFM
1285 case SENSOR_MI0360:
1286 /* read sensor exposure */
739570bb
JFM
1287 i2c_r5(gspca_dev, 0x09);
1288 return (gspca_dev->usb_buf[0] << 8)
1289 | gspca_dev->usb_buf[1];
6a7eba24 1290 case SENSOR_MO4000:
739570bb
JFM
1291 i2c_r5(gspca_dev, 0x0e);
1292 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1293 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1294 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
6a7eba24
JFM
1295 PDEBUG(D_CONF, "exposure %d",
1296 (hexpo << 10) | (mexpo << 2) | lexpo);
1297 return (hexpo << 10) | (mexpo << 2) | lexpo;
1298 default:
1299/* case SENSOR_OV7660: */
1300 /* read sensor exposure */
739570bb
JFM
1301 i2c_r5(gspca_dev, 0x04);
1302 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1303 lexpo = gspca_dev->usb_buf[0] & 0x02;
1304 i2c_r5(gspca_dev, 0x08);
1305 mexpo = gspca_dev->usb_buf[2];
6a7eba24
JFM
1306 return (hexpo << 10) | (mexpo << 2) | lexpo;
1307 }
1308}
1309
1310static void getbrightness(struct gspca_dev *gspca_dev)
1311{
1312 struct sd *sd = (struct sd *) gspca_dev;
1313
1314 /* hardcoded registers seem not readable */
1315 switch (sd->sensor) {
1316 case SENSOR_HV7131R:
1317/* sd->brightness = 0x7fff; */
1318 sd->brightness = getexposure(gspca_dev) >> 4;
1319 break;
1320 case SENSOR_MI0360:
1321 sd->brightness = getexposure(gspca_dev) << 4;
1322 break;
1323 case SENSOR_MO4000:
1324/* sd->brightness = 0x1fff; */
1325 sd->brightness = getexposure(gspca_dev) << 4;
1326 break;
1327 }
1328}
1329
1330static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 sd->brightness = val;
1335 if (gspca_dev->streaming)
1336 setbrightness(gspca_dev);
1337 return 0;
1338}
1339
1340static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343
1344 getbrightness(gspca_dev);
1345 *val = sd->brightness;
1346 return 0;
1347}
1348
1349static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1350{
1351 struct sd *sd = (struct sd *) gspca_dev;
1352
1353 sd->contrast = val;
1354 if (gspca_dev->streaming)
1355 setcontrast(gspca_dev);
1356 return 0;
1357}
1358
1359static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1360{
1361 struct sd *sd = (struct sd *) gspca_dev;
1362
1363 *val = sd->contrast;
1364 return 0;
1365}
1366
1367static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1368{
1369 struct sd *sd = (struct sd *) gspca_dev;
1370
1371 sd->colors = val;
1372 if (gspca_dev->streaming)
1373 setcolors(gspca_dev);
1374 return 0;
1375}
1376
1377static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1378{
1379 struct sd *sd = (struct sd *) gspca_dev;
1380
1381 *val = sd->colors;
1382 return 0;
1383}
1384
1385static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388
1389 sd->autogain = val;
1390 if (val)
1391 sd->ag_cnt = AG_CNT_START;
1392 else
1393 sd->ag_cnt = -1;
1394 return 0;
1395}
1396
1397static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400
1401 *val = sd->autogain;
1402 return 0;
1403}
1404
1405/* sub-driver description */
a5ae2062 1406static const struct sd_desc sd_desc = {
6a7eba24
JFM
1407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1411 .open = sd_open,
1412 .start = sd_start,
1413 .stopN = sd_stopN,
1414 .stop0 = sd_stop0,
1415 .close = sd_close,
1416 .pkt_scan = sd_pkt_scan,
1417};
1418
1419/* -- module initialisation -- */
9d64fdb1
JFM
1420#define BSI(bridge, sensor, i2c_addr) \
1421 .driver_info = (BRIDGE_ ## bridge << 16) \
1422 | (SENSOR_ ## sensor << 8) \
1423 | (i2c_addr)
a5ae2062 1424static const __devinitdata struct usb_device_id device_table[] = {
c41492c8 1425#ifndef CONFIG_USB_SN9C102
9d64fdb1
JFM
1426 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1427 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1428 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1429 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1430 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
c41492c8 1431#endif
9d64fdb1
JFM
1432 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1433 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1434/* bw600.inf:
1435 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1436/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1437/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1438 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1439/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1440 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1441/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1442/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1443 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1444/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1445/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1446 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1447 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1448/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1449/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1450/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1451/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1452 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1453/* bw600.inf:
1454 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1455 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1456/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1457/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
c41492c8 1458#ifndef CONFIG_USB_SN9C102
9d64fdb1
JFM
1459 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1460 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1461/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1462 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1463 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1464/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
c41492c8 1465#endif
e546f4bb 1466 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
6a7eba24
JFM
1467 {}
1468};
1469MODULE_DEVICE_TABLE(usb, device_table);
1470
1471/* -- device connect -- */
1472static int sd_probe(struct usb_interface *intf,
1473 const struct usb_device_id *id)
1474{
1475 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1476 THIS_MODULE);
1477}
1478
1479static struct usb_driver sd_driver = {
1480 .name = MODULE_NAME,
1481 .id_table = device_table,
1482 .probe = sd_probe,
1483 .disconnect = gspca_disconnect,
1484};
1485
1486/* -- module insert / remove -- */
1487static int __init sd_mod_init(void)
1488{
1489 if (usb_register(&sd_driver) < 0)
1490 return -1;
10b0e96e 1491 info("registered");
6a7eba24
JFM
1492 return 0;
1493}
1494static void __exit sd_mod_exit(void)
1495{
1496 usb_deregister(&sd_driver);
1497 info("deregistered");
1498}
1499
1500module_init(sd_mod_init);
1501module_exit(sd_mod_exit);
This page took 0.110464 seconds and 5 git commands to generate.