blob: 3e68b992695676b5bdaf3147367a6ecca26da9be [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine739570b2008-07-14 09:38:29 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_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
38 int avg_lum;
39 unsigned int exposure;
40
41 unsigned short brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 signed char ag_cnt;
47#define AG_CNT_START 13
48
49 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030050 unsigned char bridge;
51#define BRIDGE_SN9C102P 0
52#define BRIDGE_SN9C105 1
53#define BRIDGE_SN9C110 2
54#define BRIDGE_SN9C120 3
55#define BRIDGE_SN9C325 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056 char sensor; /* Type of image sensor chip */
57#define SENSOR_HV7131R 0
58#define SENSOR_MI0360 1
59#define SENSOR_MO4000 2
60#define SENSOR_OV7648 3
61#define SENSOR_OV7660 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030062 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
74
75static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076 {
77 {
78 .id = V4L2_CID_BRIGHTNESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Brightness",
81 .minimum = 0,
82 .maximum = 0xffff,
83 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030084#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030090 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
96 .maximum = 127,
97 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030098#define CONTRAST_DEF 63
99 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300100 },
101 .set = sd_setcontrast,
102 .get = sd_getcontrast,
103 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300104 {
105 {
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Color",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300112#define COLOR_DEF 127
113 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300114 },
115 .set = sd_setcolors,
116 .get = sd_getcolors,
117 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300118 {
119 {
120 .id = V4L2_CID_AUTOGAIN,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
122 .name = "Auto Gain",
123 .minimum = 0,
124 .maximum = 1,
125 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300126#define AUTOGAIN_DEF 1
127 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300128 },
129 .set = sd_setautogain,
130 .get = sd_getautogain,
131 },
132};
133
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300134static struct v4l2_pix_format vga_mode[] = {
135 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 160,
137 .sizeimage = 160 * 120 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 2},
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 .bytesperline = 320,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
144 .priv = 1},
145 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 640,
147 .sizeimage = 640 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150};
151
152/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300153static const __u8 sn_hv7131[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300155 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162};
163
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300164static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173};
174
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300175static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178/* reg9 rega regb regc regd rege regf reg10 reg11*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
185 0xd3, 0xdf, 0xea, 0xf5
186};
187
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300188static const __u8 sn_ov7648[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300189 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
190 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
192};
193
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300194static const __u8 sn_ov7660[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
197/* reg9 rega regb regc regd rege regf reg10 reg11*/
198 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
199/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300200 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300201/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203};
204
205/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300206static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207 sn_hv7131,
208 sn_mi0360,
209 sn_mo4000,
210 sn_ov7648,
211 sn_ov7660
212};
213
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300214static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
217};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300218static const __u8 regsn20_sn9c120[] = {
219 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
220 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
221};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300222static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300223 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
224 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
225};
226
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300227static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
229 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
230/* 0x00, 0x00, 0x00, 0x00, 0x00 */
231 0xf7, 0x0f, 0x0a, 0x00, 0x00
232};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300233static const __u8 reg84_sn9c120_1[] = {
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x0c, 0x00, 0x00
237};
238static const __u8 reg84_sn9c120_2[] = {
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x0c, 0x02, 0x3b
242};
243static const __u8 reg84_sn9c120_3[] = {
244 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
245 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
246 0xf5, 0x0f, 0x0c, 0x02, 0x3b
247};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300248static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300249 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
250 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
251 0xf8, 0x0f, 0x00, 0x00, 0x00
252};
253
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300254static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300255 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
256 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
258 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
262
263 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
268 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
269 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
270 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
271
272 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
277
278 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300283 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300284};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300285static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
287 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
290 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
291 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
292 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
308 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
309 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
311 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
313 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
315 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
318 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
319
320 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
323 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
324 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
325
326 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
327 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
328 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
330
331 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
332 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
333/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
334/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
335 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
336 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300337 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300339static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300360 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300362static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
364 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
365 /* Outformat ?? rawRGB */
366 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300367 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
368/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300369 /* GAIN BLUE RED VREF */
370 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
371 /* COM 1 BAVE GEAVE AECHH */
372 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
373 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300374 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
375/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376 /* AECH CLKRC COM7 COM8 */
377 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
378 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
379 /* HSTART HSTOP VSTRT VSTOP */
380 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
381 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
382 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
383 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300384 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
385/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386 /* AEW AEB VPT BBIAS */
387 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
388 /* GbBIAS RSVD EXHCH EXHCL */
389 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
390 /* RBIAS ADVFL ASDVFH YAVE */
391 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
392 /* HSYST HSYEN HREF */
393 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
394 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
395 /* ADC ACOM OFON TSLB */
396 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
397 /* COM11 COM12 COM13 COM14 */
398 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
399 /* EDGE COM15 COM16 COM17 */
400 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
402 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
404 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
405 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
406 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
408 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
409 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
410 /* LCC1 LCC2 LCC3 LCC4 */
411 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
412 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
413 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
414 /* band gap reference [0..3] DBLV */
415 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
420 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
421 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
422 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
423 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
424 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
425/****** (some exchanges in the win trace) ******/
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 /* bits[3..0]reserved */
428 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 /* VREF vertical frame ctrl */
431 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
433 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300435/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
436 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
437 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300438/****** (some exchanges in the win trace) ******/
439 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
440 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
441 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300443 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300444/****** (some exchanges in the win trace) ******/
445/**********startsensor KO if changed !!****/
446 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
450/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300451 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452};
453/* reg0x04 reg0x07 reg 0x10 */
454/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
455
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300456static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
459 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
460 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
461 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
462 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
464 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
465 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
466 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
467 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
468 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
469 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
471 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
472 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
473 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
474 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
475 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
476 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
477 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
478 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
479 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
480 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
481 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
482 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
483 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
484 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
486 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
487 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
488 * This is currently setting a
489 * blue tint, and some things more , i leave it here for future test if
490 * somene is having problems with color on this sensor
491 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
492 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
493 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
494 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
495 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
496 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
497 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
502 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
503 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
504 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
505 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
506 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
507 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
508/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300509 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510};
511
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300512static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
514 0x06, 0x08, 0x0A, 0x11,
515 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
516 0x19, 0x19, 0x17, 0x15,
517 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
518 0x21, 0x2E, 0x21, 0x23,
519 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
520 0x25, 0x29, 0x2C, 0x29,
521 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
522 0x17, 0x1B, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29,
527 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
528 0x29, 0x29, 0x29, 0x29
529};
530
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
532static void reg_r(struct gspca_dev *gspca_dev,
533 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300534{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300535 usb_control_msg(gspca_dev->dev,
536 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300537 0,
538 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
539 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300540 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541 500);
542}
543
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300544static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300546 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547 int len)
548{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300549 if (len <= sizeof gspca_dev->usb_buf) {
550 memcpy(gspca_dev->usb_buf, buffer, len);
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300553 0x08,
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
555 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300556 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300557 500);
558 } else {
559 __u8 *tmpbuf;
560
561 tmpbuf = kmalloc(len, GFP_KERNEL);
562 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300565 0x08,
566 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
568 tmpbuf, len,
569 500);
570 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300571 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300572}
573
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300574/* I2C write 2 bytes */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300575static void i2c_w2(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300576 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577{
578 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 __u8 mode[8];
580
581 /* is i2c ready */
Hans de Goede3647fea2008-07-15 05:36:30 -0300582 mode[0] = 0x81 | (2 << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300583 mode[1] = sd->i2c_base;
584 mode[2] = buffer[0];
585 mode[3] = buffer[1];
586 mode[4] = 0;
587 mode[5] = 0;
588 mode[6] = 0;
589 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300590 reg_w(gspca_dev, 0x08, mode, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591}
592
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300593/* I2C write 8 bytes */
594static void i2c_w8(struct gspca_dev *gspca_dev,
595 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300596{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 msleep(1);
599}
600
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300601/* read 5 bytes in gspca_dev->usb_buf */
602static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603{
604 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300605 __u8 mode[8];
606
Hans de Goede3647fea2008-07-15 05:36:30 -0300607 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 mode[1] = sd->i2c_base;
609 mode[2] = reg;
610 mode[3] = 0;
611 mode[4] = 0;
612 mode[5] = 0;
613 mode[6] = 0;
614 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 i2c_w8(gspca_dev, mode);
Hans de Goede3647fea2008-07-15 05:36:30 -0300616 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300618 i2c_w8(gspca_dev, mode);
619 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620}
621
622static int probesensor(struct gspca_dev *gspca_dev)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 __u8 reg02;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300626 static const __u8 datasend[] = { 2, 0 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627 /* reg val1 val2 val3 val4 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628
629 i2c_w2(gspca_dev, datasend);
630/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
631 msleep(10);
632 reg02 = 0x66;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300633 reg_w(gspca_dev, 0x02, &reg02, 1); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300635 i2c_r5(gspca_dev, 0); /* read sensor id */
636 if (gspca_dev->usb_buf[0] == 0x02
637 && gspca_dev->usb_buf[1] == 0x09
638 && gspca_dev->usb_buf[2] == 0x01
639 && gspca_dev->usb_buf[3] == 0x00
640 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
642 sd->sensor = SENSOR_HV7131R;
643 return SENSOR_HV7131R;
644 }
645 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300646 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
647 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
649 return -ENODEV;
650}
651
652static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300653 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654{
655 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656 __u8 data;
657 __u8 regF1;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300658 const __u8 *reg9a;
659 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300661 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300663 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
665
666
667 regF1 = 0x00;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300668 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300669 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670
671 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
673 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300674 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300675 switch (sd->bridge) {
676 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677 reg9a = reg9a_sn9c325;
678 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300679 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 reg9a = reg9a_sn9c120;
681 break;
682 default:
683 reg9a = reg9a_def;
684 break;
685 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300686 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687
688 data = 0x60; /*fixme:jfm 60 00 00 (3) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 reg_w(gspca_dev, 0xd4, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300691 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692
Hans de Goede3647fea2008-07-15 05:36:30 -0300693 switch (sd->bridge) {
694 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300696 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 data = 0x20;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300702 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300704 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300705 data = 0xae;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300708 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300709 break;
710 default:
711 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300712 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300715 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300716 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 }
718
719 if (sd->sensor == SENSOR_HV7131R) {
720 if (probesensor(gspca_dev) < 0)
721 return -ENODEV;
722 }
723 return 0;
724}
725
726static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
727{
728 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300729 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
731
732 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300733 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734 i++;
735 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300736 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737}
738
739static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
740{
741 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742
743 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300744 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745 i++;
746 }
747}
748
749static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
750{
751 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752
753 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300754 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755 i++;
756 }
757}
758
759static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
760{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761 int i = 0;
762
763 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300764 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 i++;
766 }
767}
768
769static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
770{
771 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772
773 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775 i++;
776 }
777}
778
779/* this function is called at probe time */
780static int sd_config(struct gspca_dev *gspca_dev,
781 const struct usb_device_id *id)
782{
783 struct sd *sd = (struct sd *) gspca_dev;
784 struct cam *cam;
785 __u16 vendor;
786 __u16 product;
787
788 vendor = id->idVendor;
789 product = id->idProduct;
790 sd->sensor = -1;
791 switch (vendor) {
792 case 0x0458: /* Genius */
793/* switch (product) {
794 case 0x7025: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300795 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300796 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300797 sd->i2c_base = 0x5d;
798/* break;
799 } */
800 break;
801 case 0x045e:
802/* switch (product) {
803 case 0x00f5:
804 case 0x00f7: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300805 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807 sd->i2c_base = 0x21;
808/* break;
809 } */
810 break;
811 case 0x0471: /* Philips */
812/* switch (product) {
813 case 0x0327:
814 case 0x0328:
815 case 0x0330: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300816 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 sd->i2c_base = 0x5d;
819/* break;
820 } */
821 break;
822 case 0x0c45: /* Sonix */
823 switch (product) {
824 case 0x6040:
Hans de Goede3647fea2008-07-15 05:36:30 -0300825 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300826/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
827/*fixme: MI0360 base=5d ? */
828 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 sd->i2c_base = 0x11;
830 break;
831/* case 0x607a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300832 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834 sd->i2c_base = 0x??;
835 break; */
836 case 0x607c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300837 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839 sd->i2c_base = 0x11;
840 break;
841/* case 0x607e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300842 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 sd->i2c_base = 0x??;
845 break; */
846 case 0x60c0:
Hans de Goede3647fea2008-07-15 05:36:30 -0300847 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 sd->i2c_base = 0x5d;
850 break;
851/* case 0x60c8: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300852 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854 sd->i2c_base = 0x??;
855 break; */
856/* case 0x60cc: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300857 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858 sd->sensor = SENSOR_HV7131GP;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859 sd->i2c_base = 0x??;
860 break; */
861 case 0x60ec:
Hans de Goede3647fea2008-07-15 05:36:30 -0300862 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 sd->i2c_base = 0x21;
865 break;
866/* case 0x60ef: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300867 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869 sd->i2c_base = 0x??;
870 break; */
871/* case 0x60fa: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300872 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 sd->i2c_base = 0x??;
875 break; */
876 case 0x60fb:
Hans de Goede3647fea2008-07-15 05:36:30 -0300877 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 sd->i2c_base = 0x21;
880 break;
881 case 0x60fc:
Hans de Goede3647fea2008-07-15 05:36:30 -0300882 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 sd->i2c_base = 0x11;
885 break;
886/* case 0x60fe: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300887 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 sd->i2c_base = 0x??;
890 break; */
891/* case 0x6108: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300892 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 sd->i2c_base = 0x??;
895 break; */
896/* case 0x6122: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300897 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 sd->i2c_base = 0x??;
900 break; */
901 case 0x612a:
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300902/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
Hans de Goede3647fea2008-07-15 05:36:30 -0300903 sd->bridge = BRIDGE_SN9C325;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 sd->i2c_base = 0x21;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300906/*fixme: sensor_init has base = 00 et 6e!*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 break;
908/* case 0x6123: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300909 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 sd->sensor = SENSOR_SanyoCCD;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911 sd->i2c_base = 0x??;
912 break; */
913 case 0x612c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300914 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 sd->i2c_base = 0x21;
917 break;
918/* case 0x612e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300919 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 sd->i2c_base = 0x??;
922 break; */
923/* case 0x612f: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300924 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300925 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 sd->i2c_base = 0x??;
927 break; */
928 case 0x6130:
Hans de Goede3647fea2008-07-15 05:36:30 -0300929 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 sd->i2c_base = 0x5d;
932 break;
933 case 0x6138:
Hans de Goede3647fea2008-07-15 05:36:30 -0300934 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 sd->i2c_base = 0x21;
937 break;
938/* case 0x613a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300939 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 sd->i2c_base = 0x??;
942 break; */
943 case 0x613b:
Hans de Goede3647fea2008-07-15 05:36:30 -0300944 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300945 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 sd->i2c_base = 0x21;
947 break;
948 case 0x613c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300949 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951 sd->i2c_base = 0x11;
952 break;
953/* case 0x613e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300954 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 sd->i2c_base = 0x??;
957 break; */
958 }
959 break;
960 }
961 if (sd->sensor < 0) {
962 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
963 vendor, product);
964 return -EINVAL;
965 }
966
967 cam = &gspca_dev->cam;
968 cam->dev_name = (char *) id->driver_info;
969 cam->epaddr = 0x01;
970 cam->cam_mode = vga_mode;
971 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300972
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300974 sd->brightness = BRIGHTNESS_DEF;
975 sd->contrast = CONTRAST_DEF;
976 sd->colors = COLOR_DEF;
977 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 return 0;
979}
980
981/* this function is called at open time */
982static int sd_open(struct gspca_dev *gspca_dev)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 __u8 regF1;
987 __u8 regGpio[] = { 0x29, 0x74 };
988
Hans de Goede3647fea2008-07-15 05:36:30 -0300989 /* setup a selector by bridge */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300991 reg_w(gspca_dev, 0xf1, &regF1, 1);
992 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
993 regF1 = gspca_dev->usb_buf[0];
994 reg_w(gspca_dev, 0xf1, &regF1, 1);
995 reg_r(gspca_dev, 0x00, 1);
996 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -0300997 switch (sd->bridge) {
998 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999 if (regF1 != 0x11)
1000 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001001 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001002 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001003 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004 if (regF1 != 0x11)
1005 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001006 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001008 case BRIDGE_SN9C110:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 if (regF1 != 0x12)
1010 return -ENODEV;
1011 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001012 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001014 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 if (regF1 != 0x12)
1016 return -ENODEV;
1017 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001018 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019 break;
1020 default:
Hans de Goede3647fea2008-07-15 05:36:30 -03001021/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022 if (regF1 != 0x12)
1023 return -ENODEV;
1024 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001025 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 break;
1027 }
1028
1029 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001030 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031
1032 return 0;
1033}
1034
1035static unsigned int setexposure(struct gspca_dev *gspca_dev,
1036 unsigned int expo)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001039 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001040 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001041 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001042 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001043 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1045
1046 switch (sd->sensor) {
1047 case SENSOR_HV7131R: {
1048 __u8 Expodoit[] =
1049 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1050
1051 Expodoit[3] = expo >> 16;
1052 Expodoit[4] = expo >> 8;
1053 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001054 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055 break;
1056 }
1057 case SENSOR_MI0360: {
1058 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1059 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1060
1061 if (expo > 0x0635)
1062 expo = 0x0635;
1063 else if (expo < 0x0001)
1064 expo = 0x0001;
1065 expoMi[3] = expo >> 8;
1066 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001067 i2c_w8(gspca_dev, expoMi);
1068 i2c_w8(gspca_dev, doit);
1069 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001070 break;
1071 }
1072 case SENSOR_MO4000: {
1073 __u8 expoMof[] =
1074 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1075 __u8 expoMo10[] =
1076 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1077
1078 if (expo > 0x1fff)
1079 expo = 0x1fff;
1080 else if (expo < 0x0001)
1081 expo = 0x0001;
1082 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001083 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001084 expoMo10[3] = ((expo & 0x1c00) >> 10)
1085 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001086 i2c_w8(gspca_dev, expoMo10);
1087 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001088 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089 ((expoMo10[3] & 0x07) << 10)
1090 | (expoMof[3] << 2)
1091 | ((expoMo10[3] & 0x30) >> 4));
1092 break;
1093 }
1094 }
1095 return expo;
1096}
1097
1098static void setbrightness(struct gspca_dev *gspca_dev)
1099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101 unsigned int expo;
1102 __u8 k2;
1103
1104 switch (sd->sensor) {
1105 case SENSOR_HV7131R:
1106 expo = sd->brightness << 4;
1107 if (expo > 0x002dc6c0)
1108 expo = 0x002dc6c0;
1109 else if (expo < 0x02a0)
1110 expo = 0x02a0;
1111 sd->exposure = setexposure(gspca_dev, expo);
1112 break;
1113 case SENSOR_MI0360:
1114 expo = sd->brightness >> 4;
1115 sd->exposure = setexposure(gspca_dev, expo);
1116 break;
1117 case SENSOR_MO4000:
1118 expo = sd->brightness >> 4;
1119 sd->exposure = setexposure(gspca_dev, expo);
1120 break;
1121 case SENSOR_OV7660:
1122 return; /*jfm??*/
1123 }
1124
1125 k2 = sd->brightness >> 10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001126 reg_w(gspca_dev, 0x96, &k2, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127}
1128
1129static void setcontrast(struct gspca_dev *gspca_dev)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132 __u8 k2;
1133 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1134
1135 if (sd->sensor == SENSOR_OV7660)
1136 return; /*jfm??*/
1137 k2 = sd->contrast;
1138 contrast[2] = k2;
1139 contrast[0] = (k2 + 1) >> 1;
1140 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001141 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142}
1143
1144static void setcolors(struct gspca_dev *gspca_dev)
1145{
1146 struct sd *sd = (struct sd *) gspca_dev;
1147 __u8 data;
1148 int colour;
1149
1150 colour = sd->colors - 128;
1151 if (colour > 0)
1152 data = (colour + 32) & 0x7f; /* blue */
1153 else
1154 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001155 reg_w(gspca_dev, 0x05, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001156}
1157
1158/* -- start the camera -- */
1159static void sd_start(struct gspca_dev *gspca_dev)
1160{
1161 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001162 int i;
1163 __u8 data;
1164 __u8 reg1;
1165 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001166 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001167 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001168 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1169 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1170 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1171 static const __u8 CA_sn9c120[] =
1172 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1173 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1174 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1176
1177 sn9c1xx = sn_tb[(int) sd->sensor];
1178 configure_gpio(gspca_dev, sn9c1xx);
1179
1180/*fixme:jfm this sequence should appear at end of sd_start */
1181/* with
1182 data = 0x44;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001183 reg_w(gspca_dev, 0x01, &data, 1); */
1184 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1185 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1186 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1187 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1188 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1189 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1190 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1191 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1192 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1193 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1194 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195/*fixme:jfm end of ending sequence */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001196 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001197 switch (sd->bridge) {
1198 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001200 break;
1201 case BRIDGE_SN9C120:
1202 data = 0xa0;
1203 break;
1204 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001206 break;
1207 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001208 reg_w(gspca_dev, 0x17, &data, 1);
1209 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1210 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1211 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1212 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001213 switch (sd->bridge) {
1214 case BRIDGE_SN9C325:
1215 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1216 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001218 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1219 sizeof reg84_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001220 data = 0x0a;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001221 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001222 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001223 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001224 break;
1225 case BRIDGE_SN9C120:
1226 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1227 sizeof regsn20_sn9c120);
1228 for (i = 0; i < 2; i++)
1229 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1230 sizeof reg84_sn9c120_1);
1231 for (i = 0; i < 6; i++)
1232 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1233 sizeof reg84_sn9c120_2);
1234 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1235 sizeof reg84_sn9c120_3);
1236 data = 0x05;
1237 reg_w(gspca_dev, 0x9a, &data, 1);
1238 data = 0x5b;
1239 reg_w(gspca_dev, 0x99, &data, 1);
1240 break;
1241 default:
1242 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001243 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001244 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001245 data = 0x08;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001246 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001247 data = 0x59;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001248 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001249 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001250 }
1251
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001252 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 reg1 = 0x02;
1254 reg17 = 0x61;
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 hv7131R_InitSensor(gspca_dev);
1258 if (mode)
1259 reg1 = 0x46; /* 320 clk 48Mhz */
1260 else
1261 reg1 = 0x06; /* 640 clk 24Mz */
1262 break;
1263 case SENSOR_MI0360:
1264 mi0360_InitSensor(gspca_dev);
1265 if (mode)
1266 reg1 = 0x46; /* 320 clk 48Mhz */
1267 else
1268 reg1 = 0x06; /* 640 clk 24Mz */
1269 break;
1270 case SENSOR_MO4000:
1271 mo4000_InitSensor(gspca_dev);
1272 if (mode) {
1273/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1274 reg1 = 0x06; /* clk 24Mz */
1275 } else {
1276 reg17 = 0x22; /* 640 MCKSIZE */
1277 reg1 = 0x06; /* 640 clk 24Mz */
1278 }
1279 break;
1280 case SENSOR_OV7648:
1281 reg17 = 0xa2;
1282 reg1 = 0x44;
1283 ov7648_InitSensor(gspca_dev);
1284/* if (mode)
1285 ; * 320x2...
1286 else
1287 ; * 640x... */
1288 break;
1289 default:
1290/* case SENSOR_OV7660: */
1291 ov7660_InitSensor(gspca_dev);
1292 if (mode) {
1293/* reg17 = 0x21; * 320 */
1294/* reg1 = 0x44; */
1295 reg1 = 0x46;
1296 } else {
1297 reg17 = 0xa2; /* 640 */
1298 reg1 = 0x40;
1299 }
1300 break;
1301 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001302 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001303 switch (sd->bridge) {
1304 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001305 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001306 break;
1307 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001308 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001309 break;
1310 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001311 switch (sd->bridge) {
1312 case BRIDGE_SN9C120: /*jfm ?? */
1313 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001314 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001315 break;
1316 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001317 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001318 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1319 break;
1320 }
1321
1322 /* here change size mode 0 -> VGA; 1 -> CIF */
1323 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001324 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001325
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001326 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1327 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328
1329 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001330 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001331
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001332 reg_w(gspca_dev, 0x17, &reg17, 1);
1333 reg_w(gspca_dev, 0x01, &reg1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001334 setbrightness(gspca_dev);
1335 setcontrast(gspca_dev);
1336}
1337
1338static void sd_stopN(struct gspca_dev *gspca_dev)
1339{
1340 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001341 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001342 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001343 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1345 __u8 regF1;
1346 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001347 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001348
1349 data = 0x0b;
1350 switch (sd->sensor) {
1351 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001352 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001353 data = 0x2b;
1354 break;
1355 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001356 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001357 data = 0x29;
1358 break;
1359 case SENSOR_MO4000:
1360 break;
1361 case SENSOR_OV7648:
1362 data = 0x29;
1363 break;
1364 default:
1365/* case SENSOR_OV7660: */
1366 break;
1367 }
1368 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001369 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1370 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1371 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1372 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001373 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001374 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001375}
1376
1377static void sd_stop0(struct gspca_dev *gspca_dev)
1378{
1379}
1380
1381static void sd_close(struct gspca_dev *gspca_dev)
1382{
1383}
1384
1385static void setautogain(struct gspca_dev *gspca_dev)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388 /* Thanks S., without your advice, autobright should not work :) */
1389 int delta;
1390 int expotimes = 0;
1391 __u8 luma_mean = 130;
1392 __u8 luma_delta = 20;
1393
1394 delta = sd->avg_lum;
1395 if (delta < luma_mean - luma_delta ||
1396 delta > luma_mean + luma_delta) {
1397 switch (sd->sensor) {
1398 case SENSOR_HV7131R:
1399 expotimes = sd->exposure >> 8;
1400 expotimes += (luma_mean - delta) >> 4;
1401 if (expotimes < 0)
1402 expotimes = 0;
1403 sd->exposure = setexposure(gspca_dev,
1404 (unsigned int) (expotimes << 8));
1405 break;
1406 case SENSOR_MO4000:
1407 case SENSOR_MI0360:
1408 expotimes = sd->exposure;
1409 expotimes += (luma_mean - delta) >> 6;
1410 if (expotimes < 0)
1411 expotimes = 0;
1412 sd->exposure = setexposure(gspca_dev,
1413 (unsigned int) expotimes);
1414 setcolors(gspca_dev);
1415 break;
1416 }
1417 }
1418}
1419
1420static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1421 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001422 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001423 int len) /* iso packet length */
1424{
1425 struct sd *sd = (struct sd *) gspca_dev;
1426 int sof, avg_lum;
1427
1428 sof = len - 64;
1429 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1430
1431 /* end of frame */
1432 gspca_frame_add(gspca_dev, LAST_PACKET,
1433 frame, data, sof + 2);
1434 if (sd->ag_cnt < 0)
1435 return;
1436 if (--sd->ag_cnt >= 0)
1437 return;
1438 sd->ag_cnt = AG_CNT_START;
1439/* w1 w2 w3 */
1440/* w4 w5 w6 */
1441/* w7 w8 */
1442/* w4 */
1443 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1444/* w6 */
1445 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1446/* w2 */
1447 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1448/* w8 */
1449 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1450/* w5 */
1451 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1452 avg_lum >>= 4;
1453 sd->avg_lum = avg_lum;
1454 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1455 setautogain(gspca_dev);
1456 return;
1457 }
1458 if (gspca_dev->last_packet_type == LAST_PACKET) {
1459
1460 /* put the JPEG 422 header */
1461 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1462 }
1463 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1464}
1465
1466static unsigned int getexposure(struct gspca_dev *gspca_dev)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001470
1471 switch (sd->sensor) {
1472 case SENSOR_HV7131R:
1473 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001474 i2c_r5(gspca_dev, 0x25);
1475 return (gspca_dev->usb_buf[0] << 16)
1476 | (gspca_dev->usb_buf[1] << 8)
1477 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001478 case SENSOR_MI0360:
1479 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001480 i2c_r5(gspca_dev, 0x09);
1481 return (gspca_dev->usb_buf[0] << 8)
1482 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001483 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001484 i2c_r5(gspca_dev, 0x0e);
1485 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1486 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1487 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001488 PDEBUG(D_CONF, "exposure %d",
1489 (hexpo << 10) | (mexpo << 2) | lexpo);
1490 return (hexpo << 10) | (mexpo << 2) | lexpo;
1491 default:
1492/* case SENSOR_OV7660: */
1493 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001494 i2c_r5(gspca_dev, 0x04);
1495 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1496 lexpo = gspca_dev->usb_buf[0] & 0x02;
1497 i2c_r5(gspca_dev, 0x08);
1498 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001499 return (hexpo << 10) | (mexpo << 2) | lexpo;
1500 }
1501}
1502
1503static void getbrightness(struct gspca_dev *gspca_dev)
1504{
1505 struct sd *sd = (struct sd *) gspca_dev;
1506
1507 /* hardcoded registers seem not readable */
1508 switch (sd->sensor) {
1509 case SENSOR_HV7131R:
1510/* sd->brightness = 0x7fff; */
1511 sd->brightness = getexposure(gspca_dev) >> 4;
1512 break;
1513 case SENSOR_MI0360:
1514 sd->brightness = getexposure(gspca_dev) << 4;
1515 break;
1516 case SENSOR_MO4000:
1517/* sd->brightness = 0x1fff; */
1518 sd->brightness = getexposure(gspca_dev) << 4;
1519 break;
1520 }
1521}
1522
1523static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1524{
1525 struct sd *sd = (struct sd *) gspca_dev;
1526
1527 sd->brightness = val;
1528 if (gspca_dev->streaming)
1529 setbrightness(gspca_dev);
1530 return 0;
1531}
1532
1533static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 getbrightness(gspca_dev);
1538 *val = sd->brightness;
1539 return 0;
1540}
1541
1542static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1543{
1544 struct sd *sd = (struct sd *) gspca_dev;
1545
1546 sd->contrast = val;
1547 if (gspca_dev->streaming)
1548 setcontrast(gspca_dev);
1549 return 0;
1550}
1551
1552static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 *val = sd->contrast;
1557 return 0;
1558}
1559
1560static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 sd->colors = val;
1565 if (gspca_dev->streaming)
1566 setcolors(gspca_dev);
1567 return 0;
1568}
1569
1570static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1571{
1572 struct sd *sd = (struct sd *) gspca_dev;
1573
1574 *val = sd->colors;
1575 return 0;
1576}
1577
1578static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1579{
1580 struct sd *sd = (struct sd *) gspca_dev;
1581
1582 sd->autogain = val;
1583 if (val)
1584 sd->ag_cnt = AG_CNT_START;
1585 else
1586 sd->ag_cnt = -1;
1587 return 0;
1588}
1589
1590static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1591{
1592 struct sd *sd = (struct sd *) gspca_dev;
1593
1594 *val = sd->autogain;
1595 return 0;
1596}
1597
1598/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001599static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001600 .name = MODULE_NAME,
1601 .ctrls = sd_ctrls,
1602 .nctrls = ARRAY_SIZE(sd_ctrls),
1603 .config = sd_config,
1604 .open = sd_open,
1605 .start = sd_start,
1606 .stopN = sd_stopN,
1607 .stop0 = sd_stop0,
1608 .close = sd_close,
1609 .pkt_scan = sd_pkt_scan,
1610};
1611
1612/* -- module initialisation -- */
1613#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001614static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001615#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001616 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1617 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1618 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1619 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1620 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001621#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001622 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1623 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1624 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1625 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1626 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1627 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1628 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1629 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1630 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001631#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001632 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1633 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1634 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1635 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001636#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001637 {}
1638};
1639MODULE_DEVICE_TABLE(usb, device_table);
1640
1641/* -- device connect -- */
1642static int sd_probe(struct usb_interface *intf,
1643 const struct usb_device_id *id)
1644{
1645 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1646 THIS_MODULE);
1647}
1648
1649static struct usb_driver sd_driver = {
1650 .name = MODULE_NAME,
1651 .id_table = device_table,
1652 .probe = sd_probe,
1653 .disconnect = gspca_disconnect,
1654};
1655
1656/* -- module insert / remove -- */
1657static int __init sd_mod_init(void)
1658{
1659 if (usb_register(&sd_driver) < 0)
1660 return -1;
1661 info("v%s registered", version);
1662 return 0;
1663}
1664static void __exit sd_mod_exit(void)
1665{
1666 usb_deregister(&sd_driver);
1667 info("deregistered");
1668}
1669
1670module_init(sd_mod_init);
1671module_exit(sd_mod_exit);