blob: b60ff600a757817907402346b3a78743fa87f2f0 [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
35 int avg_lum;
36 unsigned int exposure;
37
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 signed char ag_cnt;
44#define AG_CNT_START 13
45
46 char qindex;
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
57#define SENSOR_OV7648 3
58#define SENSOR_OV7660 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060};
61
62/* V4L2 controls supported by the driver */
63static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 0xffff,
80 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081#define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 127,
94 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095#define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 255,
108 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109#define COLOR_DEF 127
110 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 {
116 {
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300123#define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 },
126 .set = sd_setautogain,
127 .get = sd_getautogain,
128 },
129};
130
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300131static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 160,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 320,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 640,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147};
148
149/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300150static const __u8 sn_hv7131[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300151/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
152 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
153/* reg8 reg9 rega regb regc regd rege regf */
154 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
155/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
156 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
157/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
158 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300159};
160
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300161static const __u8 sn_mi0360[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300162/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
164/* reg8 reg9 rega regb regc regd rege regf */
165 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
166/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
167 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
168/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
169 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170};
171
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300172static const __u8 sn_mo4000[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300173/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
174 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
175/* reg8 reg9 rega regb regc regd rege regf */
176 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
178 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
179/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
180 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181};
182
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300183static const __u8 sn_ov7648[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300184/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
185 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
186/* reg8 reg9 rega regb regc regd rege regf */
187 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
188/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
189 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
190/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192};
193
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300194static const __u8 sn_ov7660[] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
197/* reg8 reg9 rega regb regc regd rege regf */
198 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
199/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
200 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
201/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
202 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203};
204
205/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300206static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207 sn_hv7131,
208 sn_mi0360,
209 sn_mo4000,
210 sn_ov7648,
211 sn_ov7660
212};
213
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300214static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
217};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300218static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300219 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
220 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
221};
222
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300223static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300224 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
225 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
226/* 0x00, 0x00, 0x00, 0x00, 0x00 */
227 0xf7, 0x0f, 0x0a, 0x00, 0x00
228};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300229static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300230 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
231 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
232 0xf8, 0x0f, 0x00, 0x00, 0x00
233};
234
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300235static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
237 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
238 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
239 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
240 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
241 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
242 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
243
244 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
245 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
246 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
247 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
248 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
249 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
250 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
251 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
252
253 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
254 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
255 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
256 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
258
259 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
262 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
263 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300264 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300266static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300267 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
268 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
269 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
270 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
271 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
272 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
273 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
274 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
275 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
285 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
287 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
288 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
289 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
290 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
292 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
294 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
296 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
299 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
300
301 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
305 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
306
307 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
308 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
309 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
310 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
311
312 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
313 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
314/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
315/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
316 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
317 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300318 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300319};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300320static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300321 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
322 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
323 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
324 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
325 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
327 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
328 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
329 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
330 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
331 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
332 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
333 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
334 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
335 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
336 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
337 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300341 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300343static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300345/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300346 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300347 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300349 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300350 /* GAIN BLUE RED VREF */
351 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
352 /* COM 1 BAVE GEAVE AECHH */
353 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
354 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300355 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356 /* AECH CLKRC COM7 COM8 */
357 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
358 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
359 /* HSTART HSTOP VSTRT VSTOP */
360 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
361 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
362 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
363 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300364/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
365 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366 /* AEW AEB VPT BBIAS */
367 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
368 /* GbBIAS RSVD EXHCH EXHCL */
369 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
370 /* RBIAS ADVFL ASDVFH YAVE */
371 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
372 /* HSYST HSYEN HREF */
373 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
374 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
375 /* ADC ACOM OFON TSLB */
376 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
377 /* COM11 COM12 COM13 COM14 */
378 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
379 /* EDGE COM15 COM16 COM17 */
380 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
381 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
382 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
383 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
384 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
385 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
386 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
387 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
388 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
389 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
390 /* LCC1 LCC2 LCC3 LCC4 */
391 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300392 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300394 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
396 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
397 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
398 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
399 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
400 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
401 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
402 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
403 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300404 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300405/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300406 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300407 /* bits[3..0]reserved */
408 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
409 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
410 /* VREF vertical frame ctrl */
411 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300412 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
413 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
414 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
415 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
416/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417/****** (some exchanges in the win trace) ******/
418 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300419 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
420 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
421 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
422/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300423/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300424/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300425 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
426 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300429 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300430};
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300431/* reg 0x04 reg 0x07 reg 0x10 */
432/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300434static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
436 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
437 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
438 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
439 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
441 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
442 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
443 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
444 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
445 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
446 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
447 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
448 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
449 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
450 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
451 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
452 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
453 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
454 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
455 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
456 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
457 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
458 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
459 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
460 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
461 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
462 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
464 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
465 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
466 * This is currently setting a
467 * blue tint, and some things more , i leave it here for future test if
468 * somene is having problems with color on this sensor
469 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
471 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
472 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
473 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
474 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
475 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
476 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
477 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
478 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
479 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
480 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
481 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
482 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
483 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
484 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
485 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
486/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300487 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488};
489
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300490static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300491 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
492 0x06, 0x08, 0x0A, 0x11,
493 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
494 0x19, 0x19, 0x17, 0x15,
495 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
496 0x21, 0x2E, 0x21, 0x23,
497 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
498 0x25, 0x29, 0x2C, 0x29,
499 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
500 0x17, 0x1B, 0x29, 0x29,
501 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
502 0x29, 0x29, 0x29, 0x29,
503 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
504 0x29, 0x29, 0x29, 0x29,
505 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
506 0x29, 0x29, 0x29, 0x29
507};
508
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300509/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
510static void reg_r(struct gspca_dev *gspca_dev,
511 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300513 usb_control_msg(gspca_dev->dev,
514 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515 0,
516 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
517 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300518 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300520 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300521}
522
Jean-Francois Moine60017612008-07-18 08:46:19 -0300523static void reg_w1(struct gspca_dev *gspca_dev,
524 __u16 value,
525 __u8 data)
526{
527 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
528 gspca_dev->usb_buf[0] = data;
529 usb_control_msg(gspca_dev->dev,
530 usb_sndctrlpipe(gspca_dev->dev, 0),
531 0x08,
532 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
533 value,
534 0,
535 gspca_dev->usb_buf, 1,
536 500);
537}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300540 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 int len)
542{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300543 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
544 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 if (len <= sizeof gspca_dev->usb_buf) {
546 memcpy(gspca_dev->usb_buf, buffer, len);
547 usb_control_msg(gspca_dev->dev,
548 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300549 0x08,
550 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
551 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300552 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300553 500);
554 } else {
555 __u8 *tmpbuf;
556
557 tmpbuf = kmalloc(len, GFP_KERNEL);
558 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300559 usb_control_msg(gspca_dev->dev,
560 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300561 0x08,
562 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
563 value, 0,
564 tmpbuf, len,
565 500);
566 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300567 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300568}
569
Jean-Francois Moine60017612008-07-18 08:46:19 -0300570/* I2C write 1 byte */
571static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300572{
573 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574
Jean-Francois Moine60017612008-07-18 08:46:19 -0300575 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
576 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
577 gspca_dev->usb_buf[1] = sd->i2c_base;
578 gspca_dev->usb_buf[2] = reg;
579 gspca_dev->usb_buf[3] = val;
580 gspca_dev->usb_buf[4] = 0;
581 gspca_dev->usb_buf[5] = 0;
582 gspca_dev->usb_buf[6] = 0;
583 gspca_dev->usb_buf[7] = 0x10;
584 usb_control_msg(gspca_dev->dev,
585 usb_sndctrlpipe(gspca_dev->dev, 0),
586 0x08,
587 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
588 0x08, /* value = i2c */
589 0,
590 gspca_dev->usb_buf, 8,
591 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300592}
593
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300594/* I2C write 8 bytes */
595static void i2c_w8(struct gspca_dev *gspca_dev,
596 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300598 memcpy(gspca_dev->usb_buf, buffer, 8);
599 usb_control_msg(gspca_dev->dev,
600 usb_sndctrlpipe(gspca_dev->dev, 0),
601 0x08,
602 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
603 0x08, 0, /* value, index */
604 gspca_dev->usb_buf, 8,
605 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300606}
607
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300608/* read 5 bytes in gspca_dev->usb_buf */
609static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610{
611 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 __u8 mode[8];
613
Hans de Goede3647fea2008-07-15 05:36:30 -0300614 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615 mode[1] = sd->i2c_base;
616 mode[2] = reg;
617 mode[3] = 0;
618 mode[4] = 0;
619 mode[5] = 0;
620 mode[6] = 0;
621 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300623 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300624 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300627 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629}
630
631static int probesensor(struct gspca_dev *gspca_dev)
632{
633 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634
Jean-Francois Moine60017612008-07-18 08:46:19 -0300635 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300637 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300639 i2c_r5(gspca_dev, 0); /* read sensor id */
640 if (gspca_dev->usb_buf[0] == 0x02
641 && gspca_dev->usb_buf[1] == 0x09
642 && gspca_dev->usb_buf[2] == 0x01
643 && gspca_dev->usb_buf[3] == 0x00
644 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
646 sd->sensor = SENSOR_HV7131R;
647 return SENSOR_HV7131R;
648 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300649 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300650 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
651 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
653 return -ENODEV;
654}
655
656static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300657 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658{
659 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300660 const __u8 *reg9a;
661 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300663 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300665 static const __u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300666
Jean-Francois Moine60017612008-07-18 08:46:19 -0300667 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300668 reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300669
670 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300671 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
672 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300673 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300674 switch (sd->bridge) {
675 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676 reg9a = reg9a_sn9c325;
677 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 default:
679 reg9a = reg9a_def;
680 break;
681 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300682 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300683
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300684 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300686 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687
Hans de Goede3647fea2008-07-15 05:36:30 -0300688 switch (sd->bridge) {
Hans de Goede3647fea2008-07-15 05:36:30 -0300689 case BRIDGE_SN9C325:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300690 reg_w1(gspca_dev, 0x01, 0x43);
691 reg_w1(gspca_dev, 0x17, 0xae);
692 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 break;
694 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300695 reg_w1(gspca_dev, 0x01, 0x43);
696 reg_w1(gspca_dev, 0x17, 0x61);
697 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698 }
699
700 if (sd->sensor == SENSOR_HV7131R) {
701 if (probesensor(gspca_dev) < 0)
702 return -ENODEV;
703 }
704 return 0;
705}
706
707static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
708{
709 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300710 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
712
713 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300715 i++;
716 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300717 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718}
719
720static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
721{
722 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723
724 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300725 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726 i++;
727 }
728}
729
730static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
731{
732 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300733
734 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300735 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736 i++;
737 }
738}
739
740static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
741{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742 int i = 0;
743
744 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300745 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 i++;
747 }
748}
749
750static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
751{
752 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300753
Jean-Francois Moine60017612008-07-18 08:46:19 -0300754 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
755 i++;
756 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300758 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 i++;
760 }
761}
762
763/* this function is called at probe time */
764static int sd_config(struct gspca_dev *gspca_dev,
765 const struct usb_device_id *id)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300769
770 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 cam->epaddr = 0x01;
772 cam->cam_mode = vga_mode;
773 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300774
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300775 sd->bridge = id->driver_info >> 16;
776 sd->sensor = id->driver_info >> 8;
777 sd->i2c_base = id->driver_info;
778
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300780 sd->brightness = BRIGHTNESS_DEF;
781 sd->contrast = CONTRAST_DEF;
782 sd->colors = COLOR_DEF;
783 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784 return 0;
785}
786
787/* this function is called at open time */
788static int sd_open(struct gspca_dev *gspca_dev)
789{
790 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300791/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300793 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794
Hans de Goede3647fea2008-07-15 05:36:30 -0300795 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300796 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300797 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300798 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
799 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300800 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300801 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -0300802 switch (sd->bridge) {
803 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804 if (regF1 != 0x11)
805 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300806 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300808 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809 if (regF1 != 0x11)
810 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300811 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300813 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814 if (regF1 != 0x12)
815 return -ENODEV;
816 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300817 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 break;
819 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300820/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300821/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822 if (regF1 != 0x12)
823 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300824 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 break;
826 }
827
Jean-Francois Moine60017612008-07-18 08:46:19 -0300828 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829
830 return 0;
831}
832
833static unsigned int setexposure(struct gspca_dev *gspca_dev,
834 unsigned int expo)
835{
836 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300837 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300839 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300841 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
843
844 switch (sd->sensor) {
845 case SENSOR_HV7131R: {
846 __u8 Expodoit[] =
847 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
848
849 Expodoit[3] = expo >> 16;
850 Expodoit[4] = expo >> 8;
851 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300852 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 break;
854 }
855 case SENSOR_MI0360: {
856 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
857 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
858
859 if (expo > 0x0635)
860 expo = 0x0635;
861 else if (expo < 0x0001)
862 expo = 0x0001;
863 expoMi[3] = expo >> 8;
864 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300865 i2c_w8(gspca_dev, expoMi);
866 i2c_w8(gspca_dev, doit);
867 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 break;
869 }
870 case SENSOR_MO4000: {
871 __u8 expoMof[] =
872 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
873 __u8 expoMo10[] =
874 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
875
876 if (expo > 0x1fff)
877 expo = 0x1fff;
878 else if (expo < 0x0001)
879 expo = 0x0001;
880 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300881 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882 expoMo10[3] = ((expo & 0x1c00) >> 10)
883 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300884 i2c_w8(gspca_dev, expoMo10);
885 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300886 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887 ((expoMo10[3] & 0x07) << 10)
888 | (expoMof[3] << 2)
889 | ((expoMo10[3] & 0x30) >> 4));
890 break;
891 }
892 }
893 return expo;
894}
895
896static void setbrightness(struct gspca_dev *gspca_dev)
897{
898 struct sd *sd = (struct sd *) gspca_dev;
899 unsigned int expo;
900 __u8 k2;
901
902 switch (sd->sensor) {
903 case SENSOR_HV7131R:
904 expo = sd->brightness << 4;
905 if (expo > 0x002dc6c0)
906 expo = 0x002dc6c0;
907 else if (expo < 0x02a0)
908 expo = 0x02a0;
909 sd->exposure = setexposure(gspca_dev, expo);
910 break;
911 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 case SENSOR_MO4000:
913 expo = sd->brightness >> 4;
914 sd->exposure = setexposure(gspca_dev, expo);
915 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 }
917
918 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300919 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920}
921
922static void setcontrast(struct gspca_dev *gspca_dev)
923{
924 struct sd *sd = (struct sd *) gspca_dev;
925 __u8 k2;
926 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
927
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 k2 = sd->contrast;
929 contrast[2] = k2;
930 contrast[0] = (k2 + 1) >> 1;
931 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300932 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933}
934
935static void setcolors(struct gspca_dev *gspca_dev)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
938 __u8 data;
939 int colour;
940
941 colour = sd->colors - 128;
942 if (colour > 0)
943 data = (colour + 32) & 0x7f; /* blue */
944 else
945 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300946 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300947}
948
949/* -- start the camera -- */
950static void sd_start(struct gspca_dev *gspca_dev)
951{
952 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953 int i;
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300954 __u8 reg1, reg17, reg18;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300955 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300957 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
958 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300959 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
960 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
962
963 sn9c1xx = sn_tb[(int) sd->sensor];
964 configure_gpio(gspca_dev, sn9c1xx);
965
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300966/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/
Jean-Francois Moine60017612008-07-18 08:46:19 -0300967 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
968 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
969 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
970 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
971 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
972 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
973 reg_w1(gspca_dev, 0xd3, 0x50);
974 reg_w1(gspca_dev, 0xc6, 0x00);
975 reg_w1(gspca_dev, 0xc7, 0x00);
976 reg_w1(gspca_dev, 0xc8, 0x50);
977 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300978 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300979 switch (sd->bridge) {
980 case BRIDGE_SN9C325:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300981 reg17 = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300982 break;
983 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300984 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300985 break;
986 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300987 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300988 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
989 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
990 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
991 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300992 switch (sd->bridge) {
993 case BRIDGE_SN9C325:
994 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
995 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300997 reg_w(gspca_dev, 0x84, reg84_sn9c325,
998 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300999 reg_w1(gspca_dev, 0x9a, 0x0a);
1000 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001001 break;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001002 default:
1003 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001005 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001006 reg_w1(gspca_dev, 0x9a, 0x08);
1007 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001008 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 }
1010
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001011 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001012 if (mode)
1013 reg1 = 0x46; /* 320 clk 48Mhz */
1014 else
1015 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001016 reg17 = 0x61;
1017 switch (sd->sensor) {
1018 case SENSOR_HV7131R:
1019 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001020 break;
1021 case SENSOR_MI0360:
1022 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 break;
1024 case SENSOR_MO4000:
1025 mo4000_InitSensor(gspca_dev);
1026 if (mode) {
1027/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1028 reg1 = 0x06; /* clk 24Mz */
1029 } else {
1030 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001031/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032 }
1033 break;
1034 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001035 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001036 reg17 = 0xa2;
1037 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038/* if (mode)
1039 ; * 320x2...
1040 else
1041 ; * 640x... */
1042 break;
1043 default:
1044/* case SENSOR_OV7660: */
1045 ov7660_InitSensor(gspca_dev);
1046 if (mode) {
1047/* reg17 = 0x21; * 320 */
1048/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001049/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050 } else {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001051 reg17 = 0x22; /* 640 MCKSIZE */
1052 reg1 = 0x06;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 }
1054 break;
1055 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001056 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001057 reg_w(gspca_dev, 0xca, CA, 4);
Hans de Goede3647fea2008-07-15 05:36:30 -03001058 switch (sd->bridge) {
Hans de Goede3647fea2008-07-15 05:36:30 -03001059 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001060 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001061 break;
1062 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001063 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1065 break;
1066 }
1067
1068 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001069 reg18 = sn9c1xx[0x18] | (mode << 4);
1070 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001072 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1073 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001074
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001075 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001076
Jean-Francois Moine60017612008-07-18 08:46:19 -03001077 reg_w1(gspca_dev, 0x17, reg17);
1078 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001079 setbrightness(gspca_dev);
1080 setcontrast(gspca_dev);
1081}
1082
1083static void sd_stopN(struct gspca_dev *gspca_dev)
1084{
1085 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001086 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001087 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001088 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001091 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001092
1093 data = 0x0b;
1094 switch (sd->sensor) {
1095 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001096 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001097 data = 0x2b;
1098 break;
1099 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001100 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001101 data = 0x29;
1102 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001103 case SENSOR_OV7648:
1104 data = 0x29;
1105 break;
1106 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001107/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001108/* case SENSOR_OV7660: */
1109 break;
1110 }
1111 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001112 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1113 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1114 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1115 reg_w1(gspca_dev, 0x01, data);
1116 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117}
1118
1119static void sd_stop0(struct gspca_dev *gspca_dev)
1120{
1121}
1122
1123static void sd_close(struct gspca_dev *gspca_dev)
1124{
1125}
1126
1127static void setautogain(struct gspca_dev *gspca_dev)
1128{
1129 struct sd *sd = (struct sd *) gspca_dev;
1130 /* Thanks S., without your advice, autobright should not work :) */
1131 int delta;
1132 int expotimes = 0;
1133 __u8 luma_mean = 130;
1134 __u8 luma_delta = 20;
1135
1136 delta = sd->avg_lum;
1137 if (delta < luma_mean - luma_delta ||
1138 delta > luma_mean + luma_delta) {
1139 switch (sd->sensor) {
1140 case SENSOR_HV7131R:
1141 expotimes = sd->exposure >> 8;
1142 expotimes += (luma_mean - delta) >> 4;
1143 if (expotimes < 0)
1144 expotimes = 0;
1145 sd->exposure = setexposure(gspca_dev,
1146 (unsigned int) (expotimes << 8));
1147 break;
1148 case SENSOR_MO4000:
1149 case SENSOR_MI0360:
1150 expotimes = sd->exposure;
1151 expotimes += (luma_mean - delta) >> 6;
1152 if (expotimes < 0)
1153 expotimes = 0;
1154 sd->exposure = setexposure(gspca_dev,
1155 (unsigned int) expotimes);
1156 setcolors(gspca_dev);
1157 break;
1158 }
1159 }
1160}
1161
1162static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1163 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001164 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001165 int len) /* iso packet length */
1166{
1167 struct sd *sd = (struct sd *) gspca_dev;
1168 int sof, avg_lum;
1169
1170 sof = len - 64;
1171 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1172
1173 /* end of frame */
1174 gspca_frame_add(gspca_dev, LAST_PACKET,
1175 frame, data, sof + 2);
1176 if (sd->ag_cnt < 0)
1177 return;
1178 if (--sd->ag_cnt >= 0)
1179 return;
1180 sd->ag_cnt = AG_CNT_START;
1181/* w1 w2 w3 */
1182/* w4 w5 w6 */
1183/* w7 w8 */
1184/* w4 */
1185 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1186/* w6 */
1187 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1188/* w2 */
1189 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1190/* w8 */
1191 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1192/* w5 */
1193 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1194 avg_lum >>= 4;
1195 sd->avg_lum = avg_lum;
1196 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1197 setautogain(gspca_dev);
1198 return;
1199 }
1200 if (gspca_dev->last_packet_type == LAST_PACKET) {
1201
1202 /* put the JPEG 422 header */
1203 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1204 }
1205 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1206}
1207
1208static unsigned int getexposure(struct gspca_dev *gspca_dev)
1209{
1210 struct sd *sd = (struct sd *) gspca_dev;
1211 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212
1213 switch (sd->sensor) {
1214 case SENSOR_HV7131R:
1215 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001216 i2c_r5(gspca_dev, 0x25);
1217 return (gspca_dev->usb_buf[0] << 16)
1218 | (gspca_dev->usb_buf[1] << 8)
1219 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001220 case SENSOR_MI0360:
1221 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001222 i2c_r5(gspca_dev, 0x09);
1223 return (gspca_dev->usb_buf[0] << 8)
1224 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001226 i2c_r5(gspca_dev, 0x0e);
1227 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1228 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1229 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001230 PDEBUG(D_CONF, "exposure %d",
1231 (hexpo << 10) | (mexpo << 2) | lexpo);
1232 return (hexpo << 10) | (mexpo << 2) | lexpo;
1233 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001234/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001235/* case SENSOR_OV7660: */
1236 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001237 i2c_r5(gspca_dev, 0x04);
1238 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1239 lexpo = gspca_dev->usb_buf[0] & 0x02;
1240 i2c_r5(gspca_dev, 0x08);
1241 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001242 return (hexpo << 10) | (mexpo << 2) | lexpo;
1243 }
1244}
1245
1246static void getbrightness(struct gspca_dev *gspca_dev)
1247{
1248 struct sd *sd = (struct sd *) gspca_dev;
1249
1250 /* hardcoded registers seem not readable */
1251 switch (sd->sensor) {
1252 case SENSOR_HV7131R:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 sd->brightness = getexposure(gspca_dev) >> 4;
1254 break;
1255 case SENSOR_MI0360:
1256 sd->brightness = getexposure(gspca_dev) << 4;
1257 break;
1258 case SENSOR_MO4000:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001259 sd->brightness = getexposure(gspca_dev) << 4;
1260 break;
1261 }
1262}
1263
1264static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1265{
1266 struct sd *sd = (struct sd *) gspca_dev;
1267
1268 sd->brightness = val;
1269 if (gspca_dev->streaming)
1270 setbrightness(gspca_dev);
1271 return 0;
1272}
1273
1274static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1275{
1276 struct sd *sd = (struct sd *) gspca_dev;
1277
1278 getbrightness(gspca_dev);
1279 *val = sd->brightness;
1280 return 0;
1281}
1282
1283static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1284{
1285 struct sd *sd = (struct sd *) gspca_dev;
1286
1287 sd->contrast = val;
1288 if (gspca_dev->streaming)
1289 setcontrast(gspca_dev);
1290 return 0;
1291}
1292
1293static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1294{
1295 struct sd *sd = (struct sd *) gspca_dev;
1296
1297 *val = sd->contrast;
1298 return 0;
1299}
1300
1301static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1302{
1303 struct sd *sd = (struct sd *) gspca_dev;
1304
1305 sd->colors = val;
1306 if (gspca_dev->streaming)
1307 setcolors(gspca_dev);
1308 return 0;
1309}
1310
1311static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1312{
1313 struct sd *sd = (struct sd *) gspca_dev;
1314
1315 *val = sd->colors;
1316 return 0;
1317}
1318
1319static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1320{
1321 struct sd *sd = (struct sd *) gspca_dev;
1322
1323 sd->autogain = val;
1324 if (val)
1325 sd->ag_cnt = AG_CNT_START;
1326 else
1327 sd->ag_cnt = -1;
1328 return 0;
1329}
1330
1331static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1332{
1333 struct sd *sd = (struct sd *) gspca_dev;
1334
1335 *val = sd->autogain;
1336 return 0;
1337}
1338
1339/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001340static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001341 .name = MODULE_NAME,
1342 .ctrls = sd_ctrls,
1343 .nctrls = ARRAY_SIZE(sd_ctrls),
1344 .config = sd_config,
1345 .open = sd_open,
1346 .start = sd_start,
1347 .stopN = sd_stopN,
1348 .stop0 = sd_stop0,
1349 .close = sd_close,
1350 .pkt_scan = sd_pkt_scan,
1351};
1352
1353/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001354#define BSI(bridge, sensor, i2c_addr) \
1355 .driver_info = (BRIDGE_ ## bridge << 16) \
1356 | (SENSOR_ ## sensor << 8) \
1357 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001358static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001359#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001360 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1361 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1362 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1363 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1364 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001365#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001366 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1367 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1368/* bw600.inf:
1369 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1370/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1371/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1372 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1373/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1374 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1375/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1376/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1377 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1378/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1379/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1380 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1381 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1382/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1383/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1384/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1385/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1386 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1387/* bw600.inf:
1388 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1389 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1390/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1391/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001392#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001393 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1394 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1395/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1396 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1397 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1398/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001399#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001400 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001401 {}
1402};
1403MODULE_DEVICE_TABLE(usb, device_table);
1404
1405/* -- device connect -- */
1406static int sd_probe(struct usb_interface *intf,
1407 const struct usb_device_id *id)
1408{
1409 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1410 THIS_MODULE);
1411}
1412
1413static struct usb_driver sd_driver = {
1414 .name = MODULE_NAME,
1415 .id_table = device_table,
1416 .probe = sd_probe,
1417 .disconnect = gspca_disconnect,
1418};
1419
1420/* -- module insert / remove -- */
1421static int __init sd_mod_init(void)
1422{
1423 if (usb_register(&sd_driver) < 0)
1424 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001425 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001426 return 0;
1427}
1428static void __exit sd_mod_exit(void)
1429{
1430 usb_deregister(&sd_driver);
1431 info("deregistered");
1432}
1433
1434module_init(sd_mod_init);
1435module_exit(sd_mod_exit);