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, 3)
28 static const char version[] = "2.1.3";
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,
341 #ifdef CONFIG_VIDEO_ADV_DEBUG
342 if (len > sizeof tmpbuf) {
343 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
347 memcpy(tmpbuf, buffer, len);
349 usb_sndctrlpipe(dev, 0),
351 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
358 static int i2c_w(struct usb_device *dev, const __u8 *buffer)
364 reg_w(dev, 0x08, buffer, 8);
367 reg_r(dev, 0x08, &ByteReceive);
368 if (ByteReceive == 4)
374 static void i2c_w_vector(struct usb_device *dev,
375 const __u8 buffer[][8], int len)
378 reg_w(dev, 0x08, *buffer, 8);
386 static void setbrightness(struct gspca_dev *gspca_dev)
388 struct sd *sd = (struct sd *) gspca_dev;
391 switch (sd->sensor) {
392 case SENSOR_OV6650: {
394 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
396 i2cOV6650[3] = sd->brightness;
397 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
401 case SENSOR_OV7630: {
403 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
405 /* change reg 0x06 */
406 i2cOV[3] = sd->brightness;
407 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
411 case SENSOR_PAS106: {
413 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
415 i2c1[3] = sd->brightness >> 3;
417 if (i2c_w(gspca_dev->dev, i2c1) < 0)
421 if (i2c_w(gspca_dev->dev, i2c1) < 0)
425 case SENSOR_PAS202: {
426 /* __u8 i2cpexpo1[] =
427 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
429 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
431 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
432 static __u8 i2cpdoit[] =
433 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
435 /* change reg 0x10 */
436 i2cpexpo[4] = 0xff - sd->brightness;
437 /* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
439 /* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
441 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
443 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
445 i2cp202[3] = sd->brightness >> 3;
446 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
448 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
452 case SENSOR_TAS5130CXX:
453 case SENSOR_TAS5110: {
455 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
457 value = 0xff - sd->brightness;
459 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
460 if (i2c_w(gspca_dev->dev, i2c) < 0)
467 PDEBUG(D_ERR, "i2c error brightness");
469 static void setcontrast(struct gspca_dev *gspca_dev)
471 struct sd *sd = (struct sd *) gspca_dev;
475 gain = sd->contrast >> 4;
476 /* red and blue gain */
477 rgb_value = gain << 4 | gain;
478 reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
481 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
484 /* this function is called at probe time */
485 static int sd_config(struct gspca_dev *gspca_dev,
486 const struct usb_device_id *id)
488 struct sd *sd = (struct sd *) gspca_dev;
494 /* vendor = id->idVendor; */
495 product = id->idProduct;
496 /* switch (vendor) { */
497 /* case 0x0c45: * Sonix */
499 case 0x6001: /* SN9C102 */
500 case 0x6005: /* SN9C101 */
501 case 0x6007: /* SN9C101 */
502 sd->sensor = SENSOR_TAS5110;
505 case 0x6009: /* SN9C101 */
506 case 0x600d: /* SN9C101 */
507 case 0x6029: /* SN9C101 */
508 sd->sensor = SENSOR_PAS106;
511 case 0x6011: /* SN9C101 - SN9C101G */
512 sd->sensor = SENSOR_OV6650;
515 case 0x6019: /* SN9C101 */
516 case 0x602c: /* SN9C102 */
517 case 0x602e: /* SN9C102 */
518 sd->sensor = SENSOR_OV7630;
520 case 0x60b0: /* SN9C103 */
521 sd->sensor = SENSOR_OV7630_3;
523 case 0x6024: /* SN9C102 */
524 case 0x6025: /* SN9C102 */
525 sd->sensor = SENSOR_TAS5130CXX;
527 case 0x6028: /* SN9C102 */
528 sd->sensor = SENSOR_PAS202;
530 case 0x602d: /* SN9C102 */
531 sd->sensor = SENSOR_HV7131R;
533 case 0x60af: /* SN9C103 */
534 sd->sensor = SENSOR_PAS202;
540 cam = &gspca_dev->cam;
541 cam->dev_name = (char *) id->driver_info;
544 cam->cam_mode = vga_mode;
545 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
547 cam->cam_mode = sif_mode;
548 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
550 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
551 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
552 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
553 reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
557 /* this function is called at open time */
558 static int sd_open(struct gspca_dev *gspca_dev)
562 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
563 if (ByteReceive != 0x10)
568 static void pas106_i2cinit(struct usb_device *dev)
572 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
574 i = ARRAY_SIZE(pas106_data);
575 data = pas106_data[0];
577 memcpy(&i2c1[2], data, 2);
578 /* copy 2 bytes from the template */
579 if (i2c_w(dev, i2c1) < 0)
580 PDEBUG(D_ERR, "i2c error pas106");
585 /* -- start the camera -- */
586 static void sd_start(struct gspca_dev *gspca_dev)
588 struct sd *sd = (struct sd *) gspca_dev;
589 struct usb_device *dev = gspca_dev->dev;
595 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
596 switch (sd->sensor) {
598 sn9c10x = initHv7131;
600 reg17_19[1] = (mode << 4) | 0x8a;
604 sn9c10x = initOv6650;
606 reg17_19[1] = (mode << 4) | 0x8b;
610 sn9c10x = initOv7630;
612 reg17_19[1] = (mode << 4) | COMP2;
613 reg17_19[2] = MCK_INIT1;
615 case SENSOR_OV7630_3:
616 sn9c10x = initOv7630_3;
618 reg17_19[1] = (mode << 4) | COMP2;
619 reg17_19[2] = MCK_INIT1;
622 sn9c10x = initPas106;
623 reg17_19[0] = 0x24; /* 0x28 */
624 reg17_19[1] = (mode << 4) | COMP1;
625 reg17_19[2] = MCK_INIT1;
628 sn9c10x = initPas202;
629 reg17_19[0] = mode ? 0x24 : 0x20;
630 reg17_19[1] = (mode << 4) | 0x89;
634 sn9c10x = initTas5110;
636 reg17_19[1] = (mode << 4) | 0x86;
637 reg17_19[2] = 0x2b; /* 0xf3; */
640 /* case SENSOR_TAS5130CXX: */
641 sn9c10x = initTas5130;
643 reg17_19[1] = (mode << 4) | COMP;
644 reg17_19[2] = mode ? 0x23 : 0x43;
647 switch (sd->sensor) {
653 case SENSOR_OV7630_3:
660 reg17 = sn9c10x[0x17 - 1];
665 /* reg 0x01 bit 2 video transfert on */
666 reg_w(dev, 0x01, ®01, 1);
667 /* reg 0x17 SensorClk enable inv Clk 0x60 */
668 reg_w(dev, 0x17, ®17, 1);
669 /*fixme: for ov7630 102
670 reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
671 /* Set the registers from the template */
672 reg_w(dev, 0x01, sn9c10x, l);
673 switch (sd->sensor) {
675 i2c_w_vector(dev, hv7131_sensor_init,
676 sizeof hv7131_sensor_init);
679 i2c_w_vector(dev, ov6650_sensor_init,
680 sizeof ov6650_sensor_init);
683 i2c_w_vector(dev, ov7630_sensor_init_com,
684 sizeof ov7630_sensor_init_com);
686 i2c_w_vector(dev, ov7630_sensor_init,
687 sizeof ov7630_sensor_init);
689 case SENSOR_OV7630_3:
690 i2c_w_vector(dev, ov7630_sensor_init_com,
691 sizeof ov7630_sensor_init_com);
693 i2c_w_vector(dev, ov7630_sensor_init_3,
694 sizeof ov7630_sensor_init_3);
700 i2c_w_vector(dev, pas202_sensor_init,
701 sizeof pas202_sensor_init);
704 i2c_w_vector(dev, tas5110_sensor_init,
705 sizeof tas5110_sensor_init);
708 /* case SENSOR_TAS5130CXX: */
709 i2c_w_vector(dev, tas5130_sensor_init,
710 sizeof tas5130_sensor_init);
713 /* H_size V_size 0x28, 0x1e maybe 640x480 */
714 reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
715 /* compression register */
716 reg_w(dev, 0x18, ®17_19[1], 1);
717 /* H_start */ /*fixme: not ov7630*/
718 reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
719 /* V_START */ /*fixme: not ov7630*/
720 reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
721 /* reset 0x17 SensorClk enable inv Clk 0x60 */
722 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
723 reg_w(dev, 0x17, ®17_19[0], 1);
724 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
725 reg_w(dev, 0x19, ®17_19[2], 1);
726 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
727 reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
728 /* Enable video transfert */
729 reg_w(dev, 0x01, &sn9c10x[0], 1);
731 reg_w(dev, 0x18, ®17_19[1], 2);
734 setcontrast(gspca_dev);
735 setbrightness(gspca_dev);
738 static void sd_stopN(struct gspca_dev *gspca_dev)
742 ByteSend = 0x09; /* 0X00 */
743 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
746 static void sd_stop0(struct gspca_dev *gspca_dev)
750 static void sd_close(struct gspca_dev *gspca_dev)
754 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
755 struct gspca_frame *frame, /* target */
756 unsigned char *data, /* isoc packet */
757 int len) /* iso packet length */
761 if (len > 6 && len < 24) {
762 for (i = 0; i < len - 6; i++) {
763 if (data[0 + i] == 0xff
764 && data[1 + i] == 0xff
765 && data[2 + i] == 0x00
766 && data[3 + i] == 0xc4
767 && data[4 + i] == 0xc4
768 && data[5 + i] == 0x96) { /* start of frame */
769 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
773 gspca_frame_add(gspca_dev, FIRST_PACKET,
779 gspca_frame_add(gspca_dev, INTER_PACKET,
783 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
785 struct sd *sd = (struct sd *) gspca_dev;
787 sd->brightness = val;
788 if (gspca_dev->streaming)
789 setbrightness(gspca_dev);
793 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
795 struct sd *sd = (struct sd *) gspca_dev;
797 *val = sd->brightness;
801 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
803 struct sd *sd = (struct sd *) gspca_dev;
806 if (gspca_dev->streaming)
807 setcontrast(gspca_dev);
811 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
813 struct sd *sd = (struct sd *) gspca_dev;
819 /* sub-driver description */
820 static struct sd_desc sd_desc = {
823 .nctrls = ARRAY_SIZE(sd_ctrls),
830 .pkt_scan = sd_pkt_scan,
833 /* -- module initialisation -- */
834 #define DVNM(name) .driver_info = (kernel_ulong_t) name
835 static __devinitdata struct usb_device_id device_table[] = {
836 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
837 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
838 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
839 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
840 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
841 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
842 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
843 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
844 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
845 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
846 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
847 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
848 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
849 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
850 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
851 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
854 MODULE_DEVICE_TABLE(usb, device_table);
856 /* -- device connect -- */
857 static int sd_probe(struct usb_interface *intf,
858 const struct usb_device_id *id)
860 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
864 static struct usb_driver sd_driver = {
866 .id_table = device_table,
868 .disconnect = gspca_disconnect,
871 /* -- module insert / remove -- */
872 static int __init sd_mod_init(void)
874 if (usb_register(&sd_driver) < 0)
876 PDEBUG(D_PROBE, "v%s registered", version);
879 static void __exit sd_mod_exit(void)
881 usb_deregister(&sd_driver);
882 PDEBUG(D_PROBE, "deregistered");
885 module_init(sd_mod_init);
886 module_exit(sd_mod_exit);