blob: eb5e1bfd79117a2517fd56fbe0a2ddb8ff3c6dfe [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 Moinea5ae2062008-07-04 11:16:16 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4)
28static const char version[] = "2.1.4";
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;
50 char sensor; /* Type of image sensor chip */
51#define SENSOR_HV7131R 0
52#define SENSOR_MI0360 1
53#define SENSOR_MO4000 2
54#define SENSOR_OV7648 3
55#define SENSOR_OV7660 4
56 unsigned char customid;
57#define SN9C102P 0
58#define SN9C105 1
59#define SN9C110 2
60#define SN9C120 3
61#define SN9C325 4
62 unsigned char i2c_base;
63 unsigned char i2c_ctrl_reg;
64};
65
66/* V4L2 controls supported by the driver */
67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
75
76static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030077 {
78 {
79 .id = V4L2_CID_BRIGHTNESS,
80 .type = V4L2_CTRL_TYPE_INTEGER,
81 .name = "Brightness",
82 .minimum = 0,
83 .maximum = 0xffff,
84 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030085#define BRIGHTNESS_DEF 0x7fff
86 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 },
88 .set = sd_setbrightness,
89 .get = sd_getbrightness,
90 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091 {
92 {
93 .id = V4L2_CID_CONTRAST,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Contrast",
96 .minimum = 0,
97 .maximum = 127,
98 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030099#define CONTRAST_DEF 63
100 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 },
102 .set = sd_setcontrast,
103 .get = sd_getcontrast,
104 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 {
106 {
107 .id = V4L2_CID_SATURATION,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Color",
110 .minimum = 0,
111 .maximum = 255,
112 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300113#define COLOR_DEF 127
114 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 },
116 .set = sd_setcolors,
117 .get = sd_getcolors,
118 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119 {
120 {
121 .id = V4L2_CID_AUTOGAIN,
122 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 .name = "Auto Gain",
124 .minimum = 0,
125 .maximum = 1,
126 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300127#define AUTOGAIN_DEF 1
128 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300129 },
130 .set = sd_setautogain,
131 .get = sd_getautogain,
132 },
133};
134
135static struct cam_mode vga_mode[] = {
136 {V4L2_PIX_FMT_JPEG, 160, 120, 2},
137 {V4L2_PIX_FMT_JPEG, 320, 240, 1},
138 {V4L2_PIX_FMT_JPEG, 640, 480, 0},
139};
140
141/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300142static const __u8 sn_hv7131[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
144/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
145 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
146/* rega regb regc regd rege regf reg10 reg11 */
147 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
148/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
150/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
151};
152
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300153static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
155/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
156 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
157/* rega regb regc regd rege regf reg10 reg11 */
158 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
159/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
162};
163
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300164static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
166/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
167 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
168/* reg9 rega regb regc regd rege regf reg10 reg11*/
169 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
170/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
172/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
173 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
174 0xd3, 0xdf, 0xea, 0xf5
175};
176
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300177static const __u8 sn_ov7648[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
179 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
180 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
181};
182
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300183static const __u8 sn_ov7660[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
185 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
186/* reg9 rega regb regc regd rege regf reg10 reg11*/
187 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
188/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
189 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, 0x07, 0x00, 0x00,
190/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
192};
193
194/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300195static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300196 sn_hv7131,
197 sn_mi0360,
198 sn_mo4000,
199 sn_ov7648,
200 sn_ov7660
201};
202
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300203static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
205 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
206};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300207static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300208 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
209 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
210};
211
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300212static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300213 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
214 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
215/* 0x00, 0x00, 0x00, 0x00, 0x00 */
216 0xf7, 0x0f, 0x0a, 0x00, 0x00
217};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300218static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300219 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
220 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
221 0xf8, 0x0f, 0x00, 0x00, 0x00
222};
223
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300224static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300225 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
226 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
227 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
228 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
229 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
230 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
231 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
232
233 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
234 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
235 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
236 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
237 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
238 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
239 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
240 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
241
242 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
243 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
244 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
245 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
246 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
247
248 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
249 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
250 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
251 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
252 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300253 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300255static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300256 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
257 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
258 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
260 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
262 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
263 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
264 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
265 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
266 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
267 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
268 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
269 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
270 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
272 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
275 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
278 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
279 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
281 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
282 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
283 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
284 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
285 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
287 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
288 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
289
290 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
291 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
292 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
294 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
295
296 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
297 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
298 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
299 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
300
301 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
302 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
303/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
304/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
305 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
306 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300307 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300308};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300309static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300310 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
311 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
312 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
315 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
316 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
317 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
318 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
319 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
320 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
321 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
322 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
323 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
324 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
325 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
327 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
328 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
329 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300330 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300331};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300332static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300333 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
334 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
335 /* Outformat ?? rawRGB */
336 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
337/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
338 * GAIN BLUE RED VREF */
339 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
340 /* GAIN BLUE RED VREF */
341 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
342 /* COM 1 BAVE GEAVE AECHH */
343 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
344 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
345/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
346 * AECH CLKRC COM7 COM8 */
347 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
348 /* AECH CLKRC COM7 COM8 */
349 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
350 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
351 /* HSTART HSTOP VSTRT VSTOP */
352 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
353 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
354 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
355 /* BOS GBOS GROS ROS (BGGR offset) */
356/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
357 * AEW AEB VPT BBIAS */
358 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
359 /* AEW AEB VPT BBIAS */
360 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
361 /* GbBIAS RSVD EXHCH EXHCL */
362 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
363 /* RBIAS ADVFL ASDVFH YAVE */
364 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
365 /* HSYST HSYEN HREF */
366 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
367 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
368 /* ADC ACOM OFON TSLB */
369 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
370 /* COM11 COM12 COM13 COM14 */
371 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
372 /* EDGE COM15 COM16 COM17 */
373 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
374 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
375 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
376 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
377 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
378 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
379 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
380 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
381 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
382 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
383 /* LCC1 LCC2 LCC3 LCC4 */
384 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
385 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
386 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
387 /* band gap reference [0..3] DBLV */
388 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
389 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
390 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
391 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
392 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
393 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
394 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
395 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
396 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
397 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
398/****** (some exchanges in the win trace) ******/
399 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
400 /* bits[3..0]reserved */
401 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
402 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
403 /* VREF vertical frame ctrl */
404 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
405 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
406 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
407 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
408 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10},
409/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, */
410/****** (some exchanges in the win trace) ******/
411 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
412 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
413 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
414 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
415/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, */
416/****** (some exchanges in the win trace) ******/
417/**********startsensor KO if changed !!****/
418 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
420 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
422/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300423 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300424};
425/* reg0x04 reg0x07 reg 0x10 */
426/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
427
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300428static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300429 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
430 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
431 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
432 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
433 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
434 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
435 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
436 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
437 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
438 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
439 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
440 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
441 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
442 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
443 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
444 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
445 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
446 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
447 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
448 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
449 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
450 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
451 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
452 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
453 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
454 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
455 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
456 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
457 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
458 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
459 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
460 * This is currently setting a
461 * blue tint, and some things more , i leave it here for future test if
462 * somene is having problems with color on this sensor
463 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
464 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
465 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
466 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
467 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
468 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
469 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
470 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
471 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
472 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
473 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
474 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
475 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
476 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
477 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
478 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
479 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
480/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300481 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300482};
483
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300484static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300485 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
486 0x06, 0x08, 0x0A, 0x11,
487 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
488 0x19, 0x19, 0x17, 0x15,
489 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
490 0x21, 0x2E, 0x21, 0x23,
491 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
492 0x25, 0x29, 0x2C, 0x29,
493 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
494 0x17, 0x1B, 0x29, 0x29,
495 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
496 0x29, 0x29, 0x29, 0x29,
497 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
498 0x29, 0x29, 0x29, 0x29,
499 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
500 0x29, 0x29, 0x29, 0x29
501};
502
503static void reg_r(struct usb_device *dev,
504 __u16 value,
505 __u8 *buffer, int len)
506{
507 usb_control_msg(dev,
508 usb_rcvctrlpipe(dev, 0),
509 0,
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
511 value, 0,
512 buffer, len,
513 500);
514}
515
516static void reg_w(struct usb_device *dev,
517 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300518 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 int len)
520{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300521 if (len < 16) {
522 __u8 tmpbuf[16];
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300523
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300524 memcpy(tmpbuf, buffer, len);
525 usb_control_msg(dev,
526 usb_sndctrlpipe(dev, 0),
527 0x08,
528 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
529 value, 0,
530 tmpbuf, len,
531 500);
532 } else {
533 __u8 *tmpbuf;
534
535 tmpbuf = kmalloc(len, GFP_KERNEL);
536 memcpy(tmpbuf, buffer, len);
537 usb_control_msg(dev,
538 usb_sndctrlpipe(dev, 0),
539 0x08,
540 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
541 value, 0,
542 tmpbuf, len,
543 500);
544 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300545 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546}
547
548/* write 2 bytes */
549static void i2c_w2(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300550 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551{
552 struct sd *sd = (struct sd *) gspca_dev;
553 struct usb_device *dev = gspca_dev->dev;
554 __u8 mode[8];
555
556 /* is i2c ready */
557 mode[0] = sd->i2c_ctrl_reg | (2 << 4);
558 mode[1] = sd->i2c_base;
559 mode[2] = buffer[0];
560 mode[3] = buffer[1];
561 mode[4] = 0;
562 mode[5] = 0;
563 mode[6] = 0;
564 mode[7] = 0x10;
565 reg_w(dev, 0x08, mode, 8);
566}
567
568/* write 8 bytes */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569static void i2c_w8(struct usb_device *dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570{
571 reg_w(dev, 0x08, buffer, 8);
572 msleep(1);
573}
574
575/* read 5 bytes */
576static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300577 __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578{
579 struct sd *sd = (struct sd *) gspca_dev;
580 struct usb_device *dev = gspca_dev->dev;
581 __u8 mode[8];
582
583 mode[0] = sd->i2c_ctrl_reg | 0x10;
584 mode[1] = sd->i2c_base;
585 mode[2] = reg;
586 mode[3] = 0;
587 mode[4] = 0;
588 mode[5] = 0;
589 mode[6] = 0;
590 mode[7] = 0x10;
591 i2c_w8(dev, mode);
592 mode[0] = sd->i2c_ctrl_reg | (5 << 4) | 0x02;
593 mode[2] = 0;
594 i2c_w8(dev, mode);
595 reg_r(dev, 0x0a, buffer, 5);
596}
597
598static int probesensor(struct gspca_dev *gspca_dev)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601 struct usb_device *dev = gspca_dev->dev;
602 __u8 reg02;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300603 static const __u8 datasend[] = { 2, 0 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604 /* reg val1 val2 val3 val4 */
605 __u8 datarecd[6];
606
607 i2c_w2(gspca_dev, datasend);
608/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
609 msleep(10);
610 reg02 = 0x66;
611 reg_w(dev, 0x02, &reg02, 1); /* Gpio on */
612 msleep(10);
613 i2c_r5(gspca_dev, 0, datarecd); /* read sensor id */
614 if (datarecd[0] == 0x02
615 && datarecd[1] == 0x09
616 && datarecd[2] == 0x01
617 && datarecd[3] == 0x00
618 && datarecd[4] == 0x00) {
619 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
620 sd->sensor = SENSOR_HV7131R;
621 return SENSOR_HV7131R;
622 }
623 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
624 datarecd[0], datarecd[1], datarecd[2]);
625 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
626 return -ENODEV;
627}
628
629static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300630 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631{
632 struct sd *sd = (struct sd *) gspca_dev;
633 struct usb_device *dev = gspca_dev->dev;
634 __u8 data;
635 __u8 regF1;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300636 const __u8 *reg9a;
637 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300639 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300641 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300642 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
643
644
645 regF1 = 0x00;
646 reg_w(dev, 0xf1, &regF1, 1);
647
648 reg_w(dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
649
650 /* configure gpio */
651 reg_w(dev, 0x01, &sn9c1xx[1], 2);
652 reg_w(dev, 0x08, &sn9c1xx[8], 2);
653 reg_w(dev, 0x17, &sn9c1xx[0x17], 3);
654 switch (sd->customid) {
655 case SN9C325:
656 reg9a = reg9a_sn9c325;
657 break;
658 case SN9C120:
659 reg9a = reg9a_sn9c120;
660 break;
661 default:
662 reg9a = reg9a_def;
663 break;
664 }
665 reg_w(dev, 0x9a, reg9a, 6);
666
667 data = 0x60; /*fixme:jfm 60 00 00 (3) */
668 reg_w(dev, 0xd4, &data, 1);
669
670 reg_w(dev, 0x03, &sn9c1xx[3], 0x0f);
671
672 switch (sd->customid) {
673 case SN9C120: /* from win trace */
674 data = 0x61;
675 reg_w(dev, 0x01, &data, 1);
676 data = 0x20;
677 reg_w(dev, 0x17, &data, 1);
678 data = 0x60;
679 reg_w(dev, 0x01, &data, 1);
680 break;
681 case SN9C325:
682 data = 0x43;
683 reg_w(dev, 0x01, &data, 1);
684 data = 0xae;
685 reg_w(dev, 0x17, &data, 1);
686 data = 0x42;
687 reg_w(dev, 0x01, &data, 1);
688 break;
689 default:
690 data = 0x43;
691 reg_w(dev, 0x01, &data, 1);
692 data = 0x61;
693 reg_w(dev, 0x17, &data, 1);
694 data = 0x42;
695 reg_w(dev, 0x01, &data, 1);
696 }
697
698 if (sd->sensor == SENSOR_HV7131R) {
699 if (probesensor(gspca_dev) < 0)
700 return -ENODEV;
701 }
702 return 0;
703}
704
705static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
706{
707 int i = 0;
708 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300709 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
711
712 while (hv7131r_sensor_init[i][0]) {
713 i2c_w8(dev, hv7131r_sensor_init[i]);
714 i++;
715 }
716 i2c_w8(dev, SetSensorClk);
717}
718
719static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
720{
721 int i = 0;
722 struct usb_device *dev = gspca_dev->dev;
723
724 while (mi0360_sensor_init[i][0]) {
725 i2c_w8(dev, mi0360_sensor_init[i]);
726 i++;
727 }
728}
729
730static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
731{
732 int i = 0;
733 struct usb_device *dev = gspca_dev->dev;
734
735 while (mo4000_sensor_init[i][0]) {
736 i2c_w8(dev, mo4000_sensor_init[i]);
737 i++;
738 }
739}
740
741static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
742{
743 struct usb_device *dev = gspca_dev->dev;
744 int i = 0;
745
746 while (ov7648_sensor_init[i][0]) {
747 i2c_w8(dev, ov7648_sensor_init[i]);
748 i++;
749 }
750}
751
752static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
753{
754 int i = 0;
755 struct usb_device *dev = gspca_dev->dev;
756
757 while (ov7660_sensor_init[i][0]) {
758 i2c_w8(dev, ov7660_sensor_init[i]);
759 i++;
760 }
761}
762
763/* this function is called at probe time */
764static int sd_config(struct gspca_dev *gspca_dev,
765 const struct usb_device_id *id)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768 struct cam *cam;
769 __u16 vendor;
770 __u16 product;
771
772 vendor = id->idVendor;
773 product = id->idProduct;
774 sd->sensor = -1;
775 switch (vendor) {
776 case 0x0458: /* Genius */
777/* switch (product) {
778 case 0x7025: */
779 sd->customid = SN9C120;
780 sd->sensor = SENSOR_MI0360;
781 sd->i2c_ctrl_reg = 0x81;
782 sd->i2c_base = 0x5d;
783/* break;
784 } */
785 break;
786 case 0x045e:
787/* switch (product) {
788 case 0x00f5:
789 case 0x00f7: */
790 sd->customid = SN9C105;
791 sd->sensor = SENSOR_OV7660;
792 sd->i2c_ctrl_reg = 0x81;
793 sd->i2c_base = 0x21;
794/* break;
795 } */
796 break;
797 case 0x0471: /* Philips */
798/* switch (product) {
799 case 0x0327:
800 case 0x0328:
801 case 0x0330: */
802 sd->customid = SN9C105;
803 sd->sensor = SENSOR_MI0360;
804 sd->i2c_ctrl_reg = 0x81;
805 sd->i2c_base = 0x5d;
806/* break;
807 } */
808 break;
809 case 0x0c45: /* Sonix */
810 switch (product) {
811 case 0x6040:
812 sd->customid = SN9C102P;
813 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
814/* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
815 sd->i2c_ctrl_reg = 0x81;
816 sd->i2c_base = 0x11;
817 break;
818/* case 0x607a: * from BW600.inf
819 sd->customid = SN9C102P;
820 sd->sensor = SENSOR_OV7648;
821 sd->i2c_ctrl_reg = 0x??;
822 sd->i2c_base = 0x??;
823 break; */
824 case 0x607c:
825 sd->customid = SN9C102P;
826 sd->sensor = SENSOR_HV7131R;
827 sd->i2c_ctrl_reg = 0x81;
828 sd->i2c_base = 0x11;
829 break;
830/* case 0x607e: * from BW600.inf
831 sd->customid = SN9C102P;
832 sd->sensor = SENSOR_OV7630;
833 sd->i2c_ctrl_reg = 0x??;
834 sd->i2c_base = 0x??;
835 break; */
836 case 0x60c0:
837 sd->customid = SN9C105;
838 sd->sensor = SENSOR_MI0360;
839 sd->i2c_ctrl_reg = 0x81;
840 sd->i2c_base = 0x5d;
841 break;
842/* case 0x60c8: * from BW600.inf
843 sd->customid = SN9C105;
844 sd->sensor = SENSOR_OM6801;
845 sd->i2c_ctrl_reg = 0x??;
846 sd->i2c_base = 0x??;
847 break; */
848/* case 0x60cc: * from BW600.inf
849 sd->customid = SN9C105;
850 sd->sensor = SENSOR_HV7131GP;
851 sd->i2c_ctrl_reg = 0x??;
852 sd->i2c_base = 0x??;
853 break; */
854 case 0x60ec:
855 sd->customid = SN9C105;
856 sd->sensor = SENSOR_MO4000;
857 sd->i2c_ctrl_reg = 0x81;
858 sd->i2c_base = 0x21;
859 break;
860/* case 0x60ef: * from BW600.inf
861 sd->customid = SN9C105;
862 sd->sensor = SENSOR_ICM105C;
863 sd->i2c_ctrl_reg = 0x??;
864 sd->i2c_base = 0x??;
865 break; */
866/* case 0x60fa: * from BW600.inf
867 sd->customid = SN9C105;
868 sd->sensor = SENSOR_OV7648;
869 sd->i2c_ctrl_reg = 0x??;
870 sd->i2c_base = 0x??;
871 break; */
872 case 0x60fb:
873 sd->customid = SN9C105;
874 sd->sensor = SENSOR_OV7660;
875 sd->i2c_ctrl_reg = 0x81;
876 sd->i2c_base = 0x21;
877 break;
878 case 0x60fc:
879 sd->customid = SN9C105;
880 sd->sensor = SENSOR_HV7131R;
881 sd->i2c_ctrl_reg = 0x81;
882 sd->i2c_base = 0x11;
883 break;
884/* case 0x60fe: * from BW600.inf
885 sd->customid = SN9C105;
886 sd->sensor = SENSOR_OV7630;
887 sd->i2c_ctrl_reg = 0x??;
888 sd->i2c_base = 0x??;
889 break; */
890/* case 0x6108: * from BW600.inf
891 sd->customid = SN9C120;
892 sd->sensor = SENSOR_OM6801;
893 sd->i2c_ctrl_reg = 0x??;
894 sd->i2c_base = 0x??;
895 break; */
896/* case 0x6122: * from BW600.inf
897 sd->customid = SN9C110;
898 sd->sensor = SENSOR_ICM105C;
899 sd->i2c_ctrl_reg = 0x??;
900 sd->i2c_base = 0x??;
901 break; */
902 case 0x612a:
903/* sd->customid = SN9C110; * in BW600.inf */
904 sd->customid = SN9C325;
905 sd->sensor = SENSOR_OV7648;
906 sd->i2c_ctrl_reg = 0x81;
907 sd->i2c_base = 0x21;
908 break;
909/* case 0x6123: * from BW600.inf
910 sd->customid = SN9C110;
911 sd->sensor = SENSOR_SanyoCCD;
912 sd->i2c_ctrl_reg = 0x??;
913 sd->i2c_base = 0x??;
914 break; */
915 case 0x612c:
916 sd->customid = SN9C110;
917 sd->sensor = SENSOR_MO4000;
918 sd->i2c_ctrl_reg = 0x81;
919 sd->i2c_base = 0x21;
920 break;
921/* case 0x612e: * from BW600.inf
922 sd->customid = SN9C110;
923 sd->sensor = SENSOR_OV7630;
924 sd->i2c_ctrl_reg = 0x??;
925 sd->i2c_base = 0x??;
926 break; */
927/* case 0x612f: * from BW600.inf
928 sd->customid = SN9C110;
929 sd->sensor = SENSOR_ICM105C;
930 sd->i2c_ctrl_reg = 0x??;
931 sd->i2c_base = 0x??;
932 break; */
933 case 0x6130:
934 sd->customid = SN9C120;
935 sd->sensor = SENSOR_MI0360;
936 sd->i2c_ctrl_reg = 0x81;
937 sd->i2c_base = 0x5d;
938 break;
939 case 0x6138:
940 sd->customid = SN9C120;
941 sd->sensor = SENSOR_MO4000;
942 sd->i2c_ctrl_reg = 0x81;
943 sd->i2c_base = 0x21;
944 break;
945/* case 0x613a: * from BW600.inf
946 sd->customid = SN9C120;
947 sd->sensor = SENSOR_OV7648;
948 sd->i2c_ctrl_reg = 0x??;
949 sd->i2c_base = 0x??;
950 break; */
951 case 0x613b:
952 sd->customid = SN9C120;
953 sd->sensor = SENSOR_OV7660;
954 sd->i2c_ctrl_reg = 0x81;
955 sd->i2c_base = 0x21;
956 break;
957 case 0x613c:
958 sd->customid = SN9C120;
959 sd->sensor = SENSOR_HV7131R;
960 sd->i2c_ctrl_reg = 0x81;
961 sd->i2c_base = 0x11;
962 break;
963/* case 0x613e: * from BW600.inf
964 sd->customid = SN9C120;
965 sd->sensor = SENSOR_OV7630;
966 sd->i2c_ctrl_reg = 0x??;
967 sd->i2c_base = 0x??;
968 break; */
969 }
970 break;
971 }
972 if (sd->sensor < 0) {
973 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
974 vendor, product);
975 return -EINVAL;
976 }
977
978 cam = &gspca_dev->cam;
979 cam->dev_name = (char *) id->driver_info;
980 cam->epaddr = 0x01;
981 cam->cam_mode = vga_mode;
982 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300983
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985 sd->brightness = BRIGHTNESS_DEF;
986 sd->contrast = CONTRAST_DEF;
987 sd->colors = COLOR_DEF;
988 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989 return 0;
990}
991
992/* this function is called at open time */
993static int sd_open(struct gspca_dev *gspca_dev)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300997/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998 __u8 regF1;
999 __u8 regGpio[] = { 0x29, 0x74 };
1000
1001 /* setup a selector by customid */
1002 regF1 = 0x01;
1003 reg_w(dev, 0xf1, &regF1, 1);
1004 reg_r(dev, 0x00, &regF1, 1); /* -> regF1 = 0x00 */
1005 reg_w(dev, 0xf1, &regF1, 1);
1006 reg_r(dev, 0x00, &regF1, 1);
1007 switch (sd->customid) {
1008 case SN9C102P:
1009 if (regF1 != 0x11)
1010 return -ENODEV;
1011 reg_w(dev, 0x02, &regGpio[1], 1);
1012 break;
1013 case SN9C105:
1014 if (regF1 != 0x11)
1015 return -ENODEV;
1016 reg_w(dev, 0x02, regGpio, 2);
1017 break;
1018 case SN9C110:
1019 if (regF1 != 0x12)
1020 return -ENODEV;
1021 regGpio[1] = 0x62;
1022 reg_w(dev, 0x02, &regGpio[1], 1);
1023 break;
1024 case SN9C120:
1025 if (regF1 != 0x12)
1026 return -ENODEV;
1027 regGpio[1] = 0x70;
1028 reg_w(dev, 0x02, regGpio, 2);
1029 break;
1030 default:
1031/* case SN9C325: */
1032 if (regF1 != 0x12)
1033 return -ENODEV;
1034 regGpio[1] = 0x62;
1035 reg_w(dev, 0x02, &regGpio[1], 1);
1036 break;
1037 }
1038
1039 regF1 = 0x01;
1040 reg_w(dev, 0xf1, &regF1, 1);
1041
1042 return 0;
1043}
1044
1045static unsigned int setexposure(struct gspca_dev *gspca_dev,
1046 unsigned int expo)
1047{
1048 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001049 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001051 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001052 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001053 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1055
1056 switch (sd->sensor) {
1057 case SENSOR_HV7131R: {
1058 __u8 Expodoit[] =
1059 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1060
1061 Expodoit[3] = expo >> 16;
1062 Expodoit[4] = expo >> 8;
1063 Expodoit[5] = expo;
1064 i2c_w8(gspca_dev->dev, Expodoit);
1065 break;
1066 }
1067 case SENSOR_MI0360: {
1068 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1069 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1070
1071 if (expo > 0x0635)
1072 expo = 0x0635;
1073 else if (expo < 0x0001)
1074 expo = 0x0001;
1075 expoMi[3] = expo >> 8;
1076 expoMi[4] = expo;
1077 i2c_w8(gspca_dev->dev, expoMi);
1078 i2c_w8(gspca_dev->dev, doit);
1079 i2c_w8(gspca_dev->dev, sensorgo);
1080 break;
1081 }
1082 case SENSOR_MO4000: {
1083 __u8 expoMof[] =
1084 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1085 __u8 expoMo10[] =
1086 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1087
1088 if (expo > 0x1fff)
1089 expo = 0x1fff;
1090 else if (expo < 0x0001)
1091 expo = 0x0001;
1092 expoMof[3] = (expo & 0x03fc) >> 2;
1093 i2c_w8(gspca_dev->dev, expoMof);
1094 expoMo10[3] = ((expo & 0x1c00) >> 10)
1095 | ((expo & 0x0003) << 4);
1096 i2c_w8(gspca_dev->dev, expoMo10);
1097 i2c_w8(gspca_dev->dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001098 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001099 ((expoMo10[3] & 0x07) << 10)
1100 | (expoMof[3] << 2)
1101 | ((expoMo10[3] & 0x30) >> 4));
1102 break;
1103 }
1104 }
1105 return expo;
1106}
1107
1108static void setbrightness(struct gspca_dev *gspca_dev)
1109{
1110 struct sd *sd = (struct sd *) gspca_dev;
1111 unsigned int expo;
1112 __u8 k2;
1113
1114 switch (sd->sensor) {
1115 case SENSOR_HV7131R:
1116 expo = sd->brightness << 4;
1117 if (expo > 0x002dc6c0)
1118 expo = 0x002dc6c0;
1119 else if (expo < 0x02a0)
1120 expo = 0x02a0;
1121 sd->exposure = setexposure(gspca_dev, expo);
1122 break;
1123 case SENSOR_MI0360:
1124 expo = sd->brightness >> 4;
1125 sd->exposure = setexposure(gspca_dev, expo);
1126 break;
1127 case SENSOR_MO4000:
1128 expo = sd->brightness >> 4;
1129 sd->exposure = setexposure(gspca_dev, expo);
1130 break;
1131 case SENSOR_OV7660:
1132 return; /*jfm??*/
1133 }
1134
1135 k2 = sd->brightness >> 10;
1136 reg_w(gspca_dev->dev, 0x96, &k2, 1);
1137}
1138
1139static void setcontrast(struct gspca_dev *gspca_dev)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142 __u8 k2;
1143 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1144
1145 if (sd->sensor == SENSOR_OV7660)
1146 return; /*jfm??*/
1147 k2 = sd->contrast;
1148 contrast[2] = k2;
1149 contrast[0] = (k2 + 1) >> 1;
1150 contrast[4] = (k2 + 1) / 5;
1151 reg_w(gspca_dev->dev, 0x84, contrast, 6);
1152}
1153
1154static void setcolors(struct gspca_dev *gspca_dev)
1155{
1156 struct sd *sd = (struct sd *) gspca_dev;
1157 __u8 data;
1158 int colour;
1159
1160 colour = sd->colors - 128;
1161 if (colour > 0)
1162 data = (colour + 32) & 0x7f; /* blue */
1163 else
1164 data = (-colour + 32) & 0x7f; /* red */
1165 reg_w(gspca_dev->dev, 0x05, &data, 1);
1166}
1167
1168/* -- start the camera -- */
1169static void sd_start(struct gspca_dev *gspca_dev)
1170{
1171 struct sd *sd = (struct sd *) gspca_dev;
1172 struct usb_device *dev = gspca_dev->dev;
1173 int i;
1174 __u8 data;
1175 __u8 reg1;
1176 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001177 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001178 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001179 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1180 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1181 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1182 static const __u8 CA_sn9c120[] =
1183 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1184 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1185 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1187
1188 sn9c1xx = sn_tb[(int) sd->sensor];
1189 configure_gpio(gspca_dev, sn9c1xx);
1190
1191/*fixme:jfm this sequence should appear at end of sd_start */
1192/* with
1193 data = 0x44;
1194 reg_w(dev, 0x01, &data, 1); */
1195 reg_w(dev, 0x15, &sn9c1xx[0x15], 1);
1196 reg_w(dev, 0x16, &sn9c1xx[0x16], 1);
1197 reg_w(dev, 0x12, &sn9c1xx[0x12], 1);
1198 reg_w(dev, 0x13, &sn9c1xx[0x13], 1);
1199 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1200 reg_w(dev, 0xd2, &DC29[0], 1);
1201 reg_w(dev, 0xd3, &DC29[1], 1);
1202 reg_w(dev, 0xc6, &DC29[2], 1);
1203 reg_w(dev, 0xc7, &DC29[3], 1);
1204 reg_w(dev, 0xc8, &DC29[4], 1);
1205 reg_w(dev, 0xc9, &DC29[5], 1);
1206/*fixme:jfm end of ending sequence */
1207 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1208 if (sd->customid == SN9C325)
1209 data = 0xae;
1210 else
1211 data = 0x60;
1212 reg_w(dev, 0x17, &data, 1);
1213 reg_w(dev, 0x05, &sn9c1xx[5], 1);
1214 reg_w(dev, 0x07, &sn9c1xx[7], 1);
1215 reg_w(dev, 0x06, &sn9c1xx[6], 1);
1216 reg_w(dev, 0x14, &sn9c1xx[0x14], 1);
1217 if (sd->customid == SN9C325) {
1218 reg_w(dev, 0x20, regsn20_sn9c325, 0x11);
1219 for (i = 0; i < 8; i++)
1220 reg_w(dev, 0x84, reg84_sn9c325, 0x15);
1221 data = 0x0a;
1222 reg_w(dev, 0x9a, &data, 1);
1223 data = 0x60;
1224 reg_w(dev, 0x99, &data, 1);
1225 } else {
1226 reg_w(dev, 0x20, regsn20, 0x11);
1227 for (i = 0; i < 8; i++)
1228 reg_w(dev, 0x84, reg84, 0x15);
1229 data = 0x08;
1230 reg_w(dev, 0x9a, &data, 1);
1231 data = 0x59;
1232 reg_w(dev, 0x99, &data, 1);
1233 }
1234
1235 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
1236 reg1 = 0x02;
1237 reg17 = 0x61;
1238 switch (sd->sensor) {
1239 case SENSOR_HV7131R:
1240 hv7131R_InitSensor(gspca_dev);
1241 if (mode)
1242 reg1 = 0x46; /* 320 clk 48Mhz */
1243 else
1244 reg1 = 0x06; /* 640 clk 24Mz */
1245 break;
1246 case SENSOR_MI0360:
1247 mi0360_InitSensor(gspca_dev);
1248 if (mode)
1249 reg1 = 0x46; /* 320 clk 48Mhz */
1250 else
1251 reg1 = 0x06; /* 640 clk 24Mz */
1252 break;
1253 case SENSOR_MO4000:
1254 mo4000_InitSensor(gspca_dev);
1255 if (mode) {
1256/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1257 reg1 = 0x06; /* clk 24Mz */
1258 } else {
1259 reg17 = 0x22; /* 640 MCKSIZE */
1260 reg1 = 0x06; /* 640 clk 24Mz */
1261 }
1262 break;
1263 case SENSOR_OV7648:
1264 reg17 = 0xa2;
1265 reg1 = 0x44;
1266 ov7648_InitSensor(gspca_dev);
1267/* if (mode)
1268 ; * 320x2...
1269 else
1270 ; * 640x... */
1271 break;
1272 default:
1273/* case SENSOR_OV7660: */
1274 ov7660_InitSensor(gspca_dev);
1275 if (mode) {
1276/* reg17 = 0x21; * 320 */
1277/* reg1 = 0x44; */
1278 reg1 = 0x46;
1279 } else {
1280 reg17 = 0xa2; /* 640 */
1281 reg1 = 0x40;
1282 }
1283 break;
1284 }
1285 reg_w(dev, 0xc0, C0, 6);
1286 switch (sd->customid) {
1287 case SN9C120: /*jfm ?? */
1288 reg_w(dev, 0xca, CA_sn9c120, 4);
1289 break;
1290 default:
1291 reg_w(dev, 0xca, CA, 4);
1292 break;
1293 }
1294 switch (sd->customid) {
1295 case SN9C120: /*jfm ?? */
1296 case SN9C325:
1297 reg_w(dev, 0xce, CE_sn9c325, 4);
1298 break;
1299 default:
1300 reg_w(dev, 0xce, CE, 4);
1301 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1302 break;
1303 }
1304
1305 /* here change size mode 0 -> VGA; 1 -> CIF */
1306 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1307 reg_w(dev, 0x18, &data, 1);
1308
1309 reg_w(dev, 0x100, qtable4, 0x40);
1310 reg_w(dev, 0x140, qtable4 + 0x40, 0x40);
1311
1312 data = sn9c1xx[0x18] | (mode << 4);
1313 reg_w(dev, 0x18, &data, 1);
1314
1315 reg_w(dev, 0x17, &reg17, 1);
1316 reg_w(dev, 0x01, &reg1, 1);
1317 setbrightness(gspca_dev);
1318 setcontrast(gspca_dev);
1319}
1320
1321static void sd_stopN(struct gspca_dev *gspca_dev)
1322{
1323 struct sd *sd = (struct sd *) gspca_dev;
1324 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001325 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001326 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001327 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1329 __u8 regF1;
1330 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001331 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001332
1333 data = 0x0b;
1334 switch (sd->sensor) {
1335 case SENSOR_HV7131R:
1336 i2c_w8(dev, stophv7131);
1337 data = 0x2b;
1338 break;
1339 case SENSOR_MI0360:
1340 i2c_w8(dev, stopmi0360);
1341 data = 0x29;
1342 break;
1343 case SENSOR_MO4000:
1344 break;
1345 case SENSOR_OV7648:
1346 data = 0x29;
1347 break;
1348 default:
1349/* case SENSOR_OV7660: */
1350 break;
1351 }
1352 sn9c1xx = sn_tb[(int) sd->sensor];
1353 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1354 reg_w(dev, 0x17, &sn9c1xx[0x17], 1);
1355 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1356 reg_w(dev, 0x01, &data, 1);
1357 regF1 = 0x01;
1358 reg_w(dev, 0xf1, &regF1, 1);
1359}
1360
1361static void sd_stop0(struct gspca_dev *gspca_dev)
1362{
1363}
1364
1365static void sd_close(struct gspca_dev *gspca_dev)
1366{
1367}
1368
1369static void setautogain(struct gspca_dev *gspca_dev)
1370{
1371 struct sd *sd = (struct sd *) gspca_dev;
1372 /* Thanks S., without your advice, autobright should not work :) */
1373 int delta;
1374 int expotimes = 0;
1375 __u8 luma_mean = 130;
1376 __u8 luma_delta = 20;
1377
1378 delta = sd->avg_lum;
1379 if (delta < luma_mean - luma_delta ||
1380 delta > luma_mean + luma_delta) {
1381 switch (sd->sensor) {
1382 case SENSOR_HV7131R:
1383 expotimes = sd->exposure >> 8;
1384 expotimes += (luma_mean - delta) >> 4;
1385 if (expotimes < 0)
1386 expotimes = 0;
1387 sd->exposure = setexposure(gspca_dev,
1388 (unsigned int) (expotimes << 8));
1389 break;
1390 case SENSOR_MO4000:
1391 case SENSOR_MI0360:
1392 expotimes = sd->exposure;
1393 expotimes += (luma_mean - delta) >> 6;
1394 if (expotimes < 0)
1395 expotimes = 0;
1396 sd->exposure = setexposure(gspca_dev,
1397 (unsigned int) expotimes);
1398 setcolors(gspca_dev);
1399 break;
1400 }
1401 }
1402}
1403
1404static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1405 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001406 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001407 int len) /* iso packet length */
1408{
1409 struct sd *sd = (struct sd *) gspca_dev;
1410 int sof, avg_lum;
1411
1412 sof = len - 64;
1413 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1414
1415 /* end of frame */
1416 gspca_frame_add(gspca_dev, LAST_PACKET,
1417 frame, data, sof + 2);
1418 if (sd->ag_cnt < 0)
1419 return;
1420 if (--sd->ag_cnt >= 0)
1421 return;
1422 sd->ag_cnt = AG_CNT_START;
1423/* w1 w2 w3 */
1424/* w4 w5 w6 */
1425/* w7 w8 */
1426/* w4 */
1427 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1428/* w6 */
1429 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1430/* w2 */
1431 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1432/* w8 */
1433 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1434/* w5 */
1435 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1436 avg_lum >>= 4;
1437 sd->avg_lum = avg_lum;
1438 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1439 setautogain(gspca_dev);
1440 return;
1441 }
1442 if (gspca_dev->last_packet_type == LAST_PACKET) {
1443
1444 /* put the JPEG 422 header */
1445 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1446 }
1447 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1448}
1449
1450static unsigned int getexposure(struct gspca_dev *gspca_dev)
1451{
1452 struct sd *sd = (struct sd *) gspca_dev;
1453 __u8 hexpo, mexpo, lexpo;
1454 __u8 expo[6];
1455
1456 switch (sd->sensor) {
1457 case SENSOR_HV7131R:
1458 /* read sensor exposure */
1459 i2c_r5(gspca_dev, 0x25, expo);
1460 return (expo[0] << 16) | (expo[1] << 8) | expo[2];
1461 case SENSOR_MI0360:
1462 /* read sensor exposure */
1463 i2c_r5(gspca_dev, 0x09, expo);
1464 return (expo[0] << 8) | expo[1];
1465 case SENSOR_MO4000:
1466 i2c_r5(gspca_dev, 0x0e, expo);
1467 hexpo = 0; /* expo[1] & 0x07; */
1468 mexpo = 0x40; /* expo[2] &0xff; */
1469 lexpo = (expo[1] & 0x30) >> 4;
1470 PDEBUG(D_CONF, "exposure %d",
1471 (hexpo << 10) | (mexpo << 2) | lexpo);
1472 return (hexpo << 10) | (mexpo << 2) | lexpo;
1473 default:
1474/* case SENSOR_OV7660: */
1475 /* read sensor exposure */
1476 i2c_r5(gspca_dev, 0x04, expo);
1477 hexpo = expo[3] & 0x2f;
1478 lexpo = expo[0] & 0x02;
1479 i2c_r5(gspca_dev, 0x08, expo);
1480 mexpo = expo[2];
1481 return (hexpo << 10) | (mexpo << 2) | lexpo;
1482 }
1483}
1484
1485static void getbrightness(struct gspca_dev *gspca_dev)
1486{
1487 struct sd *sd = (struct sd *) gspca_dev;
1488
1489 /* hardcoded registers seem not readable */
1490 switch (sd->sensor) {
1491 case SENSOR_HV7131R:
1492/* sd->brightness = 0x7fff; */
1493 sd->brightness = getexposure(gspca_dev) >> 4;
1494 break;
1495 case SENSOR_MI0360:
1496 sd->brightness = getexposure(gspca_dev) << 4;
1497 break;
1498 case SENSOR_MO4000:
1499/* sd->brightness = 0x1fff; */
1500 sd->brightness = getexposure(gspca_dev) << 4;
1501 break;
1502 }
1503}
1504
1505static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1506{
1507 struct sd *sd = (struct sd *) gspca_dev;
1508
1509 sd->brightness = val;
1510 if (gspca_dev->streaming)
1511 setbrightness(gspca_dev);
1512 return 0;
1513}
1514
1515static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 getbrightness(gspca_dev);
1520 *val = sd->brightness;
1521 return 0;
1522}
1523
1524static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1525{
1526 struct sd *sd = (struct sd *) gspca_dev;
1527
1528 sd->contrast = val;
1529 if (gspca_dev->streaming)
1530 setcontrast(gspca_dev);
1531 return 0;
1532}
1533
1534static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537
1538 *val = sd->contrast;
1539 return 0;
1540}
1541
1542static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1543{
1544 struct sd *sd = (struct sd *) gspca_dev;
1545
1546 sd->colors = val;
1547 if (gspca_dev->streaming)
1548 setcolors(gspca_dev);
1549 return 0;
1550}
1551
1552static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 *val = sd->colors;
1557 return 0;
1558}
1559
1560static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 sd->autogain = val;
1565 if (val)
1566 sd->ag_cnt = AG_CNT_START;
1567 else
1568 sd->ag_cnt = -1;
1569 return 0;
1570}
1571
1572static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1573{
1574 struct sd *sd = (struct sd *) gspca_dev;
1575
1576 *val = sd->autogain;
1577 return 0;
1578}
1579
1580/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001581static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001582 .name = MODULE_NAME,
1583 .ctrls = sd_ctrls,
1584 .nctrls = ARRAY_SIZE(sd_ctrls),
1585 .config = sd_config,
1586 .open = sd_open,
1587 .start = sd_start,
1588 .stopN = sd_stopN,
1589 .stop0 = sd_stop0,
1590 .close = sd_close,
1591 .pkt_scan = sd_pkt_scan,
1592};
1593
1594/* -- module initialisation -- */
1595#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001596static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001597 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1598 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1599 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1600 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1601 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1602 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1603 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1604 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1605 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1606 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1607 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1608 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1609 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1610 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1611 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1612 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1613 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1614 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1615 {}
1616};
1617MODULE_DEVICE_TABLE(usb, device_table);
1618
1619/* -- device connect -- */
1620static int sd_probe(struct usb_interface *intf,
1621 const struct usb_device_id *id)
1622{
1623 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1624 THIS_MODULE);
1625}
1626
1627static struct usb_driver sd_driver = {
1628 .name = MODULE_NAME,
1629 .id_table = device_table,
1630 .probe = sd_probe,
1631 .disconnect = gspca_disconnect,
1632};
1633
1634/* -- module insert / remove -- */
1635static int __init sd_mod_init(void)
1636{
1637 if (usb_register(&sd_driver) < 0)
1638 return -1;
1639 info("v%s registered", version);
1640 return 0;
1641}
1642static void __exit sd_mod_exit(void)
1643{
1644 usb_deregister(&sd_driver);
1645 info("deregistered");
1646}
1647
1648module_init(sd_mod_init);
1649module_exit(sd_mod_exit);