blob: 325b71df96ff11ada67444b06f21c42b9578b545 [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"
Jean-Francois Moine36e819d2009-01-07 16:49:57 -030025#define QUANT_VAL 4 /* quantization table */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030026#include "jpeg.h"
27
Jean-Francois Moine0cae8962008-10-17 07:48:24 -030028#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
29
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -030038 atomic_t avg_lum;
Jean-Francois Moine98819182009-01-19 07:37:33 -030039 u32 exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030040
Jean-Francois Moine98819182009-01-19 07:37:33 -030041 u16 brightness;
42 u8 contrast;
43 u8 colors;
44 u8 autogain;
45 u8 blue;
46 u8 red;
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -030047 u8 gamma;
Jean-Francois Moine98819182009-01-19 07:37:33 -030048 u8 vflip; /* ov7630 only */
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -030049 u8 infrared; /* mt9v111 only */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030050
Jean-Francois Moine98819182009-01-19 07:37:33 -030051 s8 ag_cnt;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030052#define AG_CNT_START 13
53
Jean-Francois Moine98819182009-01-19 07:37:33 -030054 u8 bridge;
Hans de Goede3647fea2008-07-15 05:36:30 -030055#define BRIDGE_SN9C102P 0
56#define BRIDGE_SN9C105 1
57#define BRIDGE_SN9C110 2
58#define BRIDGE_SN9C120 3
59#define BRIDGE_SN9C325 4
Jean-Francois Moine98819182009-01-19 07:37:33 -030060 u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030061#define SENSOR_HV7131R 0
62#define SENSOR_MI0360 1
63#define SENSOR_MO4000 2
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -030064#define SENSOR_MT9V111 3
65#define SENSOR_OM6802 4
66#define SENSOR_OV7630 5
67#define SENSOR_OV7648 6
68#define SENSOR_OV7660 7
Jean-Francois Moine98819182009-01-19 07:37:33 -030069 u8 i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030070};
71
72/* V4L2 controls supported by the driver */
73static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine403123d2008-11-26 04:46:15 -030079static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -030083static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030085static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6c862742008-09-08 04:57:26 -030087static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine0cae8962008-10-17 07:48:24 -030089static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091
92static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093 {
94 {
95 .id = V4L2_CID_BRIGHTNESS,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Brightness",
98 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -030099#define BRIGHTNESS_MAX 0xffff
100 .maximum = BRIGHTNESS_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 .step = 1,
Jean-Francois Moineb1b056a2008-11-25 04:47:09 -0300102#define BRIGHTNESS_DEF 0x8000
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300103 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300104 },
105 .set = sd_setbrightness,
106 .get = sd_getbrightness,
107 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108 {
109 {
110 .id = V4L2_CID_CONTRAST,
111 .type = V4L2_CTRL_TYPE_INTEGER,
112 .name = "Contrast",
113 .minimum = 0,
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300114#define CONTRAST_MAX 127
115 .maximum = CONTRAST_MAX,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300116 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300117#define CONTRAST_DEF 63
118 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119 },
120 .set = sd_setcontrast,
121 .get = sd_getcontrast,
122 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300123 {
124 {
125 .id = V4L2_CID_SATURATION,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Color",
128 .minimum = 0,
Jean-Francois Moine403123d2008-11-26 04:46:15 -0300129 .maximum = 40,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 .step = 1,
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -0300131#define COLOR_DEF 32
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300132 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300133 },
134 .set = sd_setcolors,
135 .get = sd_getcolors,
136 },
Jean-Francois Moine403123d2008-11-26 04:46:15 -0300137 {
138 {
139 .id = V4L2_CID_BLUE_BALANCE,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Blue Balance",
142 .minimum = 24,
143 .maximum = 40,
144 .step = 1,
145#define BLUE_BALANCE_DEF 32
146 .default_value = BLUE_BALANCE_DEF,
147 },
148 .set = sd_setblue_balance,
149 .get = sd_getblue_balance,
150 },
151 {
152 {
153 .id = V4L2_CID_RED_BALANCE,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Red Balance",
156 .minimum = 24,
157 .maximum = 40,
158 .step = 1,
159#define RED_BALANCE_DEF 32
160 .default_value = RED_BALANCE_DEF,
161 },
162 .set = sd_setred_balance,
163 .get = sd_getred_balance,
164 },
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -0300165 {
166 {
167 .id = V4L2_CID_GAMMA,
168 .type = V4L2_CTRL_TYPE_INTEGER,
169 .name = "Gamma",
170 .minimum = 0,
171 .maximum = 40,
172 .step = 1,
173#define GAMMA_DEF 20
174 .default_value = GAMMA_DEF,
175 },
176 .set = sd_setgamma,
177 .get = sd_getgamma,
178 },
Jean-Francois Moine403123d2008-11-26 04:46:15 -0300179#define AUTOGAIN_IDX 5
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180 {
181 {
182 .id = V4L2_CID_AUTOGAIN,
183 .type = V4L2_CTRL_TYPE_BOOLEAN,
184 .name = "Auto Gain",
185 .minimum = 0,
186 .maximum = 1,
187 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300188#define AUTOGAIN_DEF 1
189 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300190 },
191 .set = sd_setautogain,
192 .get = sd_getautogain,
193 },
Jean-Francois Moine6c862742008-09-08 04:57:26 -0300194/* ov7630 only */
Jean-Francois Moine403123d2008-11-26 04:46:15 -0300195#define VFLIP_IDX 6
Jean-Francois Moine6c862742008-09-08 04:57:26 -0300196 {
197 {
198 .id = V4L2_CID_VFLIP,
199 .type = V4L2_CTRL_TYPE_BOOLEAN,
200 .name = "Vflip",
201 .minimum = 0,
202 .maximum = 1,
203 .step = 1,
Jean-Francois Moine40e6ec12008-09-22 03:14:25 -0300204#define VFLIP_DEF 1
Jean-Francois Moine6c862742008-09-08 04:57:26 -0300205 .default_value = VFLIP_DEF,
206 },
207 .set = sd_setvflip,
208 .get = sd_getvflip,
209 },
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300210/* mt9v111 only */
Jean-Francois Moine403123d2008-11-26 04:46:15 -0300211#define INFRARED_IDX 7
Jean-Francois Moine0cae8962008-10-17 07:48:24 -0300212 {
213 {
214 .id = V4L2_CID_INFRARED,
215 .type = V4L2_CTRL_TYPE_BOOLEAN,
216 .name = "Infrared",
217 .minimum = 0,
218 .maximum = 1,
219 .step = 1,
220#define INFRARED_DEF 0
221 .default_value = INFRARED_DEF,
222 },
223 .set = sd_setinfrared,
224 .get = sd_getinfrared,
225 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300226};
227
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300228/* table of the disabled controls */
229static __u32 ctrl_dis[] = {
230 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
231 /* SENSOR_HV7131R 0 */
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300232 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300233 /* SENSOR_MI0360 1 */
234 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
235 /* SENSOR_MO4000 2 */
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300236 (1 << AUTOGAIN_IDX),
237 /* SENSOR_MT9V111 3 */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300238 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300239 /* SENSOR_OM6802 4 */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300240 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300241 /* SENSOR_OV7630 5 */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300242 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300243 /* SENSOR_OV7648 6 */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300244 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300245 /* SENSOR_OV7660 7 */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300246};
247
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300248static const struct v4l2_pix_format vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300249 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
250 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300251 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300252 .colorspace = V4L2_COLORSPACE_JPEG,
253 .priv = 2},
254 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
255 .bytesperline = 320,
256 .sizeimage = 320 * 240 * 3 / 8 + 590,
257 .colorspace = V4L2_COLORSPACE_JPEG,
258 .priv = 1},
259 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
260 .bytesperline = 640,
261 .sizeimage = 640 * 480 * 3 / 8 + 590,
262 .colorspace = V4L2_COLORSPACE_JPEG,
263 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300264};
265
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300266/*Data from sn9c102p+hv7131r */
267static const u8 sn_hv7131[0x1c] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300268/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
269 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
270/* reg8 reg9 rega regb regc regd rege regf */
271 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
272/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
273 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300274/* reg18 reg19 reg1a reg1b */
275 0x0a, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300276};
277
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300278static const u8 sn_mi0360[0x1c] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300279/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
280 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
281/* reg8 reg9 rega regb regc regd rege regf */
282 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
283/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
284 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300285/* reg18 reg19 reg1a reg1b */
286 0x06, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300287};
288
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300289static const u8 sn_mo4000[0x1c] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300290/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300291 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300292/* reg8 reg9 rega regb regc regd rege regf */
293 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
295 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300296/* reg18 reg19 reg1a reg1b */
297 0x08, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300298};
299
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300300static const u8 sn_mt9v111[0x1c] = {
301/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
302 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
303/* reg8 reg9 rega regb regc regd rege regf */
304 0x81, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
305/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
306 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40,
307/* reg18 reg19 reg1a reg1b */
308 0x06, 0x00, 0x00, 0x00
309};
310
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300311static const u8 sn_om6802[0x1c] = {
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300312/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
313 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
314/* reg8 reg9 rega regb regc regd rege regf */
315 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
317 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300318/* reg18 reg19 reg1a reg1b */
319 0x05, 0x00, 0x00, 0x00
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300320};
321
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300322static const u8 sn_ov7630[0x1c] = {
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300323/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
324 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
325/* reg8 reg9 rega regb regc regd rege regf */
326 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
327/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
328 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300329/* reg18 reg19 reg1a reg1b */
330 0x0b, 0x00, 0x00, 0x00
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300331};
332
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300333static const u8 sn_ov7648[0x1c] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300334/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
Jean-Francois Moine62703302008-11-11 08:42:56 -0300335 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300336/* reg8 reg9 rega regb regc regd rege regf */
Jean-Francois Moine62703302008-11-11 08:42:56 -0300337 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300338/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
Jean-Francois Moine62703302008-11-11 08:42:56 -0300339 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300340/* reg18 reg19 reg1a reg1b */
341 0x0b, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342};
343
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300344static const u8 sn_ov7660[0x1c] = {
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300345/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
346 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
347/* reg8 reg9 rega regb regc regd rege regf */
348 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
349/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
350 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300351/* reg18 reg19 reg1a reg1b */
352 0x07, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300353};
354
355/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300356static const u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 sn_hv7131,
358 sn_mi0360,
359 sn_mo4000,
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300360 sn_mt9v111,
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300361 sn_om6802,
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300362 sn_ov7630,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363 sn_ov7648,
364 sn_ov7660
365};
366
Jean-Francois Moine98819182009-01-19 07:37:33 -0300367static const u8 gamma_def[17] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300368 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
369 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
370};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -0300372
Jean-Francois Moine803f9cc2008-10-04 14:17:02 -0300373/* color matrix and offsets */
Jean-Francois Moine98819182009-01-19 07:37:33 -0300374static const u8 reg84[] = {
Jean-Francois Moine803f9cc2008-10-04 14:17:02 -0300375 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
376 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
377 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
378 0x00, 0x00, 0x00 /* YUV offsets */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300380static const u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300381 {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
382 {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
383 {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
384/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
385 {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
386 {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
387/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300389 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
390 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
391 {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
392 {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
393 {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
394 {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
395 {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
396 {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300397
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300398 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
399 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
400 {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
401 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
402 {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300403
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300404 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
405 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
406 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
407 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
408 {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300409 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300410};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300411static const u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300412 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
Jean-Francois Moine98819182009-01-19 07:37:33 -0300413 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300414 {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300415 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
416 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
417 {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
418 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
419 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
422 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
423 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
424 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
425 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
426 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
427 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
429 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
431 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
433 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
Jean-Francois Moine98819182009-01-19 07:37:33 -0300434 {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300435 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
436 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
437 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
438 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
439 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
440 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
441 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
444 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300446 {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
447 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
448 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
449 {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
450 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300451
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300452 {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
453 {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
454 {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
455 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456
Jean-Francois Moine8c2ba442009-01-13 05:55:40 -0300457 {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
458 {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
459/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
460/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
461 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
462 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300463 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300464};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300465static const u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
467 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
468 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
469 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
470 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
471 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
472 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
473 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
474 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
475 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
477 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
478 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
479 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
480 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
481 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
482 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
483 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
484 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
485 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300486 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300487};
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300488static const u8 mt9v111_sensor_init[][8] = {
489 {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
490 /* delay 20 ms */
491 {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
492 {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
493 {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
494 {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
495 {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
496 {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
497 {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
498 {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
499 {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
500 {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
501 {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
502 {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
503 {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
504 {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
505 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
506 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
507 /*******/
508 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
509 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
510 {0xb1, 0x5c, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, /* shutter width */
511 {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */
512 {0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */
513 /*******/
514 {0xb1, 0x5c, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x10}, /* vert blanking */
515 {0xb1, 0x5c, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, /* horiz blanking */
516 {0xd1, 0x5c, 0x2c, 0x00, 0xad, 0x00, 0xad, 0x10}, /* blue gain */
517 {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
518 {}
519};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300520static const u8 om6802_sensor_init[][8] = {
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300521 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
522 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
523 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
524 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
525/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
526 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
527 /* white balance & auto-exposure */
528/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
529 * set color mode */
530/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
531 * max AGC value in AE */
532/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
533 * preset AGC */
534/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
535 * preset brightness */
536/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
537 * preset contrast */
538/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
539 * preset gamma */
540 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
541 /* luminance mode (0x4f = AE) */
542 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
543 /* preset shutter */
544/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
545 * auto frame rate */
546/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
547
548/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
549/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
550/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
551/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
552 {}
553};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300554static const u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300555 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
556 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
557/* win: delay 20ms */
558 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
559 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
560/* win: delay 20ms */
561 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300562/* win: i2c_r from 00 to 80 */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300563 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
564 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
565 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
566 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
567 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
568 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
569 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
570 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
571 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
572 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
573 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
574 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
575 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
576 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
577 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
578 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
579 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
580 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
581 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
582 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
583 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
584 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
585 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
586 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
587 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
588 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
589/* */
590 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
591 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
592/*fixme: + 0x12, 0x04*/
Jean-Francois Moine6c862742008-09-08 04:57:26 -0300593/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
594 * set by setvflip */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300595 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
596 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
597 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300598/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300599 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
600 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
601 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300602/* */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300603 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine91de65a2008-09-03 17:12:18 -0300604/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -0300605 {}
606};
Jean-Francois Moine62703302008-11-11 08:42:56 -0300607
Jean-Francois Moine98819182009-01-19 07:37:33 -0300608static const u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine62703302008-11-11 08:42:56 -0300609 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
610 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
611 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
612 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
613 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
614 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
615 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
616 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
617 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
618 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
619 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
620 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
621 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
622 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
623 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
624 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
625 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
626 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
627 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
628 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
629 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
630
631 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
632/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
633/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
634 {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
635/*...*/
636/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
637/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
638 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
639 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
640/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
641/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
642/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
643/*...*/
644 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
645/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
646/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
647/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
648/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
649/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
650
651 {}
652};
653
Jean-Francois Moine98819182009-01-19 07:37:33 -0300654static const u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300656/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300657 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300658 /* Outformat = rawRGB */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300659 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300660 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300661 /* GAIN BLUE RED VREF */
662 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
663 /* COM 1 BAVE GEAVE AECHH */
664 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
665 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300666 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667 /* AECH CLKRC COM7 COM8 */
668 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
669 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
670 /* HSTART HSTOP VSTRT VSTOP */
671 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
672 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
673 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
674 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300675/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
676 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 /* AEW AEB VPT BBIAS */
678 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
679 /* GbBIAS RSVD EXHCH EXHCL */
680 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
681 /* RBIAS ADVFL ASDVFH YAVE */
682 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
683 /* HSYST HSYEN HREF */
684 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
685 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
686 /* ADC ACOM OFON TSLB */
687 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
688 /* COM11 COM12 COM13 COM14 */
689 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
690 /* EDGE COM15 COM16 COM17 */
691 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
692 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
693 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
694 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
695 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
696 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
697 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
698 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
699 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
700 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
701 /* LCC1 LCC2 LCC3 LCC4 */
702 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300703 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300705 /* band gap reference [0:3] DBLV */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
707 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
708 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
709 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
710 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
711 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
712 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
713 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
714 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300715 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300717 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718 /* bits[3..0]reserved */
719 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
720 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
721 /* VREF vertical frame ctrl */
722 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300723 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
724 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
725 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
726 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
727/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728/****** (some exchanges in the win trace) ******/
729 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300730 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
731 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
732 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
733/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734/****** (some exchanges in the win trace) ******/
Jean-Francois Moine738608a2008-07-28 06:41:51 -0300735/******!! startsensor KO if changed !!****/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
737 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
738 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
739 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300740 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742
Jean-Francois Moine98819182009-01-19 07:37:33 -0300743static const u8 qtable4[] = {
744 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06,
745 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11,
746 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f,
747 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15,
748 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d,
749 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23,
750 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30,
751 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29,
752 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
753 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29,
754 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
755 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
756 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
757 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
758 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
759 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300760};
761
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300762/* read <len> bytes to gspca_dev->usb_buf */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300763static void reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine98819182009-01-19 07:37:33 -0300764 u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300766#ifdef GSPCA_DEBUG
767 if (len > USB_BUF_SZ) {
768 err("reg_r: buffer overflow");
769 return;
770 }
771#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300772 usb_control_msg(gspca_dev->dev,
773 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774 0,
775 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
776 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300779 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300780}
781
Jean-Francois Moine60017612008-07-18 08:46:19 -0300782static void reg_w1(struct gspca_dev *gspca_dev,
Jean-Francois Moine98819182009-01-19 07:37:33 -0300783 u16 value,
784 u8 data)
Jean-Francois Moine60017612008-07-18 08:46:19 -0300785{
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300786 PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300787 gspca_dev->usb_buf[0] = data;
788 usb_control_msg(gspca_dev->dev,
789 usb_sndctrlpipe(gspca_dev->dev, 0),
790 0x08,
791 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
792 value,
793 0,
794 gspca_dev->usb_buf, 1,
795 500);
796}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300797static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine98819182009-01-19 07:37:33 -0300798 u16 value,
799 const u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800 int len)
801{
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300802 PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
Jean-Francois Moine60017612008-07-18 08:46:19 -0300803 value, buffer[0], buffer[1]);
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300804#ifdef GSPCA_DEBUG
805 if (len > USB_BUF_SZ) {
806 err("reg_w: buffer overflow");
807 return;
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300808 }
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300809#endif
810 memcpy(gspca_dev->usb_buf, buffer, len);
811 usb_control_msg(gspca_dev->dev,
812 usb_sndctrlpipe(gspca_dev->dev, 0),
813 0x08,
814 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
815 value, 0,
816 gspca_dev->usb_buf, len,
817 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818}
819
Jean-Francois Moine60017612008-07-18 08:46:19 -0300820/* I2C write 1 byte */
Jean-Francois Moine98819182009-01-19 07:37:33 -0300821static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822{
823 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300824
Jean-Francois Moine60017612008-07-18 08:46:19 -0300825 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
826 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
827 gspca_dev->usb_buf[1] = sd->i2c_base;
828 gspca_dev->usb_buf[2] = reg;
829 gspca_dev->usb_buf[3] = val;
830 gspca_dev->usb_buf[4] = 0;
831 gspca_dev->usb_buf[5] = 0;
832 gspca_dev->usb_buf[6] = 0;
833 gspca_dev->usb_buf[7] = 0x10;
834 usb_control_msg(gspca_dev->dev,
835 usb_sndctrlpipe(gspca_dev->dev, 0),
836 0x08,
837 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
838 0x08, /* value = i2c */
839 0,
840 gspca_dev->usb_buf, 8,
841 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842}
843
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300844/* I2C write 8 bytes */
845static void i2c_w8(struct gspca_dev *gspca_dev,
Jean-Francois Moine98819182009-01-19 07:37:33 -0300846 const u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300848 memcpy(gspca_dev->usb_buf, buffer, 8);
849 usb_control_msg(gspca_dev->dev,
850 usb_sndctrlpipe(gspca_dev->dev, 0),
851 0x08,
852 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
853 0x08, 0, /* value, index */
854 gspca_dev->usb_buf, 8,
855 500);
Jean-Francois Moine8d768e12008-09-21 03:28:55 -0300856 msleep(2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857}
858
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300859/* read 5 bytes in gspca_dev->usb_buf */
Jean-Francois Moine98819182009-01-19 07:37:33 -0300860static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300861{
862 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine98819182009-01-19 07:37:33 -0300863 u8 mode[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864
Hans de Goede3647fea2008-07-15 05:36:30 -0300865 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 mode[1] = sd->i2c_base;
867 mode[2] = reg;
868 mode[3] = 0;
869 mode[4] = 0;
870 mode[5] = 0;
871 mode[6] = 0;
872 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300873 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300874 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300875 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300877 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300878 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300879 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880}
881
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300882static int hv7131r_probe(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300884 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300886 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300888 i2c_r5(gspca_dev, 0); /* read sensor id */
889 if (gspca_dev->usb_buf[0] == 0x02
890 && gspca_dev->usb_buf[1] == 0x09
891 && gspca_dev->usb_buf[2] == 0x01
892 && gspca_dev->usb_buf[3] == 0x00
893 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
Jean-Francois Moine577cbf42008-12-05 06:18:37 -0300895 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300897 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300898 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
899 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
901 return -ENODEV;
902}
903
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300904static int mi0360_probe(struct gspca_dev *gspca_dev)
905{
906 int i, j;
907 u16 val;
908 static const u8 probe_tb[][4][8] = {
909 {
910 {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
911 {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
912 {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
913 {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
914 },
915 {
916 {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
917 {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
918 {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
919 {}
920 },
921 };
922
923 for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
924 reg_w1(gspca_dev, 0x17, 0x62);
925 reg_w1(gspca_dev, 0x01, 0x08);
926 for (j = 0; j < 3; j++)
927 i2c_w8(gspca_dev, probe_tb[i][j]);
928 msleep(2);
929 reg_r(gspca_dev, 0x0a, 5);
930 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
931 if (probe_tb[i][3][0] != 0)
932 i2c_w8(gspca_dev, probe_tb[i][3]);
933 reg_w1(gspca_dev, 0x01, 0x29);
934 reg_w1(gspca_dev, 0x17, 0x42);
935 if (val != 0xffff)
936 break;
937 }
938 switch (val) {
939 case 0x823a:
940 PDEBUG(D_PROBE, "Sensor mt9v111");
941 return SENSOR_MT9V111;
942 case 0x8243:
943 PDEBUG(D_PROBE, "Sensor mi0360");
944 return SENSOR_MI0360;
945 }
946 PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
947 return SENSOR_MI0360;
948}
949
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moine98819182009-01-19 07:37:33 -0300951 const u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952{
953 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine98819182009-01-19 07:37:33 -0300954 const u8 *reg9a;
955 static const u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300957 static const u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moine98819182009-01-19 07:37:33 -0300959 static const u8 regd4[] = {0x60, 0x00, 0x00};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960
Jean-Francois Moine60017612008-07-18 08:46:19 -0300961 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300962 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963
964 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300965 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
966 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300967 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300968 switch (sd->bridge) {
969 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970 reg9a = reg9a_sn9c325;
971 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300972 default:
973 reg9a = reg9a_def;
974 break;
975 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300976 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -0300978 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300979
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300980 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300981
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300982 switch (sd->sensor) {
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -0300983 case SENSOR_MT9V111:
984 reg_w1(gspca_dev, 0x01, 0x61);
985 reg_w1(gspca_dev, 0x17, 0x61);
986 reg_w1(gspca_dev, 0x01, 0x60);
987 reg_w1(gspca_dev, 0x01, 0x40);
988 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300989 case SENSOR_OM6802:
Jean-Francois Moine4f30f6c2008-09-03 16:48:05 -0300990 reg_w1(gspca_dev, 0x02, 0x71);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -0300991 reg_w1(gspca_dev, 0x01, 0x42);
992 reg_w1(gspca_dev, 0x17, 0x64);
993 reg_w1(gspca_dev, 0x01, 0x42);
994 break;
Jean-Francois Moine05b809c2008-09-03 16:47:59 -0300995/*jfm: from win trace */
996 case SENSOR_OV7630:
997 reg_w1(gspca_dev, 0x01, 0x61);
998 reg_w1(gspca_dev, 0x17, 0xe2);
999 reg_w1(gspca_dev, 0x01, 0x60);
1000 reg_w1(gspca_dev, 0x01, 0x40);
1001 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001002 case SENSOR_OV7648:
Jean-Francois Moine62703302008-11-11 08:42:56 -03001003 reg_w1(gspca_dev, 0x01, 0x63);
1004 reg_w1(gspca_dev, 0x17, 0x20);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001005 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001006 break;
Jean-Francois Moine91de65a2008-09-03 17:12:18 -03001007/*jfm: from win trace */
1008 case SENSOR_OV7660:
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001009 if (sd->bridge == BRIDGE_SN9C120) {
1010 reg_w1(gspca_dev, 0x01, 0x61);
1011 reg_w1(gspca_dev, 0x17, 0x20);
1012 reg_w1(gspca_dev, 0x01, 0x60);
1013 reg_w1(gspca_dev, 0x01, 0x40);
1014 break;
1015 }
1016 /* fall thru */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001017 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001018 reg_w1(gspca_dev, 0x01, 0x43);
1019 reg_w1(gspca_dev, 0x17, 0x61);
1020 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001021 if (sd->sensor == SENSOR_HV7131R) {
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001022 if (hv7131r_probe(gspca_dev) < 0)
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001023 return -ENODEV;
1024 }
1025 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 }
1027 return 0;
1028}
1029
1030static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
1031{
1032 int i = 0;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001033 static const u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001034 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
1035
1036 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001037 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038 i++;
1039 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001040 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001041}
1042
1043static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
1044{
1045 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046
1047 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001048 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049 i++;
1050 }
1051}
1052
1053static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
1054{
1055 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056
1057 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001058 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059 i++;
1060 }
1061}
1062
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001063static void mt9v111_InitSensor(struct gspca_dev *gspca_dev)
1064{
1065 int i = 0;
1066
1067 i2c_w8(gspca_dev, mt9v111_sensor_init[i]);
1068 i++;
1069 msleep(20);
1070 while (mt9v111_sensor_init[i][0]) {
1071 i2c_w8(gspca_dev, mt9v111_sensor_init[i]);
1072 i++;
1073 }
1074}
1075
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001076static void om6802_InitSensor(struct gspca_dev *gspca_dev)
1077{
1078 int i = 0;
1079
1080 while (om6802_sensor_init[i][0]) {
1081 i2c_w8(gspca_dev, om6802_sensor_init[i]);
1082 i++;
1083 }
1084}
1085
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001086static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
1087{
1088 int i = 0;
1089
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001090 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
1091 i++;
1092 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001093 i++;
1094 msleep(20);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001095 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
1096 i++;
1097 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
1098 i++;
1099 msleep(20);
1100 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
1101 i++;
1102/*jfm:win i2c_r from 00 to 80*/
1103
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001104 while (ov7630_sensor_init[i][0]) {
1105 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
1106 i++;
1107 }
1108}
1109
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
1111{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 int i = 0;
1113
Jean-Francois Moine62703302008-11-11 08:42:56 -03001114 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
1115 i++;
1116/* win: dble reset */
1117 i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
1118 i++;
1119 msleep(20);
1120/* win: i2c reg read 00..7f */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001121 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001122 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001123 i++;
1124 }
1125}
1126
1127static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
1128{
1129 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001130
Jean-Francois Moine60017612008-07-18 08:46:19 -03001131 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
1132 i++;
1133 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001134 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001135 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001136 i++;
1137 }
1138}
1139
1140/* this function is called at probe time */
1141static int sd_config(struct gspca_dev *gspca_dev,
1142 const struct usb_device_id *id)
1143{
1144 struct sd *sd = (struct sd *) gspca_dev;
1145 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001146
1147 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001148 cam->cam_mode = vga_mode;
1149 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001150
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001151 sd->bridge = id->driver_info >> 16;
1152 sd->sensor = id->driver_info >> 8;
1153 sd->i2c_base = id->driver_info;
1154
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001155 sd->brightness = BRIGHTNESS_DEF;
1156 sd->contrast = CONTRAST_DEF;
1157 sd->colors = COLOR_DEF;
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001158 sd->blue = BLUE_BALANCE_DEF;
1159 sd->red = RED_BALANCE_DEF;
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -03001160 sd->gamma = GAMMA_DEF;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001161 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001162 sd->ag_cnt = -1;
Jean-Francois Moine0cae8962008-10-17 07:48:24 -03001163 sd->vflip = VFLIP_DEF;
1164 sd->infrared = INFRARED_DEF;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001165
Jean-Francois Moine577cbf42008-12-05 06:18:37 -03001166 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001167 return 0;
1168}
1169
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001170/* this function is called at probe and resume time */
1171static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001172{
1173 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001174 u8 regGpio[] = { 0x29, 0x74 };
1175 u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001176
Hans de Goede3647fea2008-07-15 05:36:30 -03001177 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001178 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001179 reg_r(gspca_dev, 0x00, 1);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001180 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1181 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001182 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001183 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
Hans de Goede3647fea2008-07-15 05:36:30 -03001184 switch (sd->bridge) {
1185 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186 if (regF1 != 0x11)
1187 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001188 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001189 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001190 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 if (regF1 != 0x11)
1192 return -ENODEV;
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001193 if (sd->sensor == SENSOR_MI0360) {
1194 sd->sensor = mi0360_probe(gspca_dev);
1195 if (sd->sensor == SENSOR_MT9V111)
1196 sd->i2c_base = 0x5c;
1197 }
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001198 reg_w(gspca_dev, 0x01, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001200 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201 if (regF1 != 0x12)
1202 return -ENODEV;
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001203 if (sd->sensor == SENSOR_MI0360) {
1204 sd->sensor = mi0360_probe(gspca_dev);
1205 if (sd->sensor == SENSOR_MT9V111)
1206 sd->i2c_base = 0x5c;
1207 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208 regGpio[1] = 0x70;
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001209 reg_w(gspca_dev, 0x01, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 break;
1211 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001212/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -03001213/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001214 if (regF1 != 0x12)
1215 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001216 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 break;
1218 }
1219
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001220 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001221
1222 return 0;
1223}
1224
Jean-Francois Moine98819182009-01-19 07:37:33 -03001225static u32 setexposure(struct gspca_dev *gspca_dev,
1226 u32 expo)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227{
1228 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229
1230 switch (sd->sensor) {
1231 case SENSOR_HV7131R: {
Jean-Francois Moine98819182009-01-19 07:37:33 -03001232 u8 Expodoit[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1234
1235 Expodoit[3] = expo >> 16;
1236 Expodoit[4] = expo >> 8;
1237 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001238 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001239 break;
1240 }
1241 case SENSOR_MI0360: {
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001242 u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001243 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001244 static const u8 doit[] = /* update sensor */
1245 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1246 static const u8 sensorgo[] = /* sensor on */
1247 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001248
1249 if (expo > 0x0635)
1250 expo = 0x0635;
1251 else if (expo < 0x0001)
1252 expo = 0x0001;
1253 expoMi[3] = expo >> 8;
1254 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001255 i2c_w8(gspca_dev, expoMi);
1256 i2c_w8(gspca_dev, doit);
1257 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001258 break;
1259 }
1260 case SENSOR_MO4000: {
Jean-Francois Moine98819182009-01-19 07:37:33 -03001261 u8 expoMof[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001262 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001263 u8 expoMo10[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001264 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001265 static const u8 gainMo[] =
1266 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001267
1268 if (expo > 0x1fff)
1269 expo = 0x1fff;
1270 else if (expo < 0x0001)
1271 expo = 0x0001;
1272 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001273 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001274 expoMo10[3] = ((expo & 0x1c00) >> 10)
1275 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001276 i2c_w8(gspca_dev, expoMo10);
1277 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001278 PDEBUG(D_FRAM, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001279 ((expoMo10[3] & 0x07) << 10)
1280 | (expoMof[3] << 2)
1281 | ((expoMo10[3] & 0x30) >> 4));
1282 break;
1283 }
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001284 case SENSOR_MT9V111: {
1285 u8 expo_c1[] =
1286 { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
1287
1288 if (expo > 0x0280)
1289 expo = 0x0280;
1290 else if (expo < 0x0040)
1291 expo = 0x0040;
1292 expo_c1[3] = expo >> 8;
1293 expo_c1[4] = expo;
1294 i2c_w8(gspca_dev, expo_c1);
1295 break;
1296 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001297 case SENSOR_OM6802: {
Jean-Francois Moine98819182009-01-19 07:37:33 -03001298 u8 gainOm[] =
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001299 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1300
1301 if (expo > 0x03ff)
1302 expo = 0x03ff;
1303 if (expo < 0x0001)
1304 expo = 0x0001;
1305 gainOm[3] = expo >> 2;
1306 i2c_w8(gspca_dev, gainOm);
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001307 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001308 PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001309 break;
1310 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001311 }
1312 return expo;
1313}
1314
1315static void setbrightness(struct gspca_dev *gspca_dev)
1316{
1317 struct sd *sd = (struct sd *) gspca_dev;
1318 unsigned int expo;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001319 u8 k2;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001320
Jean-Francois Moineb1b056a2008-11-25 04:47:09 -03001321 k2 = ((int) sd->brightness - 0x8000) >> 10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001322 switch (sd->sensor) {
1323 case SENSOR_HV7131R:
1324 expo = sd->brightness << 4;
1325 if (expo > 0x002dc6c0)
1326 expo = 0x002dc6c0;
1327 else if (expo < 0x02a0)
1328 expo = 0x02a0;
1329 sd->exposure = setexposure(gspca_dev, expo);
1330 break;
1331 case SENSOR_MI0360:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001332 case SENSOR_MO4000:
1333 expo = sd->brightness >> 4;
1334 sd->exposure = setexposure(gspca_dev, expo);
1335 break;
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001336 case SENSOR_MT9V111:
1337 expo = sd->brightness >> 8;
1338 sd->exposure = setexposure(gspca_dev, expo);
1339 break;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001340 case SENSOR_OM6802:
1341 expo = sd->brightness >> 6;
1342 sd->exposure = setexposure(gspca_dev, expo);
Jean-Francois Moineb1b056a2008-11-25 04:47:09 -03001343 k2 = sd->brightness >> 11;
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001344 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001345 }
1346
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001347 if (sd->sensor != SENSOR_MT9V111)
1348 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001349}
1350
1351static void setcontrast(struct gspca_dev *gspca_dev)
1352{
1353 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001354 u8 k2;
1355 u8 contrast[6];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001356
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001357 k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */
1358 contrast[0] = (k2 + 1) / 2; /* red */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -03001359 contrast[1] = 0;
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001360 contrast[2] = k2; /* green */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -03001361 contrast[3] = 0;
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001362 contrast[4] = (k2 + 1) / 5; /* blue */
Jean-Francois Moine577cbf42008-12-05 06:18:37 -03001363 contrast[5] = 0;
1364 reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001365}
1366
1367static void setcolors(struct gspca_dev *gspca_dev)
1368{
1369 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001370 int i, v;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001371 u8 reg8a[12]; /* U & V gains */
1372 static s16 uv[6] = { /* same as reg84 in signed decimal */
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001373 -24, -38, 64, /* UR UG UB */
1374 62, -51, -9 /* VR VG VB */
1375 };
1376 for (i = 0; i < 6; i++) {
1377 v = uv[i] * sd->colors / COLOR_DEF;
Jean-Francois Moinebd088832008-12-02 06:58:57 -03001378 reg8a[i * 2] = v;
1379 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
Jean-Francois Moined55b83d2008-09-03 16:48:01 -03001380 }
Jean-Francois Moinebd088832008-12-02 06:58:57 -03001381 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001382}
1383
1384static void setredblue(struct gspca_dev *gspca_dev)
1385{
1386 struct sd *sd = (struct sd *) gspca_dev;
1387
1388 reg_w1(gspca_dev, 0x05, sd->red);
Jean-Francois Moine9c5f70f2008-09-03 16:48:04 -03001389/* reg_w1(gspca_dev, 0x07, 32); */
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001390 reg_w1(gspca_dev, 0x06, sd->blue);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001391}
1392
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -03001393static void setgamma(struct gspca_dev *gspca_dev)
1394{
1395 struct sd *sd = (struct sd *) gspca_dev;
1396 int i;
1397 u8 gamma[17];
1398 static const u8 delta[17] = {
1399 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
1400 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
1401 };
1402
1403 for (i = 0; i < sizeof gamma; i++)
1404 gamma[i] = gamma_def[i]
1405 + delta[i] * (sd->gamma - GAMMA_DEF) / 32;
1406 reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
1407}
1408
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001409static void setautogain(struct gspca_dev *gspca_dev)
1410{
1411 struct sd *sd = (struct sd *) gspca_dev;
1412
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001413 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1414 return;
1415 if (sd->autogain)
1416 sd->ag_cnt = AG_CNT_START;
1417 else
1418 sd->ag_cnt = -1;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001419}
1420
Jean-Francois Moine6c862742008-09-08 04:57:26 -03001421static void setvflip(struct sd *sd)
1422{
Jean-Francois Moine6c862742008-09-08 04:57:26 -03001423 i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
1424 sd->vflip ? 0x82 : 0x02);
1425}
1426
Jean-Francois Moine0cae8962008-10-17 07:48:24 -03001427static void setinfrared(struct sd *sd)
1428{
1429/*fixme: different sequence for StarCam Clip and StarCam 370i */
1430/* Clip */
1431 i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
1432 sd->infrared ? 0x66 : 0x64);
1433}
1434
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001435/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001436static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001437{
1438 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001439 int i;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001440 u8 reg1, reg17, reg18;
1441 const u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001442 int mode;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001443 static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1444 static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1445 static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1446 static const u8 CE_ov76xx[] =
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001447 { 0x32, 0xdd, 0x32, 0xdd };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001448
1449 sn9c1xx = sn_tb[(int) sd->sensor];
1450 configure_gpio(gspca_dev, sn9c1xx);
1451
Jean-Francois Moine60017612008-07-18 08:46:19 -03001452 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1453 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1454 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1455 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1456 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1457 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1458 reg_w1(gspca_dev, 0xd3, 0x50);
1459 reg_w1(gspca_dev, 0xc6, 0x00);
1460 reg_w1(gspca_dev, 0xc7, 0x00);
1461 reg_w1(gspca_dev, 0xc8, 0x50);
1462 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001463 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001464 switch (sd->sensor) {
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001465 case SENSOR_MT9V111:
1466 reg17 = 0xe0;
1467 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001468 case SENSOR_OV7630:
1469 reg17 = 0xe2;
1470 break;
1471 case SENSOR_OV7648:
Jean-Francois Moine62703302008-11-11 08:42:56 -03001472 reg17 = 0x20;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001473 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001474/*jfm: from win trace */
1475 case SENSOR_OV7660:
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001476 if (sd->bridge == BRIDGE_SN9C120) {
1477 reg17 = 0xa0;
1478 break;
1479 }
1480 /* fall thru */
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001481 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001482 reg17 = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001483 break;
1484 }
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001485 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001486/* set reg1 was here */
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001487 reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
1488 reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
1489 reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001490 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -03001491 setgamma(gspca_dev);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001492 for (i = 0; i < 8; i++)
1493 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001494 switch (sd->sensor) {
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001495 case SENSOR_MT9V111:
1496 reg_w1(gspca_dev, 0x9a, 0x07);
1497 reg_w1(gspca_dev, 0x99, 0x59);
1498 break;
Jean-Francois Moine62703302008-11-11 08:42:56 -03001499 case SENSOR_OV7648:
1500 reg_w1(gspca_dev, 0x9a, 0x0a);
1501 reg_w1(gspca_dev, 0x99, 0x60);
1502 break;
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001503 case SENSOR_OV7660:
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001504 if (sd->bridge == BRIDGE_SN9C120) {
1505 reg_w1(gspca_dev, 0x9a, 0x05);
1506 break;
1507 }
1508 /* fall thru */
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001509 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001510 reg_w1(gspca_dev, 0x9a, 0x08);
1511 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001512 break;
1513 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001514
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001515 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001516 if (mode)
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001517 reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001518 else
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001519 reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
1520 reg17 = 0x61; /* 0x:20: enable sensor clock */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001521 switch (sd->sensor) {
1522 case SENSOR_HV7131R:
1523 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001524 break;
1525 case SENSOR_MI0360:
1526 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001527 break;
1528 case SENSOR_MO4000:
1529 mo4000_InitSensor(gspca_dev);
1530 if (mode) {
1531/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1532 reg1 = 0x06; /* clk 24Mz */
1533 } else {
1534 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001535/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001536 }
1537 break;
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001538 case SENSOR_MT9V111:
1539 mt9v111_InitSensor(gspca_dev);
1540 if (mode) {
1541 reg1 = 0x04; /* 320 clk 48Mhz */
1542 } else {
1543/* reg1 = 0x06; * 640 clk 24Mz (done) */
1544 reg17 = 0xe2;
1545 }
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001546 case SENSOR_OM6802:
1547 om6802_InitSensor(gspca_dev);
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001548 reg17 = 0x64; /* 640 MCKSIZE */
1549 break;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001550 case SENSOR_OV7630:
1551 ov7630_InitSensor(gspca_dev);
Jean-Francois Moine6c862742008-09-08 04:57:26 -03001552 setvflip(sd);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001553 reg17 = 0xe2;
Jean-Francois Moine5b064da2008-09-03 16:48:08 -03001554 reg1 = 0x44;
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001555 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001556 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001557 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine62703302008-11-11 08:42:56 -03001558 reg17 = 0x21;
1559/* reg1 = 0x42; * 42 - 46? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001560 break;
1561 default:
1562/* case SENSOR_OV7660: */
1563 ov7660_InitSensor(gspca_dev);
Jean-Francois Moinedaa5cb42008-12-02 15:00:57 -03001564 if (sd->bridge == BRIDGE_SN9C120) {
1565 if (mode) { /* 320x240 - 160x120 */
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001566 reg17 = 0xa2;
1567 reg1 = 0x44; /* 48 Mhz, video trf eneble */
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001568 }
Jean-Francois Moinedaa5cb42008-12-02 15:00:57 -03001569 } else {
1570 reg17 = 0x22;
1571 reg1 = 0x06; /* 24 Mhz, video trf eneble
1572 * inverse power down */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001573 }
1574 break;
1575 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001576 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001577 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001578 switch (sd->sensor) {
1579 case SENSOR_OV7630:
1580 case SENSOR_OV7648:
Jean-Francois Moine674cbc62008-10-02 08:06:59 -03001581 case SENSOR_OV7660:
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001582 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001583 break;
1584 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001585 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001586 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1587 break;
1588 }
1589
1590 /* here change size mode 0 -> VGA; 1 -> CIF */
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001591 reg18 = sn9c1xx[0x18] | (mode << 4);
1592 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001593
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001594 reg_w(gspca_dev, 0x0100, qtable4, 0x40);
1595 reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001596
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001597 reg_w1(gspca_dev, 0x18, reg18);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001598
Jean-Francois Moine60017612008-07-18 08:46:19 -03001599 reg_w1(gspca_dev, 0x17, reg17);
Jean-Francois Moine1432f302008-11-21 04:34:15 -03001600 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001601 switch (sd->sensor) {
Jean-Francois Moine79a90982008-10-05 04:21:24 -03001602 case SENSOR_OV7630:
1603 setvflip(sd);
Jean-Francois Moine05b809c2008-09-03 16:47:59 -03001604 break;
1605 }
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001606 setbrightness(gspca_dev);
1607 setcontrast(gspca_dev);
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001608 setautogain(gspca_dev);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001609 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001610}
1611
1612static void sd_stopN(struct gspca_dev *gspca_dev)
1613{
1614 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001615 static const u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001616 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001617 static const u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001618 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001619 static const u8 stopov7648[] =
Jean-Francois Moine62703302008-11-11 08:42:56 -03001620 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine98819182009-01-19 07:37:33 -03001621 u8 data;
1622 const u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001623
1624 data = 0x0b;
1625 switch (sd->sensor) {
1626 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001627 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001628 data = 0x2b;
1629 break;
1630 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001631 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001632 data = 0x29;
1633 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001634 case SENSOR_OV7648:
Jean-Francois Moine62703302008-11-11 08:42:56 -03001635 i2c_w8(gspca_dev, stopov7648);
1636 /* fall thru */
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001637 case SENSOR_MT9V111:
Jean-Francois Moine62703302008-11-11 08:42:56 -03001638 case SENSOR_OV7630:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001639 data = 0x29;
1640 break;
1641 default:
Jean-Francois Moine8f47a3c2008-07-29 14:14:04 -03001642/* case SENSOR_MO4000: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001643/* case SENSOR_OV7660: */
1644 break;
1645 }
1646 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001647 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1648 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1649 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1650 reg_w1(gspca_dev, 0x01, data);
Jean-Francois Moine759aa3c2008-09-03 16:48:03 -03001651 reg_w1(gspca_dev, 0xf1, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001652}
1653
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001654static void do_autogain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001655{
1656 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001657 int delta;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001658 int expotimes;
Jean-Francois Moine98819182009-01-19 07:37:33 -03001659 u8 luma_mean = 130;
1660 u8 luma_delta = 20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001661
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001662 /* Thanks S., without your advice, autobright should not work :) */
1663 if (sd->ag_cnt < 0)
1664 return;
1665 if (--sd->ag_cnt >= 0)
1666 return;
1667 sd->ag_cnt = AG_CNT_START;
1668
1669 delta = atomic_read(&sd->avg_lum);
1670 PDEBUG(D_FRAM, "mean lum %d", delta);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001671 if (delta < luma_mean - luma_delta ||
1672 delta > luma_mean + luma_delta) {
1673 switch (sd->sensor) {
1674 case SENSOR_HV7131R:
1675 expotimes = sd->exposure >> 8;
1676 expotimes += (luma_mean - delta) >> 4;
1677 if (expotimes < 0)
1678 expotimes = 0;
1679 sd->exposure = setexposure(gspca_dev,
1680 (unsigned int) (expotimes << 8));
1681 break;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001682 default:
1683/* case SENSOR_MO4000: */
1684/* case SENSOR_MI0360: */
Jean-Francois Moine3ef2c5b2009-01-29 04:59:45 -03001685/* case SENSOR_MT9V111: */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001686/* case SENSOR_OM6802: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001687 expotimes = sd->exposure;
1688 expotimes += (luma_mean - delta) >> 6;
1689 if (expotimes < 0)
1690 expotimes = 0;
1691 sd->exposure = setexposure(gspca_dev,
1692 (unsigned int) expotimes);
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001693 setredblue(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001694 break;
1695 }
1696 }
1697}
1698
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001699/* scan the URB packets */
1700/* This function is run at interrupt level. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001701static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1702 struct gspca_frame *frame, /* target */
Jean-Francois Moine98819182009-01-19 07:37:33 -03001703 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001704 int len) /* iso packet length */
1705{
1706 struct sd *sd = (struct sd *) gspca_dev;
1707 int sof, avg_lum;
1708
1709 sof = len - 64;
1710 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1711
1712 /* end of frame */
1713 gspca_frame_add(gspca_dev, LAST_PACKET,
1714 frame, data, sof + 2);
1715 if (sd->ag_cnt < 0)
1716 return;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001717/* w1 w2 w3 */
1718/* w4 w5 w6 */
1719/* w7 w8 */
1720/* w4 */
1721 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1722/* w6 */
1723 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1724/* w2 */
1725 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1726/* w8 */
1727 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1728/* w5 */
1729 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1730 avg_lum >>= 4;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001731 atomic_set(&sd->avg_lum, avg_lum);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001732 return;
1733 }
1734 if (gspca_dev->last_packet_type == LAST_PACKET) {
1735
1736 /* put the JPEG 422 header */
Jean-Francois Moine36e819d2009-01-07 16:49:57 -03001737 jpeg_put_header(gspca_dev, frame, 0x21);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001738 }
1739 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1740}
1741
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001742static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1743{
1744 struct sd *sd = (struct sd *) gspca_dev;
1745
1746 sd->brightness = val;
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001747 if (gspca_dev->streaming)
1748 setbrightness(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001749 return 0;
1750}
1751
1752static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1753{
1754 struct sd *sd = (struct sd *) gspca_dev;
1755
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001756 *val = sd->brightness;
1757 return 0;
1758}
1759
1760static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1761{
1762 struct sd *sd = (struct sd *) gspca_dev;
1763
1764 sd->contrast = val;
Jean-Francois Moine91bd3412008-11-23 14:47:50 -03001765 if (gspca_dev->streaming)
1766 setcontrast(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001767 return 0;
1768}
1769
1770static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1771{
1772 struct sd *sd = (struct sd *) gspca_dev;
1773
1774 *val = sd->contrast;
1775 return 0;
1776}
1777
1778static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1779{
1780 struct sd *sd = (struct sd *) gspca_dev;
1781
1782 sd->colors = val;
1783 if (gspca_dev->streaming)
1784 setcolors(gspca_dev);
1785 return 0;
1786}
1787
1788static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1789{
1790 struct sd *sd = (struct sd *) gspca_dev;
1791
1792 *val = sd->colors;
1793 return 0;
1794}
1795
Jean-Francois Moine403123d2008-11-26 04:46:15 -03001796static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1797{
1798 struct sd *sd = (struct sd *) gspca_dev;
1799
1800 sd->blue = val;
1801 if (gspca_dev->streaming)
1802 setredblue(gspca_dev);
1803 return 0;
1804}
1805
1806static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1807{
1808 struct sd *sd = (struct sd *) gspca_dev;
1809
1810 *val = sd->blue;
1811 return 0;
1812}
1813
1814static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1815{
1816 struct sd *sd = (struct sd *) gspca_dev;
1817
1818 sd->red = val;
1819 if (gspca_dev->streaming)
1820 setredblue(gspca_dev);
1821 return 0;
1822}
1823
1824static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1825{
1826 struct sd *sd = (struct sd *) gspca_dev;
1827
1828 *val = sd->red;
1829 return 0;
1830}
1831
Jean-Francois Moine592f4eb2009-01-15 08:01:32 -03001832static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1833{
1834 struct sd *sd = (struct sd *) gspca_dev;
1835
1836 sd->gamma = val;
1837 if (gspca_dev->streaming)
1838 setgamma(gspca_dev);
1839 return 0;
1840}
1841
1842static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1843{
1844 struct sd *sd = (struct sd *) gspca_dev;
1845
1846 *val = sd->gamma;
1847 return 0;
1848}
1849
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001850static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1851{
1852 struct sd *sd = (struct sd *) gspca_dev;
1853
1854 sd->autogain = val;
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001855 if (gspca_dev->streaming)
1856 setautogain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001857 return 0;
1858}
1859
1860static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1861{
1862 struct sd *sd = (struct sd *) gspca_dev;
1863
1864 *val = sd->autogain;
1865 return 0;
1866}
1867
Jean-Francois Moine6c862742008-09-08 04:57:26 -03001868static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1869{
1870 struct sd *sd = (struct sd *) gspca_dev;
1871
1872 sd->vflip = val;
Jean-Francois Moine79a90982008-10-05 04:21:24 -03001873 if (gspca_dev->streaming)
1874 setvflip(sd);
Jean-Francois Moine6c862742008-09-08 04:57:26 -03001875 return 0;
1876}
1877
1878static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1879{
1880 struct sd *sd = (struct sd *) gspca_dev;
1881
1882 *val = sd->vflip;
1883 return 0;
1884}
1885
Jean-Francois Moine0cae8962008-10-17 07:48:24 -03001886static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1887{
1888 struct sd *sd = (struct sd *) gspca_dev;
1889
1890 sd->infrared = val;
1891 if (gspca_dev->streaming)
1892 setinfrared(sd);
1893 return 0;
1894}
1895
1896static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1897{
1898 struct sd *sd = (struct sd *) gspca_dev;
1899
1900 *val = sd->infrared;
1901 return 0;
1902}
1903
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001904/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001905static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001906 .name = MODULE_NAME,
1907 .ctrls = sd_ctrls,
1908 .nctrls = ARRAY_SIZE(sd_ctrls),
1909 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001910 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001911 .start = sd_start,
1912 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001913 .pkt_scan = sd_pkt_scan,
Jean-Francois Moinecebf3b62008-08-03 07:52:53 -03001914 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001915};
1916
1917/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001918#define BSI(bridge, sensor, i2c_addr) \
1919 .driver_info = (BRIDGE_ ## bridge << 16) \
1920 | (SENSOR_ ## sensor << 8) \
1921 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001922static const __devinitdata struct usb_device_id device_table[] = {
Hans de Goede222a07f2008-09-03 17:12:20 -03001923#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001924 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine7b537392008-09-07 11:56:49 -03001925 {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
Jean-Francois Moinea08d81a2008-11-22 04:53:31 -03001926#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001927 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1928 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
Jean-Francois Moinea08d81a2008-11-22 04:53:31 -03001929#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001930 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001931#endif
Jean-Francois Moine7e21fda2008-11-10 04:45:51 -03001932 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001933 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moine3319dc92008-12-01 14:44:02 -03001934 {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001935 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1936/* bw600.inf:
1937 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1938/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1939/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1940 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1941/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
Jean-Francois Moine661ab252009-01-29 16:03:19 -03001942 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001943/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1944/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1945 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1946/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1947/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1948 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1949 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
Jean-Francois Moine3c41cb72008-09-10 02:57:09 -03001950#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1951 {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1952#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001953/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1954/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1955/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
Jean-Francois Moined2d16e92008-09-03 16:47:23 -03001956 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1957/*bw600.inf:*/
Jean-Francois Moine62703302008-11-11 08:42:56 -03001958 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001959 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
Jean-Francois Moine6ab0b172008-09-03 16:47:34 -03001960 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001961/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Hans de Goede222a07f2008-09-03 17:12:20 -03001962#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001963 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001964#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001965 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
Jean-Francois Moine821ced22008-11-11 07:10:11 -03001966 {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001967#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001968 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1969 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1970/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001971#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001972 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001973 {}
1974};
1975MODULE_DEVICE_TABLE(usb, device_table);
1976
1977/* -- device connect -- */
1978static int sd_probe(struct usb_interface *intf,
1979 const struct usb_device_id *id)
1980{
1981 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1982 THIS_MODULE);
1983}
1984
1985static struct usb_driver sd_driver = {
1986 .name = MODULE_NAME,
1987 .id_table = device_table,
1988 .probe = sd_probe,
1989 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001990#ifdef CONFIG_PM
1991 .suspend = gspca_suspend,
1992 .resume = gspca_resume,
1993#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001994};
1995
1996/* -- module insert / remove -- */
1997static int __init sd_mod_init(void)
1998{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001999 int ret;
2000 ret = usb_register(&sd_driver);
2001 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03002002 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03002003 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002004 return 0;
2005}
2006static void __exit sd_mod_exit(void)
2007{
2008 usb_deregister(&sd_driver);
2009 info("deregistered");
2010}
2011
2012module_init(sd_mod_init);
2013module_exit(sd_mod_exit);