V4L/DVB (8180): Source cleanup - compile error with VIDEO_ADV_DEBUG.
[linux-2.6-block.git] / drivers / media / video / gspca / sonixj.c
CommitLineData
6a7eba24
JFM
1/*
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
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
28static const char version[] = "2.1.0";
29
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,
518 __u8 *buffer,
519 int len)
520{
521 usb_control_msg(dev,
522 usb_sndctrlpipe(dev, 0),
523 0x08,
524 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
525 value, 0,
526 buffer, len,
527 500);
528}
529
530/* write 2 bytes */
531static void i2c_w2(struct gspca_dev *gspca_dev,
532 __u8 *buffer)
533{
534 struct sd *sd = (struct sd *) gspca_dev;
535 struct usb_device *dev = gspca_dev->dev;
536 __u8 mode[8];
537
538 /* is i2c ready */
539 mode[0] = sd->i2c_ctrl_reg | (2 << 4);
540 mode[1] = sd->i2c_base;
541 mode[2] = buffer[0];
542 mode[3] = buffer[1];
543 mode[4] = 0;
544 mode[5] = 0;
545 mode[6] = 0;
546 mode[7] = 0x10;
547 reg_w(dev, 0x08, mode, 8);
548}
549
550/* write 8 bytes */
551static void i2c_w8(struct usb_device *dev, __u8 *buffer)
552{
553 reg_w(dev, 0x08, buffer, 8);
554 msleep(1);
555}
556
557/* read 5 bytes */
558static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg,
559 __u8 *buffer)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 struct usb_device *dev = gspca_dev->dev;
563 __u8 mode[8];
564
565 mode[0] = sd->i2c_ctrl_reg | 0x10;
566 mode[1] = sd->i2c_base;
567 mode[2] = reg;
568 mode[3] = 0;
569 mode[4] = 0;
570 mode[5] = 0;
571 mode[6] = 0;
572 mode[7] = 0x10;
573 i2c_w8(dev, mode);
574 mode[0] = sd->i2c_ctrl_reg | (5 << 4) | 0x02;
575 mode[2] = 0;
576 i2c_w8(dev, mode);
577 reg_r(dev, 0x0a, buffer, 5);
578}
579
580static int probesensor(struct gspca_dev *gspca_dev)
581{
582 struct sd *sd = (struct sd *) gspca_dev;
583 struct usb_device *dev = gspca_dev->dev;
584 __u8 reg02;
585 static __u8 datasend[] = { 2, 0 };
586 /* reg val1 val2 val3 val4 */
587 __u8 datarecd[6];
588
589 i2c_w2(gspca_dev, datasend);
590/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
591 msleep(10);
592 reg02 = 0x66;
593 reg_w(dev, 0x02, &reg02, 1); /* Gpio on */
594 msleep(10);
595 i2c_r5(gspca_dev, 0, datarecd); /* read sensor id */
596 if (datarecd[0] == 0x02
597 && datarecd[1] == 0x09
598 && datarecd[2] == 0x01
599 && datarecd[3] == 0x00
600 && datarecd[4] == 0x00) {
601 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
602 sd->sensor = SENSOR_HV7131R;
603 return SENSOR_HV7131R;
604 }
605 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
606 datarecd[0], datarecd[1], datarecd[2]);
607 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
608 return -ENODEV;
609}
610
611static int configure_gpio(struct gspca_dev *gspca_dev,
612 __u8 *sn9c1xx)
613{
614 struct sd *sd = (struct sd *) gspca_dev;
615 struct usb_device *dev = gspca_dev->dev;
616 __u8 data;
617 __u8 regF1;
618 __u8 *reg9a;
619 static __u8 reg9a_def[] =
620 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
621 static __u8 reg9a_sn9c120[] = /* from win trace */
622 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
623 static __u8 reg9a_sn9c325[] =
624 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
625
626
627 regF1 = 0x00;
628 reg_w(dev, 0xf1, &regF1, 1);
629
630 reg_w(dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
631
632 /* configure gpio */
633 reg_w(dev, 0x01, &sn9c1xx[1], 2);
634 reg_w(dev, 0x08, &sn9c1xx[8], 2);
635 reg_w(dev, 0x17, &sn9c1xx[0x17], 3);
636 switch (sd->customid) {
637 case SN9C325:
638 reg9a = reg9a_sn9c325;
639 break;
640 case SN9C120:
641 reg9a = reg9a_sn9c120;
642 break;
643 default:
644 reg9a = reg9a_def;
645 break;
646 }
647 reg_w(dev, 0x9a, reg9a, 6);
648
649 data = 0x60; /*fixme:jfm 60 00 00 (3) */
650 reg_w(dev, 0xd4, &data, 1);
651
652 reg_w(dev, 0x03, &sn9c1xx[3], 0x0f);
653
654 switch (sd->customid) {
655 case SN9C120: /* from win trace */
656 data = 0x61;
657 reg_w(dev, 0x01, &data, 1);
658 data = 0x20;
659 reg_w(dev, 0x17, &data, 1);
660 data = 0x60;
661 reg_w(dev, 0x01, &data, 1);
662 break;
663 case SN9C325:
664 data = 0x43;
665 reg_w(dev, 0x01, &data, 1);
666 data = 0xae;
667 reg_w(dev, 0x17, &data, 1);
668 data = 0x42;
669 reg_w(dev, 0x01, &data, 1);
670 break;
671 default:
672 data = 0x43;
673 reg_w(dev, 0x01, &data, 1);
674 data = 0x61;
675 reg_w(dev, 0x17, &data, 1);
676 data = 0x42;
677 reg_w(dev, 0x01, &data, 1);
678 }
679
680 if (sd->sensor == SENSOR_HV7131R) {
681 if (probesensor(gspca_dev) < 0)
682 return -ENODEV;
683 }
684 return 0;
685}
686
687static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
688{
689 int i = 0;
690 struct usb_device *dev = gspca_dev->dev;
691 static __u8 SetSensorClk[] = /* 0x08 Mclk */
692 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
693
694 while (hv7131r_sensor_init[i][0]) {
695 i2c_w8(dev, hv7131r_sensor_init[i]);
696 i++;
697 }
698 i2c_w8(dev, SetSensorClk);
699}
700
701static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
702{
703 int i = 0;
704 struct usb_device *dev = gspca_dev->dev;
705
706 while (mi0360_sensor_init[i][0]) {
707 i2c_w8(dev, mi0360_sensor_init[i]);
708 i++;
709 }
710}
711
712static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
713{
714 int i = 0;
715 struct usb_device *dev = gspca_dev->dev;
716
717 while (mo4000_sensor_init[i][0]) {
718 i2c_w8(dev, mo4000_sensor_init[i]);
719 i++;
720 }
721}
722
723static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
724{
725 struct usb_device *dev = gspca_dev->dev;
726 int i = 0;
727
728 while (ov7648_sensor_init[i][0]) {
729 i2c_w8(dev, ov7648_sensor_init[i]);
730 i++;
731 }
732}
733
734static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
735{
736 int i = 0;
737 struct usb_device *dev = gspca_dev->dev;
738
739 while (ov7660_sensor_init[i][0]) {
740 i2c_w8(dev, ov7660_sensor_init[i]);
741 i++;
742 }
743}
744
745/* this function is called at probe time */
746static int sd_config(struct gspca_dev *gspca_dev,
747 const struct usb_device_id *id)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750 struct cam *cam;
751 __u16 vendor;
752 __u16 product;
753
754 vendor = id->idVendor;
755 product = id->idProduct;
756 sd->sensor = -1;
757 switch (vendor) {
758 case 0x0458: /* Genius */
759/* switch (product) {
760 case 0x7025: */
761 sd->customid = SN9C120;
762 sd->sensor = SENSOR_MI0360;
763 sd->i2c_ctrl_reg = 0x81;
764 sd->i2c_base = 0x5d;
765/* break;
766 } */
767 break;
768 case 0x045e:
769/* switch (product) {
770 case 0x00f5:
771 case 0x00f7: */
772 sd->customid = SN9C105;
773 sd->sensor = SENSOR_OV7660;
774 sd->i2c_ctrl_reg = 0x81;
775 sd->i2c_base = 0x21;
776/* break;
777 } */
778 break;
779 case 0x0471: /* Philips */
780/* switch (product) {
781 case 0x0327:
782 case 0x0328:
783 case 0x0330: */
784 sd->customid = SN9C105;
785 sd->sensor = SENSOR_MI0360;
786 sd->i2c_ctrl_reg = 0x81;
787 sd->i2c_base = 0x5d;
788/* break;
789 } */
790 break;
791 case 0x0c45: /* Sonix */
792 switch (product) {
793 case 0x6040:
794 sd->customid = SN9C102P;
795 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
796/* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
797 sd->i2c_ctrl_reg = 0x81;
798 sd->i2c_base = 0x11;
799 break;
800/* case 0x607a: * from BW600.inf
801 sd->customid = SN9C102P;
802 sd->sensor = SENSOR_OV7648;
803 sd->i2c_ctrl_reg = 0x??;
804 sd->i2c_base = 0x??;
805 break; */
806 case 0x607c:
807 sd->customid = SN9C102P;
808 sd->sensor = SENSOR_HV7131R;
809 sd->i2c_ctrl_reg = 0x81;
810 sd->i2c_base = 0x11;
811 break;
812/* case 0x607e: * from BW600.inf
813 sd->customid = SN9C102P;
814 sd->sensor = SENSOR_OV7630;
815 sd->i2c_ctrl_reg = 0x??;
816 sd->i2c_base = 0x??;
817 break; */
818 case 0x60c0:
819 sd->customid = SN9C105;
820 sd->sensor = SENSOR_MI0360;
821 sd->i2c_ctrl_reg = 0x81;
822 sd->i2c_base = 0x5d;
823 break;
824/* case 0x60c8: * from BW600.inf
825 sd->customid = SN9C105;
826 sd->sensor = SENSOR_OM6801;
827 sd->i2c_ctrl_reg = 0x??;
828 sd->i2c_base = 0x??;
829 break; */
830/* case 0x60cc: * from BW600.inf
831 sd->customid = SN9C105;
832 sd->sensor = SENSOR_HV7131GP;
833 sd->i2c_ctrl_reg = 0x??;
834 sd->i2c_base = 0x??;
835 break; */
836 case 0x60ec:
837 sd->customid = SN9C105;
838 sd->sensor = SENSOR_MO4000;
839 sd->i2c_ctrl_reg = 0x81;
840 sd->i2c_base = 0x21;
841 break;
842/* case 0x60ef: * from BW600.inf
843 sd->customid = SN9C105;
844 sd->sensor = SENSOR_ICM105C;
845 sd->i2c_ctrl_reg = 0x??;
846 sd->i2c_base = 0x??;
847 break; */
848/* case 0x60fa: * from BW600.inf
849 sd->customid = SN9C105;
850 sd->sensor = SENSOR_OV7648;
851 sd->i2c_ctrl_reg = 0x??;
852 sd->i2c_base = 0x??;
853 break; */
854 case 0x60fb:
855 sd->customid = SN9C105;
856 sd->sensor = SENSOR_OV7660;
857 sd->i2c_ctrl_reg = 0x81;
858 sd->i2c_base = 0x21;
859 break;
860 case 0x60fc:
861 sd->customid = SN9C105;
862 sd->sensor = SENSOR_HV7131R;
863 sd->i2c_ctrl_reg = 0x81;
864 sd->i2c_base = 0x11;
865 break;
866/* case 0x60fe: * from BW600.inf
867 sd->customid = SN9C105;
868 sd->sensor = SENSOR_OV7630;
869 sd->i2c_ctrl_reg = 0x??;
870 sd->i2c_base = 0x??;
871 break; */
872/* case 0x6108: * from BW600.inf
873 sd->customid = SN9C120;
874 sd->sensor = SENSOR_OM6801;
875 sd->i2c_ctrl_reg = 0x??;
876 sd->i2c_base = 0x??;
877 break; */
878/* case 0x6122: * from BW600.inf
879 sd->customid = SN9C110;
880 sd->sensor = SENSOR_ICM105C;
881 sd->i2c_ctrl_reg = 0x??;
882 sd->i2c_base = 0x??;
883 break; */
884 case 0x612a:
885/* sd->customid = SN9C110; * in BW600.inf */
886 sd->customid = SN9C325;
887 sd->sensor = SENSOR_OV7648;
888 sd->i2c_ctrl_reg = 0x81;
889 sd->i2c_base = 0x21;
890 break;
891/* case 0x6123: * from BW600.inf
892 sd->customid = SN9C110;
893 sd->sensor = SENSOR_SanyoCCD;
894 sd->i2c_ctrl_reg = 0x??;
895 sd->i2c_base = 0x??;
896 break; */
897 case 0x612c:
898 sd->customid = SN9C110;
899 sd->sensor = SENSOR_MO4000;
900 sd->i2c_ctrl_reg = 0x81;
901 sd->i2c_base = 0x21;
902 break;
903/* case 0x612e: * from BW600.inf
904 sd->customid = SN9C110;
905 sd->sensor = SENSOR_OV7630;
906 sd->i2c_ctrl_reg = 0x??;
907 sd->i2c_base = 0x??;
908 break; */
909/* case 0x612f: * from BW600.inf
910 sd->customid = SN9C110;
911 sd->sensor = SENSOR_ICM105C;
912 sd->i2c_ctrl_reg = 0x??;
913 sd->i2c_base = 0x??;
914 break; */
915 case 0x6130:
916 sd->customid = SN9C120;
917 sd->sensor = SENSOR_MI0360;
918 sd->i2c_ctrl_reg = 0x81;
919 sd->i2c_base = 0x5d;
920 break;
921 case 0x6138:
922 sd->customid = SN9C120;
923 sd->sensor = SENSOR_MO4000;
924 sd->i2c_ctrl_reg = 0x81;
925 sd->i2c_base = 0x21;
926 break;
927/* case 0x613a: * from BW600.inf
928 sd->customid = SN9C120;
929 sd->sensor = SENSOR_OV7648;
930 sd->i2c_ctrl_reg = 0x??;
931 sd->i2c_base = 0x??;
932 break; */
933 case 0x613b:
934 sd->customid = SN9C120;
935 sd->sensor = SENSOR_OV7660;
936 sd->i2c_ctrl_reg = 0x81;
937 sd->i2c_base = 0x21;
938 break;
939 case 0x613c:
940 sd->customid = SN9C120;
941 sd->sensor = SENSOR_HV7131R;
942 sd->i2c_ctrl_reg = 0x81;
943 sd->i2c_base = 0x11;
944 break;
945/* case 0x613e: * from BW600.inf
946 sd->customid = SN9C120;
947 sd->sensor = SENSOR_OV7630;
948 sd->i2c_ctrl_reg = 0x??;
949 sd->i2c_base = 0x??;
950 break; */
951 }
952 break;
953 }
954 if (sd->sensor < 0) {
955 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
956 vendor, product);
957 return -EINVAL;
958 }
959
960 cam = &gspca_dev->cam;
961 cam->dev_name = (char *) id->driver_info;
962 cam->epaddr = 0x01;
963 cam->cam_mode = vga_mode;
964 cam->nmodes = ARRAY_SIZE(vga_mode);
965 sd->qindex = 4; /* set the quantization table */
966 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
967 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
968 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
969 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
970 return 0;
971}
972
973/* this function is called at open time */
974static int sd_open(struct gspca_dev *gspca_dev)
975{
976 struct sd *sd = (struct sd *) gspca_dev;
977 struct usb_device *dev = gspca_dev->dev;
978/* __u8 *sn9c1xx; */
979 __u8 regF1;
980 __u8 regGpio[] = { 0x29, 0x74 };
981
982 /* setup a selector by customid */
983 regF1 = 0x01;
984 reg_w(dev, 0xf1, &regF1, 1);
985 reg_r(dev, 0x00, &regF1, 1); /* -> regF1 = 0x00 */
986 reg_w(dev, 0xf1, &regF1, 1);
987 reg_r(dev, 0x00, &regF1, 1);
988 switch (sd->customid) {
989 case SN9C102P:
990 if (regF1 != 0x11)
991 return -ENODEV;
992 reg_w(dev, 0x02, &regGpio[1], 1);
993 break;
994 case SN9C105:
995 if (regF1 != 0x11)
996 return -ENODEV;
997 reg_w(dev, 0x02, regGpio, 2);
998 break;
999 case SN9C110:
1000 if (regF1 != 0x12)
1001 return -ENODEV;
1002 regGpio[1] = 0x62;
1003 reg_w(dev, 0x02, &regGpio[1], 1);
1004 break;
1005 case SN9C120:
1006 if (regF1 != 0x12)
1007 return -ENODEV;
1008 regGpio[1] = 0x70;
1009 reg_w(dev, 0x02, regGpio, 2);
1010 break;
1011 default:
1012/* case SN9C325: */
1013 if (regF1 != 0x12)
1014 return -ENODEV;
1015 regGpio[1] = 0x62;
1016 reg_w(dev, 0x02, &regGpio[1], 1);
1017 break;
1018 }
1019
1020 regF1 = 0x01;
1021 reg_w(dev, 0xf1, &regF1, 1);
1022
1023 return 0;
1024}
1025
1026static unsigned int setexposure(struct gspca_dev *gspca_dev,
1027 unsigned int expo)
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
1030 static __u8 doit[] = /* update sensor */
1031 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1032 static __u8 sensorgo[] = /* sensor on */
1033 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1034 static __u8 gainMo[] =
1035 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1036
1037 switch (sd->sensor) {
1038 case SENSOR_HV7131R: {
1039 __u8 Expodoit[] =
1040 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1041
1042 Expodoit[3] = expo >> 16;
1043 Expodoit[4] = expo >> 8;
1044 Expodoit[5] = expo;
1045 i2c_w8(gspca_dev->dev, Expodoit);
1046 break;
1047 }
1048 case SENSOR_MI0360: {
1049 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1050 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1051
1052 if (expo > 0x0635)
1053 expo = 0x0635;
1054 else if (expo < 0x0001)
1055 expo = 0x0001;
1056 expoMi[3] = expo >> 8;
1057 expoMi[4] = expo;
1058 i2c_w8(gspca_dev->dev, expoMi);
1059 i2c_w8(gspca_dev->dev, doit);
1060 i2c_w8(gspca_dev->dev, sensorgo);
1061 break;
1062 }
1063 case SENSOR_MO4000: {
1064 __u8 expoMof[] =
1065 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1066 __u8 expoMo10[] =
1067 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1068
1069 if (expo > 0x1fff)
1070 expo = 0x1fff;
1071 else if (expo < 0x0001)
1072 expo = 0x0001;
1073 expoMof[3] = (expo & 0x03fc) >> 2;
1074 i2c_w8(gspca_dev->dev, expoMof);
1075 expoMo10[3] = ((expo & 0x1c00) >> 10)
1076 | ((expo & 0x0003) << 4);
1077 i2c_w8(gspca_dev->dev, expoMo10);
1078 i2c_w8(gspca_dev->dev, gainMo);
956e42d2 1079 PDEBUG(D_CONF, "set exposure %d",
6a7eba24
JFM
1080 ((expoMo10[3] & 0x07) << 10)
1081 | (expoMof[3] << 2)
1082 | ((expoMo10[3] & 0x30) >> 4));
1083 break;
1084 }
1085 }
1086 return expo;
1087}
1088
1089static void setbrightness(struct gspca_dev *gspca_dev)
1090{
1091 struct sd *sd = (struct sd *) gspca_dev;
1092 unsigned int expo;
1093 __u8 k2;
1094
1095 switch (sd->sensor) {
1096 case SENSOR_HV7131R:
1097 expo = sd->brightness << 4;
1098 if (expo > 0x002dc6c0)
1099 expo = 0x002dc6c0;
1100 else if (expo < 0x02a0)
1101 expo = 0x02a0;
1102 sd->exposure = setexposure(gspca_dev, expo);
1103 break;
1104 case SENSOR_MI0360:
1105 expo = sd->brightness >> 4;
1106 sd->exposure = setexposure(gspca_dev, expo);
1107 break;
1108 case SENSOR_MO4000:
1109 expo = sd->brightness >> 4;
1110 sd->exposure = setexposure(gspca_dev, expo);
1111 break;
1112 case SENSOR_OV7660:
1113 return; /*jfm??*/
1114 }
1115
1116 k2 = sd->brightness >> 10;
1117 reg_w(gspca_dev->dev, 0x96, &k2, 1);
1118}
1119
1120static void setcontrast(struct gspca_dev *gspca_dev)
1121{
1122 struct sd *sd = (struct sd *) gspca_dev;
1123 __u8 k2;
1124 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1125
1126 if (sd->sensor == SENSOR_OV7660)
1127 return; /*jfm??*/
1128 k2 = sd->contrast;
1129 contrast[2] = k2;
1130 contrast[0] = (k2 + 1) >> 1;
1131 contrast[4] = (k2 + 1) / 5;
1132 reg_w(gspca_dev->dev, 0x84, contrast, 6);
1133}
1134
1135static void setcolors(struct gspca_dev *gspca_dev)
1136{
1137 struct sd *sd = (struct sd *) gspca_dev;
1138 __u8 data;
1139 int colour;
1140
1141 colour = sd->colors - 128;
1142 if (colour > 0)
1143 data = (colour + 32) & 0x7f; /* blue */
1144 else
1145 data = (-colour + 32) & 0x7f; /* red */
1146 reg_w(gspca_dev->dev, 0x05, &data, 1);
1147}
1148
1149/* -- start the camera -- */
1150static void sd_start(struct gspca_dev *gspca_dev)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153 struct usb_device *dev = gspca_dev->dev;
1154 int i;
1155 __u8 data;
1156 __u8 reg1;
1157 __u8 reg17;
1158 __u8 *sn9c1xx;
1159 int mode;
1160 static __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1161 static __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1162 static __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1163 static __u8 CA_sn9c120[] = { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1164 static __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1165 static __u8 CE_sn9c325[] =
1166 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1167
1168 sn9c1xx = sn_tb[(int) sd->sensor];
1169 configure_gpio(gspca_dev, sn9c1xx);
1170
1171/*fixme:jfm this sequence should appear at end of sd_start */
1172/* with
1173 data = 0x44;
1174 reg_w(dev, 0x01, &data, 1); */
1175 reg_w(dev, 0x15, &sn9c1xx[0x15], 1);
1176 reg_w(dev, 0x16, &sn9c1xx[0x16], 1);
1177 reg_w(dev, 0x12, &sn9c1xx[0x12], 1);
1178 reg_w(dev, 0x13, &sn9c1xx[0x13], 1);
1179 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1180 reg_w(dev, 0xd2, &DC29[0], 1);
1181 reg_w(dev, 0xd3, &DC29[1], 1);
1182 reg_w(dev, 0xc6, &DC29[2], 1);
1183 reg_w(dev, 0xc7, &DC29[3], 1);
1184 reg_w(dev, 0xc8, &DC29[4], 1);
1185 reg_w(dev, 0xc9, &DC29[5], 1);
1186/*fixme:jfm end of ending sequence */
1187 reg_w(dev, 0x18, &sn9c1xx[0x18], 1);
1188 if (sd->customid == SN9C325)
1189 data = 0xae;
1190 else
1191 data = 0x60;
1192 reg_w(dev, 0x17, &data, 1);
1193 reg_w(dev, 0x05, &sn9c1xx[5], 1);
1194 reg_w(dev, 0x07, &sn9c1xx[7], 1);
1195 reg_w(dev, 0x06, &sn9c1xx[6], 1);
1196 reg_w(dev, 0x14, &sn9c1xx[0x14], 1);
1197 if (sd->customid == SN9C325) {
1198 reg_w(dev, 0x20, regsn20_sn9c325, 0x11);
1199 for (i = 0; i < 8; i++)
1200 reg_w(dev, 0x84, reg84_sn9c325, 0x15);
1201 data = 0x0a;
1202 reg_w(dev, 0x9a, &data, 1);
1203 data = 0x60;
1204 reg_w(dev, 0x99, &data, 1);
1205 } else {
1206 reg_w(dev, 0x20, regsn20, 0x11);
1207 for (i = 0; i < 8; i++)
1208 reg_w(dev, 0x84, reg84, 0x15);
1209 data = 0x08;
1210 reg_w(dev, 0x9a, &data, 1);
1211 data = 0x59;
1212 reg_w(dev, 0x99, &data, 1);
1213 }
1214
1215 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
1216 reg1 = 0x02;
1217 reg17 = 0x61;
1218 switch (sd->sensor) {
1219 case SENSOR_HV7131R:
1220 hv7131R_InitSensor(gspca_dev);
1221 if (mode)
1222 reg1 = 0x46; /* 320 clk 48Mhz */
1223 else
1224 reg1 = 0x06; /* 640 clk 24Mz */
1225 break;
1226 case SENSOR_MI0360:
1227 mi0360_InitSensor(gspca_dev);
1228 if (mode)
1229 reg1 = 0x46; /* 320 clk 48Mhz */
1230 else
1231 reg1 = 0x06; /* 640 clk 24Mz */
1232 break;
1233 case SENSOR_MO4000:
1234 mo4000_InitSensor(gspca_dev);
1235 if (mode) {
1236/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1237 reg1 = 0x06; /* clk 24Mz */
1238 } else {
1239 reg17 = 0x22; /* 640 MCKSIZE */
1240 reg1 = 0x06; /* 640 clk 24Mz */
1241 }
1242 break;
1243 case SENSOR_OV7648:
1244 reg17 = 0xa2;
1245 reg1 = 0x44;
1246 ov7648_InitSensor(gspca_dev);
1247/* if (mode)
1248 ; * 320x2...
1249 else
1250 ; * 640x... */
1251 break;
1252 default:
1253/* case SENSOR_OV7660: */
1254 ov7660_InitSensor(gspca_dev);
1255 if (mode) {
1256/* reg17 = 0x21; * 320 */
1257/* reg1 = 0x44; */
1258 reg1 = 0x46;
1259 } else {
1260 reg17 = 0xa2; /* 640 */
1261 reg1 = 0x40;
1262 }
1263 break;
1264 }
1265 reg_w(dev, 0xc0, C0, 6);
1266 switch (sd->customid) {
1267 case SN9C120: /*jfm ?? */
1268 reg_w(dev, 0xca, CA_sn9c120, 4);
1269 break;
1270 default:
1271 reg_w(dev, 0xca, CA, 4);
1272 break;
1273 }
1274 switch (sd->customid) {
1275 case SN9C120: /*jfm ?? */
1276 case SN9C325:
1277 reg_w(dev, 0xce, CE_sn9c325, 4);
1278 break;
1279 default:
1280 reg_w(dev, 0xce, CE, 4);
1281 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1282 break;
1283 }
1284
1285 /* here change size mode 0 -> VGA; 1 -> CIF */
1286 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1287 reg_w(dev, 0x18, &data, 1);
1288
1289 reg_w(dev, 0x100, qtable4, 0x40);
1290 reg_w(dev, 0x140, qtable4 + 0x40, 0x40);
1291
1292 data = sn9c1xx[0x18] | (mode << 4);
1293 reg_w(dev, 0x18, &data, 1);
1294
1295 reg_w(dev, 0x17, &reg17, 1);
1296 reg_w(dev, 0x01, &reg1, 1);
1297 setbrightness(gspca_dev);
1298 setcontrast(gspca_dev);
1299}
1300
1301static void sd_stopN(struct gspca_dev *gspca_dev)
1302{
1303 struct sd *sd = (struct sd *) gspca_dev;
1304 struct usb_device *dev = gspca_dev->dev;
1305 static __u8 stophv7131[] =
1306 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1307 static __u8 stopmi0360[] =
1308 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1309 __u8 regF1;
1310 __u8 data;
1311 __u8 *sn9c1xx;
1312
1313 data = 0x0b;
1314 switch (sd->sensor) {
1315 case SENSOR_HV7131R:
1316 i2c_w8(dev, stophv7131);
1317 data = 0x2b;
1318 break;
1319 case SENSOR_MI0360:
1320 i2c_w8(dev, stopmi0360);
1321 data = 0x29;
1322 break;
1323 case SENSOR_MO4000:
1324 break;
1325 case SENSOR_OV7648:
1326 data = 0x29;
1327 break;
1328 default:
1329/* case SENSOR_OV7660: */
1330 break;
1331 }
1332 sn9c1xx = sn_tb[(int) sd->sensor];
1333 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1334 reg_w(dev, 0x17, &sn9c1xx[0x17], 1);
1335 reg_w(dev, 0x01, &sn9c1xx[1], 1);
1336 reg_w(dev, 0x01, &data, 1);
1337 regF1 = 0x01;
1338 reg_w(dev, 0xf1, &regF1, 1);
1339}
1340
1341static void sd_stop0(struct gspca_dev *gspca_dev)
1342{
1343}
1344
1345static void sd_close(struct gspca_dev *gspca_dev)
1346{
1347}
1348
1349static void setautogain(struct gspca_dev *gspca_dev)
1350{
1351 struct sd *sd = (struct sd *) gspca_dev;
1352 /* Thanks S., without your advice, autobright should not work :) */
1353 int delta;
1354 int expotimes = 0;
1355 __u8 luma_mean = 130;
1356 __u8 luma_delta = 20;
1357
1358 delta = sd->avg_lum;
1359 if (delta < luma_mean - luma_delta ||
1360 delta > luma_mean + luma_delta) {
1361 switch (sd->sensor) {
1362 case SENSOR_HV7131R:
1363 expotimes = sd->exposure >> 8;
1364 expotimes += (luma_mean - delta) >> 4;
1365 if (expotimes < 0)
1366 expotimes = 0;
1367 sd->exposure = setexposure(gspca_dev,
1368 (unsigned int) (expotimes << 8));
1369 break;
1370 case SENSOR_MO4000:
1371 case SENSOR_MI0360:
1372 expotimes = sd->exposure;
1373 expotimes += (luma_mean - delta) >> 6;
1374 if (expotimes < 0)
1375 expotimes = 0;
1376 sd->exposure = setexposure(gspca_dev,
1377 (unsigned int) expotimes);
1378 setcolors(gspca_dev);
1379 break;
1380 }
1381 }
1382}
1383
1384static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1385 struct gspca_frame *frame, /* target */
1386 unsigned char *data, /* isoc packet */
1387 int len) /* iso packet length */
1388{
1389 struct sd *sd = (struct sd *) gspca_dev;
1390 int sof, avg_lum;
1391
1392 sof = len - 64;
1393 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1394
1395 /* end of frame */
1396 gspca_frame_add(gspca_dev, LAST_PACKET,
1397 frame, data, sof + 2);
1398 if (sd->ag_cnt < 0)
1399 return;
1400 if (--sd->ag_cnt >= 0)
1401 return;
1402 sd->ag_cnt = AG_CNT_START;
1403/* w1 w2 w3 */
1404/* w4 w5 w6 */
1405/* w7 w8 */
1406/* w4 */
1407 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1408/* w6 */
1409 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1410/* w2 */
1411 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1412/* w8 */
1413 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1414/* w5 */
1415 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1416 avg_lum >>= 4;
1417 sd->avg_lum = avg_lum;
1418 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1419 setautogain(gspca_dev);
1420 return;
1421 }
1422 if (gspca_dev->last_packet_type == LAST_PACKET) {
1423
1424 /* put the JPEG 422 header */
1425 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1426 }
1427 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1428}
1429
1430static unsigned int getexposure(struct gspca_dev *gspca_dev)
1431{
1432 struct sd *sd = (struct sd *) gspca_dev;
1433 __u8 hexpo, mexpo, lexpo;
1434 __u8 expo[6];
1435
1436 switch (sd->sensor) {
1437 case SENSOR_HV7131R:
1438 /* read sensor exposure */
1439 i2c_r5(gspca_dev, 0x25, expo);
1440 return (expo[0] << 16) | (expo[1] << 8) | expo[2];
1441 case SENSOR_MI0360:
1442 /* read sensor exposure */
1443 i2c_r5(gspca_dev, 0x09, expo);
1444 return (expo[0] << 8) | expo[1];
1445 case SENSOR_MO4000:
1446 i2c_r5(gspca_dev, 0x0e, expo);
1447 hexpo = 0; /* expo[1] & 0x07; */
1448 mexpo = 0x40; /* expo[2] &0xff; */
1449 lexpo = (expo[1] & 0x30) >> 4;
1450 PDEBUG(D_CONF, "exposure %d",
1451 (hexpo << 10) | (mexpo << 2) | lexpo);
1452 return (hexpo << 10) | (mexpo << 2) | lexpo;
1453 default:
1454/* case SENSOR_OV7660: */
1455 /* read sensor exposure */
1456 i2c_r5(gspca_dev, 0x04, expo);
1457 hexpo = expo[3] & 0x2f;
1458 lexpo = expo[0] & 0x02;
1459 i2c_r5(gspca_dev, 0x08, expo);
1460 mexpo = expo[2];
1461 return (hexpo << 10) | (mexpo << 2) | lexpo;
1462 }
1463}
1464
1465static void getbrightness(struct gspca_dev *gspca_dev)
1466{
1467 struct sd *sd = (struct sd *) gspca_dev;
1468
1469 /* hardcoded registers seem not readable */
1470 switch (sd->sensor) {
1471 case SENSOR_HV7131R:
1472/* sd->brightness = 0x7fff; */
1473 sd->brightness = getexposure(gspca_dev) >> 4;
1474 break;
1475 case SENSOR_MI0360:
1476 sd->brightness = getexposure(gspca_dev) << 4;
1477 break;
1478 case SENSOR_MO4000:
1479/* sd->brightness = 0x1fff; */
1480 sd->brightness = getexposure(gspca_dev) << 4;
1481 break;
1482 }
1483}
1484
1485static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1486{
1487 struct sd *sd = (struct sd *) gspca_dev;
1488
1489 sd->brightness = val;
1490 if (gspca_dev->streaming)
1491 setbrightness(gspca_dev);
1492 return 0;
1493}
1494
1495static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1496{
1497 struct sd *sd = (struct sd *) gspca_dev;
1498
1499 getbrightness(gspca_dev);
1500 *val = sd->brightness;
1501 return 0;
1502}
1503
1504static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1505{
1506 struct sd *sd = (struct sd *) gspca_dev;
1507
1508 sd->contrast = val;
1509 if (gspca_dev->streaming)
1510 setcontrast(gspca_dev);
1511 return 0;
1512}
1513
1514static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1515{
1516 struct sd *sd = (struct sd *) gspca_dev;
1517
1518 *val = sd->contrast;
1519 return 0;
1520}
1521
1522static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1523{
1524 struct sd *sd = (struct sd *) gspca_dev;
1525
1526 sd->colors = val;
1527 if (gspca_dev->streaming)
1528 setcolors(gspca_dev);
1529 return 0;
1530}
1531
1532static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1533{
1534 struct sd *sd = (struct sd *) gspca_dev;
1535
1536 *val = sd->colors;
1537 return 0;
1538}
1539
1540static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1541{
1542 struct sd *sd = (struct sd *) gspca_dev;
1543
1544 sd->autogain = val;
1545 if (val)
1546 sd->ag_cnt = AG_CNT_START;
1547 else
1548 sd->ag_cnt = -1;
1549 return 0;
1550}
1551
1552static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 *val = sd->autogain;
1557 return 0;
1558}
1559
1560/* sub-driver description */
1561static struct sd_desc sd_desc = {
1562 .name = MODULE_NAME,
1563 .ctrls = sd_ctrls,
1564 .nctrls = ARRAY_SIZE(sd_ctrls),
1565 .config = sd_config,
1566 .open = sd_open,
1567 .start = sd_start,
1568 .stopN = sd_stopN,
1569 .stop0 = sd_stop0,
1570 .close = sd_close,
1571 .pkt_scan = sd_pkt_scan,
1572};
1573
1574/* -- module initialisation -- */
1575#define DVNM(name) .driver_info = (kernel_ulong_t) name
1576static __devinitdata struct usb_device_id device_table[] = {
1577 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1578 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1579 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1580 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1581 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1582 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1583 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1584 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1585 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1586 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1587 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1588 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1589 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1590 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1591 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1592 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1593 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1594 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1595 {}
1596};
1597MODULE_DEVICE_TABLE(usb, device_table);
1598
1599/* -- device connect -- */
1600static int sd_probe(struct usb_interface *intf,
1601 const struct usb_device_id *id)
1602{
1603 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1604 THIS_MODULE);
1605}
1606
1607static struct usb_driver sd_driver = {
1608 .name = MODULE_NAME,
1609 .id_table = device_table,
1610 .probe = sd_probe,
1611 .disconnect = gspca_disconnect,
1612};
1613
1614/* -- module insert / remove -- */
1615static int __init sd_mod_init(void)
1616{
1617 if (usb_register(&sd_driver) < 0)
1618 return -1;
1619 info("v%s registered", version);
1620 return 0;
1621}
1622static void __exit sd_mod_exit(void)
1623{
1624 usb_deregister(&sd_driver);
1625 info("deregistered");
1626}
1627
1628module_init(sd_mod_init);
1629module_exit(sd_mod_exit);