2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define MODULE_NAME "sonixb"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
28 static const char version[] = "2.1.0";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 unsigned char brightness;
39 unsigned char contrast;
41 char sensor; /* Type of image sensor chip */
42 #define SENSOR_HV7131R 0
43 #define SENSOR_OV6650 1
44 #define SENSOR_OV7630 2
45 #define SENSOR_OV7630_3 3
46 #define SENSOR_PAS106 4
47 #define SENSOR_PAS202 5
48 #define SENSOR_TAS5110 6
49 #define SENSOR_TAS5130CXX 7
53 #define COMP 0xc7 /* 0x87 //0x07 */
54 #define COMP1 0xc9 /* 0x89 //0x09 */
57 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
61 /* V4L2 controls supported by the driver */
62 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67 static struct ctrl sd_ctrls[] = {
68 #define SD_BRIGHTNESS 0
71 .id = V4L2_CID_BRIGHTNESS,
72 .type = V4L2_CTRL_TYPE_INTEGER,
79 .set = sd_setbrightness,
80 .get = sd_getbrightness,
85 .id = V4L2_CID_CONTRAST,
86 .type = V4L2_CTRL_TYPE_INTEGER,
93 .set = sd_setcontrast,
94 .get = sd_getcontrast,
98 /* fixme: should have V4L2_PIX_FMT_SN9C10X */
99 static struct cam_mode vga_mode[] = {
100 {V4L2_PIX_FMT_SN9C10X, 160, 120, 2},
101 {V4L2_PIX_FMT_SN9C10X, 320, 240, 1},
102 {V4L2_PIX_FMT_SN9C10X, 640, 480, 0},
104 static struct cam_mode sif_mode[] = {
105 {V4L2_PIX_FMT_SN9C10X, 176, 144, 1},
106 {V4L2_PIX_FMT_SN9C10X, 352, 288, 0},
109 static const __u8 probe_ov7630[] = {0x08, 0x44};
111 static const __u8 initHv7131[] = {
112 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
115 0x28, 0x1e, 0x60, 0x8a, 0x20,
116 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
118 static const __u8 hv7131_sensor_init[][8] = {
119 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
120 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
121 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
122 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
123 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
125 static const __u8 initOv6650[] = {
126 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
127 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
129 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
131 static const __u8 ov6650_sensor_init[][8] =
133 /* Bright, contrast, etc are set througth SCBB interface.
134 * AVCAP on win2 do not send any data on this controls. */
135 /* Anyway, some registers appears to alter bright and constrat */
136 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
137 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
138 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
139 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
140 * THIS SET GREEN SCREEN
141 * (pixels could be innverted in decode kind of "brg",
142 * but blue wont be there. Avoid this data ... */
143 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
144 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
145 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
146 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
147 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
148 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
149 {0xa0, 0x60, 0x10, 0x5d, 0x99, 0x04, 0x94, 0x16},
150 {0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
151 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
152 {0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
153 {0xa0, 0x60, 0x11, 0xc0, 0x99, 0x04, 0x94, 0x16},
154 {0xa0, 0x60, 0x00, 0x16, 0x99, 0x04, 0x94, 0x15}, /* bright / Lumino */
155 {0xa0, 0x60, 0x2b, 0xab, 0x99, 0x04, 0x94, 0x15},
156 /* ?flicker o brillo */
157 {0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
158 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
159 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
160 {0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
161 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
162 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
163 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
164 /* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
165 {0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
166 /* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
167 /* {0xa0, 0x60, 0x11, 0xc1, 0x99, 0x04, 0x94, 0x16}, */
168 {0xa0, 0x60, 0x00, 0x17, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
169 {0xa0, 0x60, 0x00, 0x18, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
171 static const __u8 initOv7630[] = {
172 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
173 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
174 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
175 0x28, 0x1e, /* H & V sizes r15 .. r16 */
176 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
177 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
179 static const __u8 initOv7630_3[] = {
180 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
181 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
182 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
183 0x28, 0x1e, /* H & V sizes r15 .. r16 */
184 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
185 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
187 static const __u8 ov7630_sensor_init_com[][8] = {
188 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
189 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
190 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
191 {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
192 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
193 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
194 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
195 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
196 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
197 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
198 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
199 /* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
200 {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
201 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
202 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
203 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
204 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
205 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
206 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
208 static const __u8 ov7630_sensor_init[][8] = {
209 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
210 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
211 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
212 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
213 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
215 static const __u8 ov7630_sensor_init_3[][8] = {
216 {0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
217 {0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
218 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
219 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
220 /* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
221 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
222 /* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
223 {0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
226 static const __u8 initPas106[] = {
227 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
230 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
231 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
233 /* compression 0x86 mckinit1 0x2b */
234 static const __u8 pas106_data[][2] = {
235 {0x02, 0x04}, /* Pixel Clock Divider 6 */
236 {0x03, 0x13}, /* Frame Time MSB */
237 /* {0x03, 0x12}, * Frame Time MSB */
238 {0x04, 0x06}, /* Frame Time LSB */
239 /* {0x04, 0x05}, * Frame Time LSB */
240 {0x05, 0x65}, /* Shutter Time Line Offset */
241 /* {0x05, 0x6d}, * Shutter Time Line Offset */
242 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
243 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
244 {0x07, 0xc1}, /* Black Level Subtract Sign */
245 /* {0x07, 0x00}, * Black Level Subtract Sign */
246 {0x08, 0x06}, /* Black Level Subtract Level */
247 {0x08, 0x06}, /* Black Level Subtract Level */
248 /* {0x08, 0x01}, * Black Level Subtract Level */
249 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
250 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
251 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
252 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
253 {0x0d, 0x00}, /* Color GainH Pixel */
254 {0x0e, 0x0e}, /* Global Gain */
255 {0x0f, 0x00}, /* Contrast */
256 {0x10, 0x06}, /* H&V synchro polarity */
257 {0x11, 0x06}, /* ?default */
258 {0x12, 0x06}, /* DAC scale */
259 {0x14, 0x02}, /* ?default */
260 {0x13, 0x01}, /* Validate Settings */
262 static const __u8 initPas202[] = {
263 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
266 0x28, 0x1e, 0x28, 0x89, 0x30,
267 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
269 static const __u8 pas202_sensor_init[][8] = {
270 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
271 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
272 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
273 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
274 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
275 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
276 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
277 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
278 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
279 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
280 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
281 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
283 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
284 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
285 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
286 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
287 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
288 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
289 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
290 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
293 static const __u8 initTas5110[] = {
294 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
296 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
297 0x16, 0x12, 0x60, 0x86, 0x2b,
298 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
300 static const __u8 tas5110_sensor_init[][8] = {
301 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
302 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
303 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
306 static const __u8 initTas5130[] = {
307 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
309 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
310 0x28, 0x1e, 0x60, COMP, MCK_INIT,
311 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
313 static const __u8 tas5130_sensor_init[][8] = {
314 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
315 * shutter 0x47 short exposure? */
316 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
317 /* shutter 0x01 long exposure */
318 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
321 static void reg_r(struct usb_device *dev,
322 __u16 value, __u8 *buffer)
325 usb_rcvctrlpipe(dev, 0),
327 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
334 static void reg_w(struct usb_device *dev,
340 usb_sndctrlpipe(dev, 0),
342 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
345 (__u8 *) buffer, len,
349 static int i2c_w(struct usb_device *dev, const __u8 *buffer)
355 reg_w(dev, 0x08, buffer, 8);
358 reg_r(dev, 0x08, &ByteReceive);
359 if (ByteReceive == 4)
365 static void i2c_w_vector(struct usb_device *dev,
366 const __u8 buffer[][8], int len)
369 reg_w(dev, 0x08, *buffer, 8);
377 static void setbrightness(struct gspca_dev *gspca_dev)
379 struct sd *sd = (struct sd *) gspca_dev;
382 switch (sd->sensor) {
383 case SENSOR_OV6650: {
385 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
387 i2cOV6650[3] = sd->brightness;
388 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
392 case SENSOR_OV7630: {
394 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
396 /* change reg 0x06 */
397 i2cOV[3] = sd->brightness;
398 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
402 case SENSOR_PAS106: {
404 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
406 i2c1[3] = sd->brightness >> 3;
408 if (i2c_w(gspca_dev->dev, i2c1) < 0)
412 if (i2c_w(gspca_dev->dev, i2c1) < 0)
416 case SENSOR_PAS202: {
417 /* __u8 i2cpexpo1[] =
418 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
420 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
422 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
423 static __u8 i2cpdoit[] =
424 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
426 /* change reg 0x10 */
427 i2cpexpo[4] = 0xff - sd->brightness;
428 /* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
430 /* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
432 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
434 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
436 i2cp202[3] = sd->brightness >> 3;
437 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
439 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
443 case SENSOR_TAS5130CXX:
444 case SENSOR_TAS5110: {
446 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
448 value = 0xff - sd->brightness;
450 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
451 if (i2c_w(gspca_dev->dev, i2c) < 0)
458 PDEBUG(D_ERR, "i2c error brightness");
460 static void setcontrast(struct gspca_dev *gspca_dev)
462 struct sd *sd = (struct sd *) gspca_dev;
466 gain = sd->contrast >> 4;
467 /* red and blue gain */
468 rgb_value = gain << 4 | gain;
469 reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
472 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
475 /* this function is called at probe time */
476 static int sd_config(struct gspca_dev *gspca_dev,
477 const struct usb_device_id *id)
479 struct sd *sd = (struct sd *) gspca_dev;
485 /* vendor = id->idVendor; */
486 product = id->idProduct;
487 /* switch (vendor) { */
488 /* case 0x0c45: * Sonix */
490 case 0x6001: /* SN9C102 */
491 case 0x6005: /* SN9C101 */
492 case 0x6007: /* SN9C101 */
493 sd->sensor = SENSOR_TAS5110;
496 case 0x6009: /* SN9C101 */
497 case 0x600d: /* SN9C101 */
498 case 0x6029: /* SN9C101 */
499 sd->sensor = SENSOR_PAS106;
502 case 0x6011: /* SN9C101 - SN9C101G */
503 sd->sensor = SENSOR_OV6650;
506 case 0x6019: /* SN9C101 */
507 case 0x602c: /* SN9C102 */
508 case 0x602e: /* SN9C102 */
509 sd->sensor = SENSOR_OV7630;
511 case 0x60b0: /* SN9C103 */
512 sd->sensor = SENSOR_OV7630_3;
514 case 0x6024: /* SN9C102 */
515 case 0x6025: /* SN9C102 */
516 sd->sensor = SENSOR_TAS5130CXX;
518 case 0x6028: /* SN9C102 */
519 sd->sensor = SENSOR_PAS202;
521 case 0x602d: /* SN9C102 */
522 sd->sensor = SENSOR_HV7131R;
524 case 0x60af: /* SN9C103 */
525 sd->sensor = SENSOR_PAS202;
531 cam = &gspca_dev->cam;
532 cam->dev_name = (char *) id->driver_info;
535 cam->cam_mode = vga_mode;
536 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
538 cam->cam_mode = sif_mode;
539 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
541 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
542 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
543 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
544 reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
548 /* this function is called at open time */
549 static int sd_open(struct gspca_dev *gspca_dev)
553 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
554 if (ByteReceive != 0x10)
559 static void pas106_i2cinit(struct usb_device *dev)
563 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
565 i = ARRAY_SIZE(pas106_data);
566 data = pas106_data[0];
568 memcpy(&i2c1[2], data, 2);
569 /* copy 2 bytes from the template */
570 if (i2c_w(dev, i2c1) < 0)
571 PDEBUG(D_ERR, "i2c error pas106");
576 /* -- start the camera -- */
577 static void sd_start(struct gspca_dev *gspca_dev)
579 struct sd *sd = (struct sd *) gspca_dev;
580 struct usb_device *dev = gspca_dev->dev;
586 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
587 switch (sd->sensor) {
589 sn9c10x = initHv7131;
591 reg17_19[1] = (mode << 4) | 0x8a;
595 sn9c10x = initOv6650;
597 reg17_19[1] = (mode << 4) | 0x8b;
601 sn9c10x = initOv7630;
603 reg17_19[1] = (mode << 4) | COMP2;
604 reg17_19[2] = MCK_INIT1;
606 case SENSOR_OV7630_3:
607 sn9c10x = initOv7630_3;
609 reg17_19[1] = (mode << 4) | COMP2;
610 reg17_19[2] = MCK_INIT1;
613 sn9c10x = initPas106;
614 reg17_19[0] = 0x24; /* 0x28 */
615 reg17_19[1] = (mode << 4) | COMP1;
616 reg17_19[2] = MCK_INIT1;
619 sn9c10x = initPas202;
620 reg17_19[0] = mode ? 0x24 : 0x20;
621 reg17_19[1] = (mode << 4) | 0x89;
625 sn9c10x = initTas5110;
627 reg17_19[1] = (mode << 4) | 0x86;
628 reg17_19[2] = 0x2b; /* 0xf3; */
631 /* case SENSOR_TAS5130CXX: */
632 sn9c10x = initTas5130;
634 reg17_19[1] = (mode << 4) | COMP;
635 reg17_19[2] = mode ? 0x23 : 0x43;
638 switch (sd->sensor) {
644 case SENSOR_OV7630_3:
651 reg17 = sn9c10x[0x17 - 1];
656 /* reg 0x01 bit 2 video transfert on */
657 reg_w(dev, 0x01, ®01, 1);
658 /* reg 0x17 SensorClk enable inv Clk 0x60 */
659 reg_w(dev, 0x17, ®17, 1);
660 /*fixme: for ov7630 102
661 reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
662 /* Set the registers from the template */
663 reg_w(dev, 0x01, sn9c10x, l);
664 switch (sd->sensor) {
666 i2c_w_vector(dev, hv7131_sensor_init,
667 sizeof hv7131_sensor_init);
670 i2c_w_vector(dev, ov6650_sensor_init,
671 sizeof ov6650_sensor_init);
674 i2c_w_vector(dev, ov7630_sensor_init_com,
675 sizeof ov7630_sensor_init_com);
677 i2c_w_vector(dev, ov7630_sensor_init,
678 sizeof ov7630_sensor_init);
680 case SENSOR_OV7630_3:
681 i2c_w_vector(dev, ov7630_sensor_init_com,
682 sizeof ov7630_sensor_init_com);
684 i2c_w_vector(dev, ov7630_sensor_init_3,
685 sizeof ov7630_sensor_init_3);
691 i2c_w_vector(dev, pas202_sensor_init,
692 sizeof pas202_sensor_init);
695 i2c_w_vector(dev, tas5110_sensor_init,
696 sizeof tas5110_sensor_init);
699 /* case SENSOR_TAS5130CXX: */
700 i2c_w_vector(dev, tas5130_sensor_init,
701 sizeof tas5130_sensor_init);
704 /* H_size V_size 0x28, 0x1e maybe 640x480 */
705 reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
706 /* compression register */
707 reg_w(dev, 0x18, ®17_19[1], 1);
708 /* H_start */ /*fixme: not ov7630*/
709 reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
710 /* V_START */ /*fixme: not ov7630*/
711 reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
712 /* reset 0x17 SensorClk enable inv Clk 0x60 */
713 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
714 reg_w(dev, 0x17, ®17_19[0], 1);
715 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
716 reg_w(dev, 0x19, ®17_19[2], 1);
717 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
718 reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
719 /* Enable video transfert */
720 reg_w(dev, 0x01, &sn9c10x[0], 1);
722 reg_w(dev, 0x18, ®17_19[1], 2);
725 setcontrast(gspca_dev);
726 setbrightness(gspca_dev);
729 static void sd_stopN(struct gspca_dev *gspca_dev)
733 ByteSend = 0x09; /* 0X00 */
734 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
737 static void sd_stop0(struct gspca_dev *gspca_dev)
741 static void sd_close(struct gspca_dev *gspca_dev)
745 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
746 struct gspca_frame *frame, /* target */
747 unsigned char *data, /* isoc packet */
748 int len) /* iso packet length */
752 if (len > 6 && len < 24) {
753 for (p = 0; p < len - 6; p++) {
754 if (data[0 + p] == 0xff
755 && data[1 + p] == 0xff
756 && data[2 + p] == 0x00
757 && data[3 + p] == 0xc4
758 && data[4 + p] == 0xc4
759 && data[5 + p] == 0x96) { /* start of frame */
760 frame = gspca_frame_add(gspca_dev,
766 gspca_frame_add(gspca_dev, FIRST_PACKET,
772 gspca_frame_add(gspca_dev, INTER_PACKET,
776 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
778 struct sd *sd = (struct sd *) gspca_dev;
780 sd->brightness = val;
781 if (gspca_dev->streaming)
782 setbrightness(gspca_dev);
786 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
788 struct sd *sd = (struct sd *) gspca_dev;
790 *val = sd->brightness;
794 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
796 struct sd *sd = (struct sd *) gspca_dev;
799 if (gspca_dev->streaming)
800 setcontrast(gspca_dev);
804 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
806 struct sd *sd = (struct sd *) gspca_dev;
812 /* sub-driver description */
813 static struct sd_desc sd_desc = {
816 .nctrls = ARRAY_SIZE(sd_ctrls),
823 .pkt_scan = sd_pkt_scan,
826 /* -- module initialisation -- */
827 #define DVNM(name) .driver_info = (kernel_ulong_t) name
828 static __devinitdata struct usb_device_id device_table[] = {
829 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
830 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
831 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
832 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
833 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
834 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia-OV6650-SN9C101G")},
835 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
836 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
837 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
838 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
839 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
840 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
841 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
842 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
843 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
844 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
847 MODULE_DEVICE_TABLE(usb, device_table);
849 /* -- device connect -- */
850 static int sd_probe(struct usb_interface *intf,
851 const struct usb_device_id *id)
853 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
857 static struct usb_driver sd_driver = {
859 .id_table = device_table,
861 .disconnect = gspca_disconnect,
864 /* -- module insert / remove -- */
865 static int __init sd_mod_init(void)
867 if (usb_register(&sd_driver) < 0)
869 PDEBUG(D_PROBE, "v%s registered", version);
872 static void __exit sd_mod_exit(void)
874 usb_deregister(&sd_driver);
875 PDEBUG(D_PROBE, "deregistered");
878 module_init(sd_mod_init);
879 module_exit(sd_mod_exit);