blob: 30e840dca481aff0616bac45bac28a6cf8c67df9 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine739570b2008-07-14 09:38:29 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 int avg_lum;
39 unsigned int exposure;
40
41 unsigned short brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 signed char ag_cnt;
47#define AG_CNT_START 13
48
49 char qindex;
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
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300515/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
516static void reg_r(struct gspca_dev *gspca_dev,
517 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300518{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300519 usb_control_msg(gspca_dev->dev,
520 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300521 0,
522 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
523 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300524 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525 500);
526}
527
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300528static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529 __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 Moine739570b2008-07-14 09:38:29 -0300533 if (len <= sizeof gspca_dev->usb_buf) {
534 memcpy(gspca_dev->usb_buf, buffer, len);
535 usb_control_msg(gspca_dev->dev,
536 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300537 0x08,
538 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
539 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300540 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300541 500);
542 } else {
543 __u8 *tmpbuf;
544
545 tmpbuf = kmalloc(len, GFP_KERNEL);
546 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 usb_control_msg(gspca_dev->dev,
548 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300549 0x08,
550 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
551 value, 0,
552 tmpbuf, len,
553 500);
554 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300555 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300556}
557
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558/* I2C write 2 bytes */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559static void i2c_w2(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300560 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561{
562 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300563 __u8 mode[8];
564
565 /* is i2c ready */
566 mode[0] = sd->i2c_ctrl_reg | (2 << 4);
567 mode[1] = sd->i2c_base;
568 mode[2] = buffer[0];
569 mode[3] = buffer[1];
570 mode[4] = 0;
571 mode[5] = 0;
572 mode[6] = 0;
573 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300574 reg_w(gspca_dev, 0x08, mode, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300575}
576
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300577/* I2C write 8 bytes */
578static void i2c_w8(struct gspca_dev *gspca_dev,
579 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300581 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300582 msleep(1);
583}
584
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300585/* read 5 bytes in gspca_dev->usb_buf */
586static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587{
588 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300589 __u8 mode[8];
590
591 mode[0] = sd->i2c_ctrl_reg | 0x10;
592 mode[1] = sd->i2c_base;
593 mode[2] = reg;
594 mode[3] = 0;
595 mode[4] = 0;
596 mode[5] = 0;
597 mode[6] = 0;
598 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300599 i2c_w8(gspca_dev, mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600 mode[0] = sd->i2c_ctrl_reg | (5 << 4) | 0x02;
601 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300602 i2c_w8(gspca_dev, mode);
603 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604}
605
606static int probesensor(struct gspca_dev *gspca_dev)
607{
608 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300609 __u8 reg02;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300610 static const __u8 datasend[] = { 2, 0 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300611 /* reg val1 val2 val3 val4 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612
613 i2c_w2(gspca_dev, datasend);
614/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
615 msleep(10);
616 reg02 = 0x66;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617 reg_w(gspca_dev, 0x02, &reg02, 1); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619 i2c_r5(gspca_dev, 0); /* read sensor id */
620 if (gspca_dev->usb_buf[0] == 0x02
621 && gspca_dev->usb_buf[1] == 0x09
622 && gspca_dev->usb_buf[2] == 0x01
623 && gspca_dev->usb_buf[3] == 0x00
624 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
626 sd->sensor = SENSOR_HV7131R;
627 return SENSOR_HV7131R;
628 }
629 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300630 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
631 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
633 return -ENODEV;
634}
635
636static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300637 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638{
639 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 __u8 data;
641 __u8 regF1;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300642 const __u8 *reg9a;
643 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300645 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300647 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
649
650
651 regF1 = 0x00;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300652 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300653
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300654 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1);
655 /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656
657 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300658 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
659 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
660 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300661 switch (sd->customid) {
662 case SN9C325:
663 reg9a = reg9a_sn9c325;
664 break;
665 case SN9C120:
666 reg9a = reg9a_sn9c120;
667 break;
668 default:
669 reg9a = reg9a_def;
670 break;
671 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300672 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673
674 data = 0x60; /*fixme:jfm 60 00 00 (3) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300675 reg_w(gspca_dev, 0xd4, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300677 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678
679 switch (sd->customid) {
680 case SN9C120: /* from win trace */
681 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300682 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300683 data = 0x20;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300684 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300686 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687 break;
688 case SN9C325:
689 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300690 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 data = 0xae;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300692 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300694 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 break;
696 default:
697 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300698 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300702 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 }
704
705 if (sd->sensor == SENSOR_HV7131R) {
706 if (probesensor(gspca_dev) < 0)
707 return -ENODEV;
708 }
709 return 0;
710}
711
712static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
713{
714 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300715 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
717
718 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300719 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720 i++;
721 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300722 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300723}
724
725static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
726{
727 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728
729 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300730 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300731 i++;
732 }
733}
734
735static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
736{
737 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738
739 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300740 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300741 i++;
742 }
743}
744
745static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
746{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747 int i = 0;
748
749 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300750 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 i++;
752 }
753}
754
755static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
756{
757 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758
759 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761 i++;
762 }
763}
764
765/* this function is called at probe time */
766static int sd_config(struct gspca_dev *gspca_dev,
767 const struct usb_device_id *id)
768{
769 struct sd *sd = (struct sd *) gspca_dev;
770 struct cam *cam;
771 __u16 vendor;
772 __u16 product;
773
774 vendor = id->idVendor;
775 product = id->idProduct;
776 sd->sensor = -1;
777 switch (vendor) {
778 case 0x0458: /* Genius */
779/* switch (product) {
780 case 0x7025: */
781 sd->customid = SN9C120;
782 sd->sensor = SENSOR_MI0360;
783 sd->i2c_ctrl_reg = 0x81;
784 sd->i2c_base = 0x5d;
785/* break;
786 } */
787 break;
788 case 0x045e:
789/* switch (product) {
790 case 0x00f5:
791 case 0x00f7: */
792 sd->customid = SN9C105;
793 sd->sensor = SENSOR_OV7660;
794 sd->i2c_ctrl_reg = 0x81;
795 sd->i2c_base = 0x21;
796/* break;
797 } */
798 break;
799 case 0x0471: /* Philips */
800/* switch (product) {
801 case 0x0327:
802 case 0x0328:
803 case 0x0330: */
804 sd->customid = SN9C105;
805 sd->sensor = SENSOR_MI0360;
806 sd->i2c_ctrl_reg = 0x81;
807 sd->i2c_base = 0x5d;
808/* break;
809 } */
810 break;
811 case 0x0c45: /* Sonix */
812 switch (product) {
813 case 0x6040:
814 sd->customid = SN9C102P;
815 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
816/* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
817 sd->i2c_ctrl_reg = 0x81;
818 sd->i2c_base = 0x11;
819 break;
820/* case 0x607a: * from BW600.inf
821 sd->customid = SN9C102P;
822 sd->sensor = SENSOR_OV7648;
823 sd->i2c_ctrl_reg = 0x??;
824 sd->i2c_base = 0x??;
825 break; */
826 case 0x607c:
827 sd->customid = SN9C102P;
828 sd->sensor = SENSOR_HV7131R;
829 sd->i2c_ctrl_reg = 0x81;
830 sd->i2c_base = 0x11;
831 break;
832/* case 0x607e: * from BW600.inf
833 sd->customid = SN9C102P;
834 sd->sensor = SENSOR_OV7630;
835 sd->i2c_ctrl_reg = 0x??;
836 sd->i2c_base = 0x??;
837 break; */
838 case 0x60c0:
839 sd->customid = SN9C105;
840 sd->sensor = SENSOR_MI0360;
841 sd->i2c_ctrl_reg = 0x81;
842 sd->i2c_base = 0x5d;
843 break;
844/* case 0x60c8: * from BW600.inf
845 sd->customid = SN9C105;
846 sd->sensor = SENSOR_OM6801;
847 sd->i2c_ctrl_reg = 0x??;
848 sd->i2c_base = 0x??;
849 break; */
850/* case 0x60cc: * from BW600.inf
851 sd->customid = SN9C105;
852 sd->sensor = SENSOR_HV7131GP;
853 sd->i2c_ctrl_reg = 0x??;
854 sd->i2c_base = 0x??;
855 break; */
856 case 0x60ec:
857 sd->customid = SN9C105;
858 sd->sensor = SENSOR_MO4000;
859 sd->i2c_ctrl_reg = 0x81;
860 sd->i2c_base = 0x21;
861 break;
862/* case 0x60ef: * from BW600.inf
863 sd->customid = SN9C105;
864 sd->sensor = SENSOR_ICM105C;
865 sd->i2c_ctrl_reg = 0x??;
866 sd->i2c_base = 0x??;
867 break; */
868/* case 0x60fa: * from BW600.inf
869 sd->customid = SN9C105;
870 sd->sensor = SENSOR_OV7648;
871 sd->i2c_ctrl_reg = 0x??;
872 sd->i2c_base = 0x??;
873 break; */
874 case 0x60fb:
875 sd->customid = SN9C105;
876 sd->sensor = SENSOR_OV7660;
877 sd->i2c_ctrl_reg = 0x81;
878 sd->i2c_base = 0x21;
879 break;
880 case 0x60fc:
881 sd->customid = SN9C105;
882 sd->sensor = SENSOR_HV7131R;
883 sd->i2c_ctrl_reg = 0x81;
884 sd->i2c_base = 0x11;
885 break;
886/* case 0x60fe: * from BW600.inf
887 sd->customid = SN9C105;
888 sd->sensor = SENSOR_OV7630;
889 sd->i2c_ctrl_reg = 0x??;
890 sd->i2c_base = 0x??;
891 break; */
892/* case 0x6108: * from BW600.inf
893 sd->customid = SN9C120;
894 sd->sensor = SENSOR_OM6801;
895 sd->i2c_ctrl_reg = 0x??;
896 sd->i2c_base = 0x??;
897 break; */
898/* case 0x6122: * from BW600.inf
899 sd->customid = SN9C110;
900 sd->sensor = SENSOR_ICM105C;
901 sd->i2c_ctrl_reg = 0x??;
902 sd->i2c_base = 0x??;
903 break; */
904 case 0x612a:
905/* sd->customid = SN9C110; * in BW600.inf */
906 sd->customid = SN9C325;
907 sd->sensor = SENSOR_OV7648;
908 sd->i2c_ctrl_reg = 0x81;
909 sd->i2c_base = 0x21;
910 break;
911/* case 0x6123: * from BW600.inf
912 sd->customid = SN9C110;
913 sd->sensor = SENSOR_SanyoCCD;
914 sd->i2c_ctrl_reg = 0x??;
915 sd->i2c_base = 0x??;
916 break; */
917 case 0x612c:
918 sd->customid = SN9C110;
919 sd->sensor = SENSOR_MO4000;
920 sd->i2c_ctrl_reg = 0x81;
921 sd->i2c_base = 0x21;
922 break;
923/* case 0x612e: * from BW600.inf
924 sd->customid = SN9C110;
925 sd->sensor = SENSOR_OV7630;
926 sd->i2c_ctrl_reg = 0x??;
927 sd->i2c_base = 0x??;
928 break; */
929/* case 0x612f: * from BW600.inf
930 sd->customid = SN9C110;
931 sd->sensor = SENSOR_ICM105C;
932 sd->i2c_ctrl_reg = 0x??;
933 sd->i2c_base = 0x??;
934 break; */
935 case 0x6130:
936 sd->customid = SN9C120;
937 sd->sensor = SENSOR_MI0360;
938 sd->i2c_ctrl_reg = 0x81;
939 sd->i2c_base = 0x5d;
940 break;
941 case 0x6138:
942 sd->customid = SN9C120;
943 sd->sensor = SENSOR_MO4000;
944 sd->i2c_ctrl_reg = 0x81;
945 sd->i2c_base = 0x21;
946 break;
947/* case 0x613a: * from BW600.inf
948 sd->customid = SN9C120;
949 sd->sensor = SENSOR_OV7648;
950 sd->i2c_ctrl_reg = 0x??;
951 sd->i2c_base = 0x??;
952 break; */
953 case 0x613b:
954 sd->customid = SN9C120;
955 sd->sensor = SENSOR_OV7660;
956 sd->i2c_ctrl_reg = 0x81;
957 sd->i2c_base = 0x21;
958 break;
959 case 0x613c:
960 sd->customid = SN9C120;
961 sd->sensor = SENSOR_HV7131R;
962 sd->i2c_ctrl_reg = 0x81;
963 sd->i2c_base = 0x11;
964 break;
965/* case 0x613e: * from BW600.inf
966 sd->customid = SN9C120;
967 sd->sensor = SENSOR_OV7630;
968 sd->i2c_ctrl_reg = 0x??;
969 sd->i2c_base = 0x??;
970 break; */
971 }
972 break;
973 }
974 if (sd->sensor < 0) {
975 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
976 vendor, product);
977 return -EINVAL;
978 }
979
980 cam = &gspca_dev->cam;
981 cam->dev_name = (char *) id->driver_info;
982 cam->epaddr = 0x01;
983 cam->cam_mode = vga_mode;
984 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300987 sd->brightness = BRIGHTNESS_DEF;
988 sd->contrast = CONTRAST_DEF;
989 sd->colors = COLOR_DEF;
990 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300991 return 0;
992}
993
994/* this function is called at open time */
995static int sd_open(struct gspca_dev *gspca_dev)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300998/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999 __u8 regF1;
1000 __u8 regGpio[] = { 0x29, 0x74 };
1001
1002 /* setup a selector by customid */
1003 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001004 reg_w(gspca_dev, 0xf1, &regF1, 1);
1005 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
1006 regF1 = gspca_dev->usb_buf[0];
1007 reg_w(gspca_dev, 0xf1, &regF1, 1);
1008 reg_r(gspca_dev, 0x00, 1);
1009 regF1 = gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001010 switch (sd->customid) {
1011 case SN9C102P:
1012 if (regF1 != 0x11)
1013 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001014 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 break;
1016 case SN9C105:
1017 if (regF1 != 0x11)
1018 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001019 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001020 break;
1021 case SN9C110:
1022 if (regF1 != 0x12)
1023 return -ENODEV;
1024 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001025 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 break;
1027 case SN9C120:
1028 if (regF1 != 0x12)
1029 return -ENODEV;
1030 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001031 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032 break;
1033 default:
1034/* case SN9C325: */
1035 if (regF1 != 0x12)
1036 return -ENODEV;
1037 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001038 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001039 break;
1040 }
1041
1042 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001043 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044
1045 return 0;
1046}
1047
1048static unsigned int setexposure(struct gspca_dev *gspca_dev,
1049 unsigned int expo)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001052 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001054 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001056 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1058
1059 switch (sd->sensor) {
1060 case SENSOR_HV7131R: {
1061 __u8 Expodoit[] =
1062 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1063
1064 Expodoit[3] = expo >> 16;
1065 Expodoit[4] = expo >> 8;
1066 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001067 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068 break;
1069 }
1070 case SENSOR_MI0360: {
1071 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1072 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1073
1074 if (expo > 0x0635)
1075 expo = 0x0635;
1076 else if (expo < 0x0001)
1077 expo = 0x0001;
1078 expoMi[3] = expo >> 8;
1079 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001080 i2c_w8(gspca_dev, expoMi);
1081 i2c_w8(gspca_dev, doit);
1082 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001083 break;
1084 }
1085 case SENSOR_MO4000: {
1086 __u8 expoMof[] =
1087 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1088 __u8 expoMo10[] =
1089 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1090
1091 if (expo > 0x1fff)
1092 expo = 0x1fff;
1093 else if (expo < 0x0001)
1094 expo = 0x0001;
1095 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001096 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001097 expoMo10[3] = ((expo & 0x1c00) >> 10)
1098 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001099 i2c_w8(gspca_dev, expoMo10);
1100 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001101 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001102 ((expoMo10[3] & 0x07) << 10)
1103 | (expoMof[3] << 2)
1104 | ((expoMo10[3] & 0x30) >> 4));
1105 break;
1106 }
1107 }
1108 return expo;
1109}
1110
1111static void setbrightness(struct gspca_dev *gspca_dev)
1112{
1113 struct sd *sd = (struct sd *) gspca_dev;
1114 unsigned int expo;
1115 __u8 k2;
1116
1117 switch (sd->sensor) {
1118 case SENSOR_HV7131R:
1119 expo = sd->brightness << 4;
1120 if (expo > 0x002dc6c0)
1121 expo = 0x002dc6c0;
1122 else if (expo < 0x02a0)
1123 expo = 0x02a0;
1124 sd->exposure = setexposure(gspca_dev, expo);
1125 break;
1126 case SENSOR_MI0360:
1127 expo = sd->brightness >> 4;
1128 sd->exposure = setexposure(gspca_dev, expo);
1129 break;
1130 case SENSOR_MO4000:
1131 expo = sd->brightness >> 4;
1132 sd->exposure = setexposure(gspca_dev, expo);
1133 break;
1134 case SENSOR_OV7660:
1135 return; /*jfm??*/
1136 }
1137
1138 k2 = sd->brightness >> 10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001139 reg_w(gspca_dev, 0x96, &k2, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140}
1141
1142static void setcontrast(struct gspca_dev *gspca_dev)
1143{
1144 struct sd *sd = (struct sd *) gspca_dev;
1145 __u8 k2;
1146 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1147
1148 if (sd->sensor == SENSOR_OV7660)
1149 return; /*jfm??*/
1150 k2 = sd->contrast;
1151 contrast[2] = k2;
1152 contrast[0] = (k2 + 1) >> 1;
1153 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001154 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001155}
1156
1157static void setcolors(struct gspca_dev *gspca_dev)
1158{
1159 struct sd *sd = (struct sd *) gspca_dev;
1160 __u8 data;
1161 int colour;
1162
1163 colour = sd->colors - 128;
1164 if (colour > 0)
1165 data = (colour + 32) & 0x7f; /* blue */
1166 else
1167 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001168 reg_w(gspca_dev, 0x05, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001169}
1170
1171/* -- start the camera -- */
1172static void sd_start(struct gspca_dev *gspca_dev)
1173{
1174 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175 int i;
1176 __u8 data;
1177 __u8 reg1;
1178 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001179 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001181 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1182 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1183 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1184 static const __u8 CA_sn9c120[] =
1185 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1186 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1187 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001188 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1189
1190 sn9c1xx = sn_tb[(int) sd->sensor];
1191 configure_gpio(gspca_dev, sn9c1xx);
1192
1193/*fixme:jfm this sequence should appear at end of sd_start */
1194/* with
1195 data = 0x44;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001196 reg_w(gspca_dev, 0x01, &data, 1); */
1197 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1198 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1199 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1200 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1201 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1202 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1203 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1204 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1205 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1206 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1207 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208/*fixme:jfm end of ending sequence */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001209 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 if (sd->customid == SN9C325)
1211 data = 0xae;
1212 else
1213 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001214 reg_w(gspca_dev, 0x17, &data, 1);
1215 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1216 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1217 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1218 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219 if (sd->customid == SN9C325) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001220 reg_w(gspca_dev, 0x20, regsn20_sn9c325, 0x11);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001221 for (i = 0; i < 8; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001222 reg_w(gspca_dev, 0x84, reg84_sn9c325, 0x15);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001223 data = 0x0a;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001224 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001226 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227 } else {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001228 reg_w(gspca_dev, 0x20, regsn20, 0x11);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229 for (i = 0; i < 8; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001230 reg_w(gspca_dev, 0x84, reg84, 0x15);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231 data = 0x08;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001232 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001233 data = 0x59;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001234 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001235 }
1236
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001237 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238 reg1 = 0x02;
1239 reg17 = 0x61;
1240 switch (sd->sensor) {
1241 case SENSOR_HV7131R:
1242 hv7131R_InitSensor(gspca_dev);
1243 if (mode)
1244 reg1 = 0x46; /* 320 clk 48Mhz */
1245 else
1246 reg1 = 0x06; /* 640 clk 24Mz */
1247 break;
1248 case SENSOR_MI0360:
1249 mi0360_InitSensor(gspca_dev);
1250 if (mode)
1251 reg1 = 0x46; /* 320 clk 48Mhz */
1252 else
1253 reg1 = 0x06; /* 640 clk 24Mz */
1254 break;
1255 case SENSOR_MO4000:
1256 mo4000_InitSensor(gspca_dev);
1257 if (mode) {
1258/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1259 reg1 = 0x06; /* clk 24Mz */
1260 } else {
1261 reg17 = 0x22; /* 640 MCKSIZE */
1262 reg1 = 0x06; /* 640 clk 24Mz */
1263 }
1264 break;
1265 case SENSOR_OV7648:
1266 reg17 = 0xa2;
1267 reg1 = 0x44;
1268 ov7648_InitSensor(gspca_dev);
1269/* if (mode)
1270 ; * 320x2...
1271 else
1272 ; * 640x... */
1273 break;
1274 default:
1275/* case SENSOR_OV7660: */
1276 ov7660_InitSensor(gspca_dev);
1277 if (mode) {
1278/* reg17 = 0x21; * 320 */
1279/* reg1 = 0x44; */
1280 reg1 = 0x46;
1281 } else {
1282 reg17 = 0xa2; /* 640 */
1283 reg1 = 0x40;
1284 }
1285 break;
1286 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001287 reg_w(gspca_dev, 0xc0, C0, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001288 switch (sd->customid) {
1289 case SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001290 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001291 break;
1292 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001293 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001294 break;
1295 }
1296 switch (sd->customid) {
1297 case SN9C120: /*jfm ?? */
1298 case SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001299 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001300 break;
1301 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001302 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001303 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1304 break;
1305 }
1306
1307 /* here change size mode 0 -> VGA; 1 -> CIF */
1308 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001309 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001310
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001311 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1312 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001313
1314 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001315 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001316
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001317 reg_w(gspca_dev, 0x17, &reg17, 1);
1318 reg_w(gspca_dev, 0x01, &reg1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001319 setbrightness(gspca_dev);
1320 setcontrast(gspca_dev);
1321}
1322
1323static void sd_stopN(struct gspca_dev *gspca_dev)
1324{
1325 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001326 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001327 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001328 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001329 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1330 __u8 regF1;
1331 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001332 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001333
1334 data = 0x0b;
1335 switch (sd->sensor) {
1336 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001337 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001338 data = 0x2b;
1339 break;
1340 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001341 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001342 data = 0x29;
1343 break;
1344 case SENSOR_MO4000:
1345 break;
1346 case SENSOR_OV7648:
1347 data = 0x29;
1348 break;
1349 default:
1350/* case SENSOR_OV7660: */
1351 break;
1352 }
1353 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001354 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1355 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1356 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1357 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001358 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001359 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001360}
1361
1362static void sd_stop0(struct gspca_dev *gspca_dev)
1363{
1364}
1365
1366static void sd_close(struct gspca_dev *gspca_dev)
1367{
1368}
1369
1370static void setautogain(struct gspca_dev *gspca_dev)
1371{
1372 struct sd *sd = (struct sd *) gspca_dev;
1373 /* Thanks S., without your advice, autobright should not work :) */
1374 int delta;
1375 int expotimes = 0;
1376 __u8 luma_mean = 130;
1377 __u8 luma_delta = 20;
1378
1379 delta = sd->avg_lum;
1380 if (delta < luma_mean - luma_delta ||
1381 delta > luma_mean + luma_delta) {
1382 switch (sd->sensor) {
1383 case SENSOR_HV7131R:
1384 expotimes = sd->exposure >> 8;
1385 expotimes += (luma_mean - delta) >> 4;
1386 if (expotimes < 0)
1387 expotimes = 0;
1388 sd->exposure = setexposure(gspca_dev,
1389 (unsigned int) (expotimes << 8));
1390 break;
1391 case SENSOR_MO4000:
1392 case SENSOR_MI0360:
1393 expotimes = sd->exposure;
1394 expotimes += (luma_mean - delta) >> 6;
1395 if (expotimes < 0)
1396 expotimes = 0;
1397 sd->exposure = setexposure(gspca_dev,
1398 (unsigned int) expotimes);
1399 setcolors(gspca_dev);
1400 break;
1401 }
1402 }
1403}
1404
1405static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1406 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001407 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001408 int len) /* iso packet length */
1409{
1410 struct sd *sd = (struct sd *) gspca_dev;
1411 int sof, avg_lum;
1412
1413 sof = len - 64;
1414 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1415
1416 /* end of frame */
1417 gspca_frame_add(gspca_dev, LAST_PACKET,
1418 frame, data, sof + 2);
1419 if (sd->ag_cnt < 0)
1420 return;
1421 if (--sd->ag_cnt >= 0)
1422 return;
1423 sd->ag_cnt = AG_CNT_START;
1424/* w1 w2 w3 */
1425/* w4 w5 w6 */
1426/* w7 w8 */
1427/* w4 */
1428 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1429/* w6 */
1430 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1431/* w2 */
1432 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1433/* w8 */
1434 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1435/* w5 */
1436 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1437 avg_lum >>= 4;
1438 sd->avg_lum = avg_lum;
1439 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1440 setautogain(gspca_dev);
1441 return;
1442 }
1443 if (gspca_dev->last_packet_type == LAST_PACKET) {
1444
1445 /* put the JPEG 422 header */
1446 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1447 }
1448 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1449}
1450
1451static unsigned int getexposure(struct gspca_dev *gspca_dev)
1452{
1453 struct sd *sd = (struct sd *) gspca_dev;
1454 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001455
1456 switch (sd->sensor) {
1457 case SENSOR_HV7131R:
1458 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001459 i2c_r5(gspca_dev, 0x25);
1460 return (gspca_dev->usb_buf[0] << 16)
1461 | (gspca_dev->usb_buf[1] << 8)
1462 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001463 case SENSOR_MI0360:
1464 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001465 i2c_r5(gspca_dev, 0x09);
1466 return (gspca_dev->usb_buf[0] << 8)
1467 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001468 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001469 i2c_r5(gspca_dev, 0x0e);
1470 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1471 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1472 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001473 PDEBUG(D_CONF, "exposure %d",
1474 (hexpo << 10) | (mexpo << 2) | lexpo);
1475 return (hexpo << 10) | (mexpo << 2) | lexpo;
1476 default:
1477/* case SENSOR_OV7660: */
1478 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001479 i2c_r5(gspca_dev, 0x04);
1480 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1481 lexpo = gspca_dev->usb_buf[0] & 0x02;
1482 i2c_r5(gspca_dev, 0x08);
1483 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001484 return (hexpo << 10) | (mexpo << 2) | lexpo;
1485 }
1486}
1487
1488static void getbrightness(struct gspca_dev *gspca_dev)
1489{
1490 struct sd *sd = (struct sd *) gspca_dev;
1491
1492 /* hardcoded registers seem not readable */
1493 switch (sd->sensor) {
1494 case SENSOR_HV7131R:
1495/* sd->brightness = 0x7fff; */
1496 sd->brightness = getexposure(gspca_dev) >> 4;
1497 break;
1498 case SENSOR_MI0360:
1499 sd->brightness = getexposure(gspca_dev) << 4;
1500 break;
1501 case SENSOR_MO4000:
1502/* sd->brightness = 0x1fff; */
1503 sd->brightness = getexposure(gspca_dev) << 4;
1504 break;
1505 }
1506}
1507
1508static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1509{
1510 struct sd *sd = (struct sd *) gspca_dev;
1511
1512 sd->brightness = val;
1513 if (gspca_dev->streaming)
1514 setbrightness(gspca_dev);
1515 return 0;
1516}
1517
1518static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1519{
1520 struct sd *sd = (struct sd *) gspca_dev;
1521
1522 getbrightness(gspca_dev);
1523 *val = sd->brightness;
1524 return 0;
1525}
1526
1527static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1528{
1529 struct sd *sd = (struct sd *) gspca_dev;
1530
1531 sd->contrast = val;
1532 if (gspca_dev->streaming)
1533 setcontrast(gspca_dev);
1534 return 0;
1535}
1536
1537static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1538{
1539 struct sd *sd = (struct sd *) gspca_dev;
1540
1541 *val = sd->contrast;
1542 return 0;
1543}
1544
1545static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1546{
1547 struct sd *sd = (struct sd *) gspca_dev;
1548
1549 sd->colors = val;
1550 if (gspca_dev->streaming)
1551 setcolors(gspca_dev);
1552 return 0;
1553}
1554
1555static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1556{
1557 struct sd *sd = (struct sd *) gspca_dev;
1558
1559 *val = sd->colors;
1560 return 0;
1561}
1562
1563static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1564{
1565 struct sd *sd = (struct sd *) gspca_dev;
1566
1567 sd->autogain = val;
1568 if (val)
1569 sd->ag_cnt = AG_CNT_START;
1570 else
1571 sd->ag_cnt = -1;
1572 return 0;
1573}
1574
1575static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1576{
1577 struct sd *sd = (struct sd *) gspca_dev;
1578
1579 *val = sd->autogain;
1580 return 0;
1581}
1582
1583/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001584static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001585 .name = MODULE_NAME,
1586 .ctrls = sd_ctrls,
1587 .nctrls = ARRAY_SIZE(sd_ctrls),
1588 .config = sd_config,
1589 .open = sd_open,
1590 .start = sd_start,
1591 .stopN = sd_stopN,
1592 .stop0 = sd_stop0,
1593 .close = sd_close,
1594 .pkt_scan = sd_pkt_scan,
1595};
1596
1597/* -- module initialisation -- */
1598#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001599static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001600#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001601 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1602 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1603 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1604 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1605 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001606#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001607 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1608 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1609 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1610 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1611 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1612 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1613 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1614 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1615 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001616#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001617 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1618 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1619 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1620 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001621#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001622 {}
1623};
1624MODULE_DEVICE_TABLE(usb, device_table);
1625
1626/* -- device connect -- */
1627static int sd_probe(struct usb_interface *intf,
1628 const struct usb_device_id *id)
1629{
1630 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1631 THIS_MODULE);
1632}
1633
1634static struct usb_driver sd_driver = {
1635 .name = MODULE_NAME,
1636 .id_table = device_table,
1637 .probe = sd_probe,
1638 .disconnect = gspca_disconnect,
1639};
1640
1641/* -- module insert / remove -- */
1642static int __init sd_mod_init(void)
1643{
1644 if (usb_register(&sd_driver) < 0)
1645 return -1;
1646 info("v%s registered", version);
1647 return 0;
1648}
1649static void __exit sd_mod_exit(void)
1650{
1651 usb_deregister(&sd_driver);
1652 info("deregistered");
1653}
1654
1655module_init(sd_mod_init);
1656module_exit(sd_mod_exit);