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