blob: 572b0f363b640ccb407b7d312716c75c4da85e95 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -030035 atomic_t avg_lum;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 unsigned int exposure;
37
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 signed char ag_cnt;
44#define AG_CNT_START 13
45
46 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030047 unsigned char bridge;
48#define BRIDGE_SN9C102P 0
49#define BRIDGE_SN9C105 1
50#define BRIDGE_SN9C110 2
51#define BRIDGE_SN9C120 3
52#define BRIDGE_SN9C325 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_MI0360 1
56#define SENSOR_MO4000 2
Jean-Francois Moined2d16e92008-09-03 16:47:23 -030057#define SENSOR_OM6802 3
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -030058#define SENSOR_OV7630 4
59#define SENSOR_OV7648 5
60#define SENSOR_OV7660 6
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030061 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030062};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
73
74static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030075 {
76 {
77 .id = V4L2_CID_BRIGHTNESS,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Brightness",
80 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -030081#define BRIGHTNESS_MAX 0xffff
82 .maximum = BRIGHTNESS_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030084#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030090 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -030096#define CONTRAST_MAX 127
97 .maximum = CONTRAST_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030098 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030099#define CONTRAST_DEF 63
100 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 },
102 .set = sd_setcontrast,
103 .get = sd_getcontrast,
104 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 {
106 {
107 .id = V4L2_CID_SATURATION,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Color",
110 .minimum = 0,
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -0300111 .maximum = 64,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300112 .step = 1,
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -0300113#define COLOR_DEF 32
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300114 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 },
116 .set = sd_setcolors,
117 .get = sd_getcolors,
118 },
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -0300119#define AUTOGAIN_IDX 3
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300120 {
121 {
122 .id = V4L2_CID_AUTOGAIN,
123 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 .name = "Auto Gain",
125 .minimum = 0,
126 .maximum = 1,
127 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300128#define AUTOGAIN_DEF 1
129 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 },
131 .set = sd_setautogain,
132 .get = sd_getautogain,
133 },
134};
135
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300136static struct v4l2_pix_format vga_mode[] = {
137 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300139 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 2},
142 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 320,
144 .sizeimage = 320 * 240 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 1},
147 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .bytesperline = 640,
149 .sizeimage = 640 * 480 * 3 / 8 + 590,
150 .colorspace = V4L2_COLORSPACE_JPEG,
151 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152};
153
154/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300155static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300156/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
157 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
158/* reg8 reg9 rega regb regc regd rege regf */
159 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
160/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
161 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
162/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
163 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300164};
165
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300166static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300167/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
168 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
169/* reg8 reg9 rega regb regc regd rege regf */
170 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
171/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
172 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
173/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
174 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175};
176
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300177static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300178/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
179 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
180/* reg8 reg9 rega regb regc regd rege regf */
181 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
183 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
184/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
185 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300186};
187
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300188static const __u8 sn_om6802[] = {
189/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
190 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
191/* reg8 reg9 rega regb regc regd rege regf */
192 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
194 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
195/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
196 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
198 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
199 0xf7
200};
201
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300202static const __u8 sn_ov7630[] = {
203/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
204 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
205/* reg8 reg9 rega regb regc regd rege regf */
206 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
207/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
208 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
209/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
210 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
211};
212
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300213static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300214/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
215 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
216/* reg8 reg9 rega regb regc regd rege regf */
217 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
218/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
219 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
220/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
221 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300222};
223
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300224static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300225/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
226 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
227/* reg8 reg9 rega regb regc regd rege regf */
228 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
229/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
230 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
231/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
232 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300233};
234
235/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300236static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300237 sn_hv7131,
238 sn_mi0360,
239 sn_mo4000,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300240 sn_om6802,
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300241 sn_ov7630,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300242 sn_ov7648,
243 sn_ov7660
244};
245
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300246static const __u8 gamma_def[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300247 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
248 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
249};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300250
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300251static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
253 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300254 0xf7, 0x0f, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300255};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300256static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300257 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
258 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
260 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
262 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
263 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
264
265 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
266 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
268 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
269 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
270 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
271 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
272 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
273
274 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
279
280 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
283 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300285 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300287static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300288 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
290 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
292 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
293 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
294 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
305 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
308 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
310 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
311 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
313 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
315 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
317 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
318 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
319 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
320 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
321
322 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
323 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
324 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
325 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
326 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
327
328 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
329 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
330 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
331 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
332
333 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
334 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
335/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
336/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
337 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
338 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300339 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300341static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
360 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
361 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300362 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363};
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300364static __u8 om6802_sensor_init[][8] = {
365 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
366 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
367 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
368 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
369/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
370 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
371 /* white balance & auto-exposure */
372/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
373 * set color mode */
374/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
375 * max AGC value in AE */
376/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
377 * preset AGC */
378/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
379 * preset brightness */
380/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
381 * preset contrast */
382/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
383 * preset gamma */
384 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
385 /* luminance mode (0x4f = AE) */
386 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
387 /* preset shutter */
388/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
389 * auto frame rate */
390/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
391
392/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
393/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
394/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
395/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
396 {}
397};
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300398static const __u8 ov7630_sensor_init[][8] = {
399 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
400 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
401/* win: delay 20ms */
402 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
403 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
404/* win: delay 20ms */
405 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300406/* win: i2c_r from 00 to 80 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300407 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
408 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
409 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
410 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
411 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
412 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
413 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
414 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
415 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
416 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
417 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
418 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
422 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
423 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
424 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
425 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
426 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
427 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
428 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
429 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
430 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
431 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
432 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
433/* */
434 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
436/*fixme: + 0x12, 0x04*/
437 {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
438 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
439 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300441/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300442 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300445/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300446 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300447/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300448 {}
449};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300450static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300452/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300454 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300456 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 /* GAIN BLUE RED VREF */
458 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
459 /* COM 1 BAVE GEAVE AECHH */
460 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
461 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300462 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 /* AECH CLKRC COM7 COM8 */
464 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
465 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
466 /* HSTART HSTOP VSTRT VSTOP */
467 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
468 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
469 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
470 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300471/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
472 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473 /* AEW AEB VPT BBIAS */
474 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
475 /* GbBIAS RSVD EXHCH EXHCL */
476 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
477 /* RBIAS ADVFL ASDVFH YAVE */
478 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
479 /* HSYST HSYEN HREF */
480 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
481 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
482 /* ADC ACOM OFON TSLB */
483 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
484 /* COM11 COM12 COM13 COM14 */
485 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
486 /* EDGE COM15 COM16 COM17 */
487 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
488 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
489 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
490 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
491 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
492 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
493 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
494 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
495 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
496 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
497 /* LCC1 LCC2 LCC3 LCC4 */
498 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300499 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300501 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300502 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
503 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
504 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
505 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
506 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
507 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
508 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
509 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
510 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300511 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300513 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514 /* bits[3..0]reserved */
515 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
516 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
517 /* VREF vertical frame ctrl */
518 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300519 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
520 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
521 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
522 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
523/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524/****** (some exchanges in the win trace) ******/
525 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300526 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
527 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
528 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
529/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300531/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
533 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
534 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
535 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300536 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300538/* reg 0x04 reg 0x07 reg 0x10 */
539/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300541static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
543 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
544 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
545 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
546 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
547 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
548 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
549 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
550 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
551 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
552 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
553 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
554 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
555 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
556 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
557 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
558 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
559 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
560 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
561 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
562 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
563 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
564 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
565 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
566 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
567 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
568 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
569 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
570 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
571 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
572 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
573 * This is currently setting a
574 * blue tint, and some things more , i leave it here for future test if
575 * somene is having problems with color on this sensor
576 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
577 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
578 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
579 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
580 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
581 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
582 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
583 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
584 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
585 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
586 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
587 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
588 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
589 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
590 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
591 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
592 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
593/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300594 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595};
596
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300597static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
599 0x06, 0x08, 0x0A, 0x11,
600 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
601 0x19, 0x19, 0x17, 0x15,
602 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
603 0x21, 0x2E, 0x21, 0x23,
604 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
605 0x25, 0x29, 0x2C, 0x29,
606 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
607 0x17, 0x1B, 0x29, 0x29,
608 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
609 0x29, 0x29, 0x29, 0x29,
610 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
611 0x29, 0x29, 0x29, 0x29,
612 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
613 0x29, 0x29, 0x29, 0x29
614};
615
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300616/* read <len> bytes to gspca_dev->usb_buf */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617static void reg_r(struct gspca_dev *gspca_dev,
618 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300620#ifdef GSPCA_DEBUG
621 if (len > USB_BUF_SZ) {
622 err("reg_r: buffer overflow");
623 return;
624 }
625#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 usb_control_msg(gspca_dev->dev,
627 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 0,
629 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
630 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300631 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300633 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634}
635
Jean-Francois Moine60017612008-07-18 08:46:19 -0300636static void reg_w1(struct gspca_dev *gspca_dev,
637 __u16 value,
638 __u8 data)
639{
640 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
641 gspca_dev->usb_buf[0] = data;
642 usb_control_msg(gspca_dev->dev,
643 usb_sndctrlpipe(gspca_dev->dev, 0),
644 0x08,
645 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
646 value,
647 0,
648 gspca_dev->usb_buf, 1,
649 500);
650}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300653 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 int len)
655{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300656 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
657 value, buffer[0], buffer[1]);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300658#ifdef GSPCA_DEBUG
659 if (len > USB_BUF_SZ) {
660 err("reg_w: buffer overflow");
661 return;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300662 }
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300663#endif
664 memcpy(gspca_dev->usb_buf, buffer, len);
665 usb_control_msg(gspca_dev->dev,
666 usb_sndctrlpipe(gspca_dev->dev, 0),
667 0x08,
668 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
669 value, 0,
670 gspca_dev->usb_buf, len,
671 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672}
673
Jean-Francois Moine60017612008-07-18 08:46:19 -0300674/* I2C write 1 byte */
675static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676{
677 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678
Jean-Francois Moine60017612008-07-18 08:46:19 -0300679 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
680 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
681 gspca_dev->usb_buf[1] = sd->i2c_base;
682 gspca_dev->usb_buf[2] = reg;
683 gspca_dev->usb_buf[3] = val;
684 gspca_dev->usb_buf[4] = 0;
685 gspca_dev->usb_buf[5] = 0;
686 gspca_dev->usb_buf[6] = 0;
687 gspca_dev->usb_buf[7] = 0x10;
688 usb_control_msg(gspca_dev->dev,
689 usb_sndctrlpipe(gspca_dev->dev, 0),
690 0x08,
691 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
692 0x08, /* value = i2c */
693 0,
694 gspca_dev->usb_buf, 8,
695 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696}
697
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698/* I2C write 8 bytes */
699static void i2c_w8(struct gspca_dev *gspca_dev,
700 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300702 memcpy(gspca_dev->usb_buf, buffer, 8);
703 usb_control_msg(gspca_dev->dev,
704 usb_sndctrlpipe(gspca_dev->dev, 0),
705 0x08,
706 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
707 0x08, 0, /* value, index */
708 gspca_dev->usb_buf, 8,
709 500);
Jean-Francois Moine8d768e12008-09-21 03:28:55 -0300710 msleep(2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711}
712
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300713/* read 5 bytes in gspca_dev->usb_buf */
714static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300715{
716 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 __u8 mode[8];
718
Hans de Goede3647fea2008-07-15 05:36:30 -0300719 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720 mode[1] = sd->i2c_base;
721 mode[2] = reg;
722 mode[3] = 0;
723 mode[4] = 0;
724 mode[5] = 0;
725 mode[6] = 0;
726 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300727 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300728 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300729 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300731 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300732 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300733 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734}
735
736static int probesensor(struct gspca_dev *gspca_dev)
737{
738 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739
Jean-Francois Moine60017612008-07-18 08:46:19 -0300740 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300742 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300744 i2c_r5(gspca_dev, 0); /* read sensor id */
745 if (gspca_dev->usb_buf[0] == 0x02
746 && gspca_dev->usb_buf[1] == 0x09
747 && gspca_dev->usb_buf[2] == 0x01
748 && gspca_dev->usb_buf[3] == 0x00
749 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
751 sd->sensor = SENSOR_HV7131R;
752 return SENSOR_HV7131R;
753 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300754 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300755 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
756 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
758 return -ENODEV;
759}
760
761static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300762 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300763{
764 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300765 const __u8 *reg9a;
766 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300767 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300768 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300770 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771
Jean-Francois Moine60017612008-07-18 08:46:19 -0300772 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300773 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774
775 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300776 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
777 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300778 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300779 switch (sd->bridge) {
780 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 reg9a = reg9a_sn9c325;
782 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 default:
784 reg9a = reg9a_def;
785 break;
786 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300787 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300788
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300789 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300790
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300791 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300793 switch (sd->sensor) {
794 case SENSOR_OM6802:
Jean-Francois Moine4f30f6c2008-09-03 16:48:05 -0300795 reg_w1(gspca_dev, 0x02, 0x71);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300796 reg_w1(gspca_dev, 0x01, 0x42);
797 reg_w1(gspca_dev, 0x17, 0x64);
798 reg_w1(gspca_dev, 0x01, 0x42);
799 break;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300800/*jfm: from win trace */
801 case SENSOR_OV7630:
802 reg_w1(gspca_dev, 0x01, 0x61);
803 reg_w1(gspca_dev, 0x17, 0xe2);
804 reg_w1(gspca_dev, 0x01, 0x60);
805 reg_w1(gspca_dev, 0x01, 0x40);
806 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300807 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300808 reg_w1(gspca_dev, 0x01, 0x43);
809 reg_w1(gspca_dev, 0x17, 0xae);
810 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 break;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300812/*jfm: from win trace */
813 case SENSOR_OV7660:
814 reg_w1(gspca_dev, 0x01, 0x61);
815 reg_w1(gspca_dev, 0x17, 0x20);
816 reg_w1(gspca_dev, 0x01, 0x60);
817 reg_w1(gspca_dev, 0x01, 0x40);
818 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300819 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300820 reg_w1(gspca_dev, 0x01, 0x43);
821 reg_w1(gspca_dev, 0x17, 0x61);
822 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300823 if (sd->sensor == SENSOR_HV7131R) {
824 if (probesensor(gspca_dev) < 0)
825 return -ENODEV;
826 }
827 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828 }
829 return 0;
830}
831
832static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
833{
834 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300835 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300836 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
837
838 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300839 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 i++;
841 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300842 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843}
844
845static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
846{
847 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848
849 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300850 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300851 i++;
852 }
853}
854
855static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
856{
857 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858
859 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300860 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300861 i++;
862 }
863}
864
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300865static void om6802_InitSensor(struct gspca_dev *gspca_dev)
866{
867 int i = 0;
868
869 while (om6802_sensor_init[i][0]) {
870 i2c_w8(gspca_dev, om6802_sensor_init[i]);
871 i++;
872 }
873}
874
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300875static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
876{
877 int i = 0;
878
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300879 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
880 i++;
881 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300882 i++;
883 msleep(20);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300884 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
885 i++;
886 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
887 i++;
888 msleep(20);
889 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
890 i++;
891/*jfm:win i2c_r from 00 to 80*/
892
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300893 while (ov7630_sensor_init[i][0]) {
894 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
895 i++;
896 }
897}
898
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
900{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901 int i = 0;
902
903 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300904 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 i++;
906 }
907}
908
909static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
910{
911 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912
Jean-Francois Moine60017612008-07-18 08:46:19 -0300913 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
914 i++;
915 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300917 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 i++;
919 }
920}
921
922/* this function is called at probe time */
923static int sd_config(struct gspca_dev *gspca_dev,
924 const struct usb_device_id *id)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928
929 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930 cam->epaddr = 0x01;
931 cam->cam_mode = vga_mode;
932 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300933
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300934 sd->bridge = id->driver_info >> 16;
935 sd->sensor = id->driver_info >> 8;
936 sd->i2c_base = id->driver_info;
937
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300939 sd->brightness = BRIGHTNESS_DEF;
940 sd->contrast = CONTRAST_DEF;
941 sd->colors = COLOR_DEF;
942 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -0300943 sd->ag_cnt = -1;
944
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -0300945 switch (sd->sensor) {
946 case SENSOR_OV7630:
947 case SENSOR_OV7648:
948 case SENSOR_OV7660:
949 gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
950 break;
951 }
952
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 return 0;
954}
955
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300956/* this function is called at probe and resume time */
957static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958{
959 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300960/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300962 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963
Hans de Goede3647fea2008-07-15 05:36:30 -0300964 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300965 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300966 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300967 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
968 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300969 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300970 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300971 switch (sd->bridge) {
972 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 if (regF1 != 0x11)
974 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300975 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300977 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 if (regF1 != 0x11)
979 return -ENODEV;
Jean-Francois Moine674cbc62008-10-02 08:06:59 -0300980 reg_w(gspca_dev, 0x01, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300981 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300982 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983 if (regF1 != 0x12)
984 return -ENODEV;
985 regGpio[1] = 0x70;
Jean-Francois Moine674cbc62008-10-02 08:06:59 -0300986 reg_w(gspca_dev, 0x01, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 break;
988 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300989/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300990/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300991 if (regF1 != 0x12)
992 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300993 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300994 break;
995 }
996
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -0300997 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998
999 return 0;
1000}
1001
1002static unsigned int setexposure(struct gspca_dev *gspca_dev,
1003 unsigned int expo)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001006 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001008 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001010 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1012
1013 switch (sd->sensor) {
1014 case SENSOR_HV7131R: {
1015 __u8 Expodoit[] =
1016 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1017
1018 Expodoit[3] = expo >> 16;
1019 Expodoit[4] = expo >> 8;
1020 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001021 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022 break;
1023 }
1024 case SENSOR_MI0360: {
1025 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1026 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1027
1028 if (expo > 0x0635)
1029 expo = 0x0635;
1030 else if (expo < 0x0001)
1031 expo = 0x0001;
1032 expoMi[3] = expo >> 8;
1033 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001034 i2c_w8(gspca_dev, expoMi);
1035 i2c_w8(gspca_dev, doit);
1036 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001037 break;
1038 }
1039 case SENSOR_MO4000: {
1040 __u8 expoMof[] =
1041 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1042 __u8 expoMo10[] =
1043 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1044
1045 if (expo > 0x1fff)
1046 expo = 0x1fff;
1047 else if (expo < 0x0001)
1048 expo = 0x0001;
1049 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001050 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001051 expoMo10[3] = ((expo & 0x1c00) >> 10)
1052 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001053 i2c_w8(gspca_dev, expoMo10);
1054 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001055 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 ((expoMo10[3] & 0x07) << 10)
1057 | (expoMof[3] << 2)
1058 | ((expoMo10[3] & 0x30) >> 4));
1059 break;
1060 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001061 case SENSOR_OM6802: {
1062 __u8 gainOm[] =
1063 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1064
1065 if (expo > 0x03ff)
1066 expo = 0x03ff;
1067 if (expo < 0x0001)
1068 expo = 0x0001;
1069 gainOm[3] = expo >> 2;
1070 i2c_w8(gspca_dev, gainOm);
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001071 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001072 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1073 break;
1074 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 }
1076 return expo;
1077}
1078
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001079/* this function is used for sensors o76xx only */
1080static void setbrightcont(struct gspca_dev *gspca_dev)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083 unsigned val;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001084 __u8 reg84_full[0x15];
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001085
1086 memset(reg84_full, 0, sizeof reg84_full);
1087 val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
1088 reg84_full[2] = val;
1089 reg84_full[0] = (val + 1) / 2;
1090 reg84_full[4] = (val + 1) / 5;
1091 if (val > BRIGHTNESS_DEF)
1092 val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
1093 / BRIGHTNESS_MAX;
1094 else
1095 val = 0;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001096 reg84_full[0x12] = val; /* 00..1f */
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001097 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1098}
1099
1100/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001101static void setbrightness(struct gspca_dev *gspca_dev)
1102{
1103 struct sd *sd = (struct sd *) gspca_dev;
1104 unsigned int expo;
1105 __u8 k2;
1106
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001107 k2 = sd->brightness >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001108 switch (sd->sensor) {
1109 case SENSOR_HV7131R:
1110 expo = sd->brightness << 4;
1111 if (expo > 0x002dc6c0)
1112 expo = 0x002dc6c0;
1113 else if (expo < 0x02a0)
1114 expo = 0x02a0;
1115 sd->exposure = setexposure(gspca_dev, expo);
1116 break;
1117 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001118 case SENSOR_MO4000:
1119 expo = sd->brightness >> 4;
1120 sd->exposure = setexposure(gspca_dev, expo);
1121 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001122 case SENSOR_OM6802:
1123 expo = sd->brightness >> 6;
1124 sd->exposure = setexposure(gspca_dev, expo);
1125 k2 = sd->brightness >> 11;
1126 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127 }
1128
Jean-Francois Moine60017612008-07-18 08:46:19 -03001129 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001130}
1131
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001132/* sensor != ov76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001133static void setcontrast(struct gspca_dev *gspca_dev)
1134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136 __u8 k2;
1137 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1138
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001139 k2 = sd->contrast;
1140 contrast[2] = k2;
1141 contrast[0] = (k2 + 1) >> 1;
1142 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001143 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144}
1145
1146static void setcolors(struct gspca_dev *gspca_dev)
1147{
1148 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001149 __u8 blue, red;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001150
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001151 if (sd->colors >= 32) {
1152 red = 32 + (sd->colors - 32) / 2;
1153 blue = 64 - sd->colors;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001154 } else {
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001155 red = sd->colors;
1156 blue = 32 + (32 - sd->colors) / 2;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001157 }
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001158 reg_w1(gspca_dev, 0x05, red);
1159/* reg_w1(gspca_dev, 0x07, 32); */
1160 reg_w1(gspca_dev, 0x06, blue);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161}
1162
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001163static void setautogain(struct gspca_dev *gspca_dev)
1164{
1165 struct sd *sd = (struct sd *) gspca_dev;
1166
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001167 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1168 return;
1169 if (sd->autogain)
1170 sd->ag_cnt = AG_CNT_START;
1171 else
1172 sd->ag_cnt = -1;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001173}
1174
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175/* -- start the camera -- */
1176static void sd_start(struct gspca_dev *gspca_dev)
1177{
1178 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001179 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001180 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001181 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001183 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1184 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001185 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001186 static const __u8 CE_ov76xx[] =
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001187 { 0x32, 0xdd, 0x32, 0xdd };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001188
1189 sn9c1xx = sn_tb[(int) sd->sensor];
1190 configure_gpio(gspca_dev, sn9c1xx);
1191
Jean-Francois Moine60017612008-07-18 08:46:19 -03001192 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1193 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1194 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1195 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1196 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1197 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1198 reg_w1(gspca_dev, 0xd3, 0x50);
1199 reg_w1(gspca_dev, 0xc6, 0x00);
1200 reg_w1(gspca_dev, 0xc7, 0x00);
1201 reg_w1(gspca_dev, 0xc8, 0x50);
1202 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001203 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001204 switch (sd->sensor) {
1205 case SENSOR_OV7630:
1206 reg17 = 0xe2;
1207 break;
1208 case SENSOR_OV7648:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001209 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001210 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001211/*jfm: from win trace */
1212 case SENSOR_OV7660:
1213 reg17 = 0xa0;
1214 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001215 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001216 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001217 break;
1218 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001219 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001220 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1221 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1222 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1223 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001224 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1225 for (i = 0; i < 8; i++)
1226 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001227 switch (sd->sensor) {
1228 case SENSOR_OV7660:
1229 reg_w1(gspca_dev, 0x9a, 0x05);
1230 break;
1231 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001232 reg_w1(gspca_dev, 0x9a, 0x08);
1233 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001234 break;
1235 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001236
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001237 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001238 if (mode)
1239 reg1 = 0x46; /* 320 clk 48Mhz */
1240 else
1241 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001242 reg17 = 0x61;
1243 switch (sd->sensor) {
1244 case SENSOR_HV7131R:
1245 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001246 break;
1247 case SENSOR_MI0360:
1248 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001249 break;
1250 case SENSOR_MO4000:
1251 mo4000_InitSensor(gspca_dev);
1252 if (mode) {
1253/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1254 reg1 = 0x06; /* clk 24Mz */
1255 } else {
1256 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001257/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001258 }
1259 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001260 case SENSOR_OM6802:
1261 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001262 reg17 = 0x64; /* 640 MCKSIZE */
1263 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001264 case SENSOR_OV7630:
1265 ov7630_InitSensor(gspca_dev);
1266 reg17 = 0xe2;
Jean-Francois Moine5b064da2008-09-03 16:48:08 -03001267 reg1 = 0x44;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001268 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001269 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001270 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001271 reg17 = 0xa2;
1272 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001273/* if (mode)
1274 ; * 320x2...
1275 else
1276 ; * 640x... */
1277 break;
1278 default:
1279/* case SENSOR_OV7660: */
1280 ov7660_InitSensor(gspca_dev);
1281 if (mode) {
1282/* reg17 = 0x21; * 320 */
1283/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001284/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 } else {
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001286 reg17 = 0xa2; /* 640 */
1287 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001288 }
1289 break;
1290 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001292 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001293 switch (sd->sensor) {
1294 case SENSOR_OV7630:
1295 case SENSOR_OV7648:
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001296 case SENSOR_OV7660:
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001297 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001298 break;
1299 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001300 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001301 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1302 break;
1303 }
1304
1305 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001306 reg18 = sn9c1xx[0x18] | (mode << 4);
1307 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001308
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001309 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1310 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001311
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001312 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001313
Jean-Francois Moine60017612008-07-18 08:46:19 -03001314 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001315 switch (sd->sensor) {
1316 case SENSOR_HV7131R:
1317 case SENSOR_MI0360:
1318 case SENSOR_MO4000:
1319 case SENSOR_OM6802:
1320 setbrightness(gspca_dev);
1321 setcontrast(gspca_dev);
1322 break;
1323 default: /* OV76xx */
1324 setbrightcont(gspca_dev);
1325 break;
1326 }
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001327 setautogain(gspca_dev);
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001328 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001329}
1330
1331static void sd_stopN(struct gspca_dev *gspca_dev)
1332{
1333 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001334 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001335 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001336 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001337 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001338 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001339 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001340
1341 data = 0x0b;
1342 switch (sd->sensor) {
1343 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001344 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001345 data = 0x2b;
1346 break;
1347 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001348 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001349 data = 0x29;
1350 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001351 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001352 case SENSOR_OV7648:
1353 data = 0x29;
1354 break;
1355 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001356/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001357/* case SENSOR_OV7660: */
1358 break;
1359 }
1360 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001361 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1362 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1363 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1364 reg_w1(gspca_dev, 0x01, data);
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001365 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001366}
1367
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001368static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001369{
1370 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001371 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001372 int expotimes;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001373 __u8 luma_mean = 130;
1374 __u8 luma_delta = 20;
1375
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001376 /* Thanks S., without your advice, autobright should not work :) */
1377 if (sd->ag_cnt < 0)
1378 return;
1379 if (--sd->ag_cnt >= 0)
1380 return;
1381 sd->ag_cnt = AG_CNT_START;
1382
1383 delta = atomic_read(&sd->avg_lum);
1384 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001385 if (delta < luma_mean - luma_delta ||
1386 delta > luma_mean + luma_delta) {
1387 switch (sd->sensor) {
1388 case SENSOR_HV7131R:
1389 expotimes = sd->exposure >> 8;
1390 expotimes += (luma_mean - delta) >> 4;
1391 if (expotimes < 0)
1392 expotimes = 0;
1393 sd->exposure = setexposure(gspca_dev,
1394 (unsigned int) (expotimes << 8));
1395 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001396 default:
1397/* case SENSOR_MO4000: */
1398/* case SENSOR_MI0360: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001399/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001400 expotimes = sd->exposure;
1401 expotimes += (luma_mean - delta) >> 6;
1402 if (expotimes < 0)
1403 expotimes = 0;
1404 sd->exposure = setexposure(gspca_dev,
1405 (unsigned int) expotimes);
1406 setcolors(gspca_dev);
1407 break;
1408 }
1409 }
1410}
1411
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001412/* scan the URB packets */
1413/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001414static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1415 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001416 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001417 int len) /* iso packet length */
1418{
1419 struct sd *sd = (struct sd *) gspca_dev;
1420 int sof, avg_lum;
1421
1422 sof = len - 64;
1423 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1424
1425 /* end of frame */
1426 gspca_frame_add(gspca_dev, LAST_PACKET,
1427 frame, data, sof + 2);
1428 if (sd->ag_cnt < 0)
1429 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001430/* w1 w2 w3 */
1431/* w4 w5 w6 */
1432/* w7 w8 */
1433/* w4 */
1434 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1435/* w6 */
1436 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1437/* w2 */
1438 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1439/* w8 */
1440 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1441/* w5 */
1442 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1443 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001444 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001445 return;
1446 }
1447 if (gspca_dev->last_packet_type == LAST_PACKET) {
1448
1449 /* put the JPEG 422 header */
1450 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1451 }
1452 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1453}
1454
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001455static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1456{
1457 struct sd *sd = (struct sd *) gspca_dev;
1458
1459 sd->brightness = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001460 if (gspca_dev->streaming) {
1461 switch (sd->sensor) {
1462 case SENSOR_HV7131R:
1463 case SENSOR_MI0360:
1464 case SENSOR_MO4000:
1465 case SENSOR_OM6802:
1466 setbrightness(gspca_dev);
1467 break;
1468 default: /* OV76xx */
1469 setbrightcont(gspca_dev);
1470 break;
1471 }
1472 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001473 return 0;
1474}
1475
1476static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1477{
1478 struct sd *sd = (struct sd *) gspca_dev;
1479
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001480 *val = sd->brightness;
1481 return 0;
1482}
1483
1484static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1485{
1486 struct sd *sd = (struct sd *) gspca_dev;
1487
1488 sd->contrast = val;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001489 if (gspca_dev->streaming) {
1490 switch (sd->sensor) {
1491 case SENSOR_HV7131R:
1492 case SENSOR_MI0360:
1493 case SENSOR_MO4000:
1494 case SENSOR_OM6802:
1495 setcontrast(gspca_dev);
1496 break;
1497 default: /* OV76xx */
1498 setbrightcont(gspca_dev);
1499 break;
1500 }
1501 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001502 return 0;
1503}
1504
1505static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1506{
1507 struct sd *sd = (struct sd *) gspca_dev;
1508
1509 *val = sd->contrast;
1510 return 0;
1511}
1512
1513static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1514{
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 sd->colors = val;
1518 if (gspca_dev->streaming)
1519 setcolors(gspca_dev);
1520 return 0;
1521}
1522
1523static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1524{
1525 struct sd *sd = (struct sd *) gspca_dev;
1526
1527 *val = sd->colors;
1528 return 0;
1529}
1530
1531static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1532{
1533 struct sd *sd = (struct sd *) gspca_dev;
1534
1535 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001536 if (gspca_dev->streaming)
1537 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001538 return 0;
1539}
1540
1541static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1542{
1543 struct sd *sd = (struct sd *) gspca_dev;
1544
1545 *val = sd->autogain;
1546 return 0;
1547}
1548
1549/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001550static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001551 .name = MODULE_NAME,
1552 .ctrls = sd_ctrls,
1553 .nctrls = ARRAY_SIZE(sd_ctrls),
1554 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001555 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001556 .start = sd_start,
1557 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001558 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001559 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001560};
1561
1562/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001563#define BSI(bridge, sensor, i2c_addr) \
1564 .driver_info = (BRIDGE_ ## bridge << 16) \
1565 | (SENSOR_ ## sensor << 8) \
1566 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001567static const __devinitdata struct usb_device_id device_table[] = {
Hans de Goede222a07f2008-09-03 17:12:20 -03001568#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001569 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1570 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1571 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1572 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1573 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001574#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001575 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1576 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1577/* bw600.inf:
1578 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1579/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1580/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1581 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1582/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1583 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1584/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1585/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1586 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1587/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1588/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1589 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1590 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1591/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1592/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1593/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1594/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001595 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1596/*bw600.inf:*/
1597 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001598 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001599 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001600/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Hans de Goede222a07f2008-09-03 17:12:20 -03001601#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001602 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001603#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001604 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001605#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001606/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1607 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1608 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1609/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001610#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001611 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001612 {}
1613};
1614MODULE_DEVICE_TABLE(usb, device_table);
1615
1616/* -- device connect -- */
1617static int sd_probe(struct usb_interface *intf,
1618 const struct usb_device_id *id)
1619{
1620 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1621 THIS_MODULE);
1622}
1623
1624static struct usb_driver sd_driver = {
1625 .name = MODULE_NAME,
1626 .id_table = device_table,
1627 .probe = sd_probe,
1628 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001629#ifdef CONFIG_PM
1630 .suspend = gspca_suspend,
1631 .resume = gspca_resume,
1632#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001633};
1634
1635/* -- module insert / remove -- */
1636static int __init sd_mod_init(void)
1637{
1638 if (usb_register(&sd_driver) < 0)
1639 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001640 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001641 return 0;
1642}
1643static void __exit sd_mod_exit(void)
1644{
1645 usb_deregister(&sd_driver);
1646 info("deregistered");
1647}
1648
1649module_init(sd_mod_init);
1650module_exit(sd_mod_exit);