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