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