2 * sonix sn9c102 (bayer) library
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, 5)
28 static const char version[] = "2.1.5";
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 unsigned char fr_h_sz; /* size of frame header */
42 char sensor; /* Type of image sensor chip */
43 #define SENSOR_HV7131R 0
44 #define SENSOR_OV6650 1
45 #define SENSOR_OV7630 2
46 #define SENSOR_OV7630_3 3
47 #define SENSOR_PAS106 4
48 #define SENSOR_PAS202 5
49 #define SENSOR_TAS5110 6
50 #define SENSOR_TAS5130CXX 7
54 #define COMP 0xc7 /* 0x87 //0x07 */
55 #define COMP1 0xc9 /* 0x89 //0x09 */
58 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
62 /* V4L2 controls supported by the driver */
63 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68 static struct ctrl sd_ctrls[] = {
69 #define SD_BRIGHTNESS 0
72 .id = V4L2_CID_BRIGHTNESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
80 .set = sd_setbrightness,
81 .get = sd_getbrightness,
86 .id = V4L2_CID_CONTRAST,
87 .type = V4L2_CTRL_TYPE_INTEGER,
94 .set = sd_setcontrast,
95 .get = sd_getcontrast,
99 static struct v4l2_pix_format vga_mode[] = {
100 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
102 .sizeimage = 160 * 120,
103 .colorspace = V4L2_COLORSPACE_SRGB,
105 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
107 .sizeimage = 320 * 240,
108 .colorspace = V4L2_COLORSPACE_SRGB,
110 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
112 .sizeimage = 640 * 480,
113 .colorspace = V4L2_COLORSPACE_SRGB,
116 static struct v4l2_pix_format sif_mode[] = {
117 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
119 .sizeimage = 176 * 144,
120 .colorspace = V4L2_COLORSPACE_SRGB,
122 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
124 .sizeimage = 352 * 288,
125 .colorspace = V4L2_COLORSPACE_SRGB,
129 static const __u8 probe_ov7630[] = {0x08, 0x44};
131 static const __u8 initHv7131[] = {
132 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
135 0x28, 0x1e, 0x60, 0x8a, 0x20,
136 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
138 static const __u8 hv7131_sensor_init[][8] = {
139 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
140 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
141 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
142 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
143 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
145 static const __u8 initOv6650[] = {
146 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
147 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
149 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
151 static const __u8 ov6650_sensor_init[][8] =
153 /* Bright, contrast, etc are set througth SCBB interface.
154 * AVCAP on win2 do not send any data on this controls. */
155 /* Anyway, some registers appears to alter bright and constrat */
156 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
157 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
158 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
159 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
160 * THIS SET GREEN SCREEN
161 * (pixels could be innverted in decode kind of "brg",
162 * but blue wont be there. Avoid this data ... */
163 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
164 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
165 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
166 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
167 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
168 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
169 {0xa0, 0x60, 0x10, 0x5d, 0x99, 0x04, 0x94, 0x16},
170 {0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
171 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
172 {0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
173 {0xa0, 0x60, 0x11, 0xc0, 0x99, 0x04, 0x94, 0x16},
174 {0xa0, 0x60, 0x00, 0x16, 0x99, 0x04, 0x94, 0x15}, /* bright / Lumino */
175 {0xa0, 0x60, 0x2b, 0xab, 0x99, 0x04, 0x94, 0x15},
176 /* ?flicker o brillo */
177 {0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
178 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
179 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
180 {0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
181 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
182 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
183 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
184 /* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
185 {0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
186 /* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
187 /* {0xa0, 0x60, 0x11, 0xc1, 0x99, 0x04, 0x94, 0x16}, */
188 {0xa0, 0x60, 0x00, 0x17, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
189 {0xa0, 0x60, 0x00, 0x18, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
191 static const __u8 initOv7630[] = {
192 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
193 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
194 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
195 0x28, 0x1e, /* H & V sizes r15 .. r16 */
196 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
197 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
199 static const __u8 initOv7630_3[] = {
200 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
201 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
202 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
203 0x28, 0x1e, /* H & V sizes r15 .. r16 */
204 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
205 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
207 static const __u8 ov7630_sensor_init_com[][8] = {
208 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
209 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
210 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
211 {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
212 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
213 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
214 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
215 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
216 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
217 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
218 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
219 /* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
220 {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
221 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
222 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
223 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
224 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
225 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
226 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
228 static const __u8 ov7630_sensor_init[][8] = {
229 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
230 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
231 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
232 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
233 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
235 static const __u8 ov7630_sensor_init_3[][8] = {
236 {0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
237 {0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
238 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
239 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
240 /* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
241 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
242 /* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
243 {0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
246 static const __u8 initPas106[] = {
247 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
250 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
251 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
253 /* compression 0x86 mckinit1 0x2b */
254 static const __u8 pas106_data[][2] = {
255 {0x02, 0x04}, /* Pixel Clock Divider 6 */
256 {0x03, 0x13}, /* Frame Time MSB */
257 /* {0x03, 0x12}, * Frame Time MSB */
258 {0x04, 0x06}, /* Frame Time LSB */
259 /* {0x04, 0x05}, * Frame Time LSB */
260 {0x05, 0x65}, /* Shutter Time Line Offset */
261 /* {0x05, 0x6d}, * Shutter Time Line Offset */
262 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
263 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
264 {0x07, 0xc1}, /* Black Level Subtract Sign */
265 /* {0x07, 0x00}, * Black Level Subtract Sign */
266 {0x08, 0x06}, /* Black Level Subtract Level */
267 {0x08, 0x06}, /* Black Level Subtract Level */
268 /* {0x08, 0x01}, * Black Level Subtract Level */
269 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
270 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
271 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
272 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
273 {0x0d, 0x00}, /* Color GainH Pixel */
274 {0x0e, 0x0e}, /* Global Gain */
275 {0x0f, 0x00}, /* Contrast */
276 {0x10, 0x06}, /* H&V synchro polarity */
277 {0x11, 0x06}, /* ?default */
278 {0x12, 0x06}, /* DAC scale */
279 {0x14, 0x02}, /* ?default */
280 {0x13, 0x01}, /* Validate Settings */
282 static const __u8 initPas202[] = {
283 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
286 0x28, 0x1e, 0x28, 0x89, 0x30,
287 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
289 static const __u8 pas202_sensor_init[][8] = {
290 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
291 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
292 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
293 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
294 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
295 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
296 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
297 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
298 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
299 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
300 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
301 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
303 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
304 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
305 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
306 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
307 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
308 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
309 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
310 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
313 static const __u8 initTas5110[] = {
314 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
316 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
317 0x16, 0x12, 0x60, 0x86, 0x2b,
318 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
320 static const __u8 tas5110_sensor_init[][8] = {
321 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
322 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
323 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
326 static const __u8 initTas5130[] = {
327 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
329 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
330 0x28, 0x1e, 0x60, COMP, MCK_INIT,
331 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
333 static const __u8 tas5130_sensor_init[][8] = {
334 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
335 * shutter 0x47 short exposure? */
336 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
337 /* shutter 0x01 long exposure */
338 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
341 static void reg_r(struct usb_device *dev,
342 __u16 value, __u8 *buffer)
345 usb_rcvctrlpipe(dev, 0),
347 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
354 static void reg_w(struct usb_device *dev,
361 #ifdef CONFIG_VIDEO_ADV_DEBUG
362 if (len > sizeof tmpbuf) {
363 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
367 memcpy(tmpbuf, buffer, len);
369 usb_sndctrlpipe(dev, 0),
371 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
378 static int i2c_w(struct usb_device *dev, const __u8 *buffer)
384 reg_w(dev, 0x08, buffer, 8);
387 reg_r(dev, 0x08, &ByteReceive);
388 if (ByteReceive == 4)
394 static void i2c_w_vector(struct usb_device *dev,
395 const __u8 buffer[][8], int len)
398 reg_w(dev, 0x08, *buffer, 8);
406 static void setbrightness(struct gspca_dev *gspca_dev)
408 struct sd *sd = (struct sd *) gspca_dev;
411 switch (sd->sensor) {
412 case SENSOR_OV6650: {
414 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
416 i2cOV6650[3] = sd->brightness;
417 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
421 case SENSOR_OV7630: {
423 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
425 /* change reg 0x06 */
426 i2cOV[3] = sd->brightness;
427 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
431 case SENSOR_PAS106: {
433 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
435 i2c1[3] = sd->brightness >> 3;
437 if (i2c_w(gspca_dev->dev, i2c1) < 0)
441 if (i2c_w(gspca_dev->dev, i2c1) < 0)
445 case SENSOR_PAS202: {
446 /* __u8 i2cpexpo1[] =
447 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
449 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
451 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
452 static __u8 i2cpdoit[] =
453 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
455 /* change reg 0x10 */
456 i2cpexpo[4] = 0xff - sd->brightness;
457 /* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
459 /* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
461 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
463 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
465 i2cp202[3] = sd->brightness >> 3;
466 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
468 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
472 case SENSOR_TAS5130CXX:
473 case SENSOR_TAS5110: {
475 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
477 value = 0xff - sd->brightness;
479 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
480 if (i2c_w(gspca_dev->dev, i2c) < 0)
487 PDEBUG(D_ERR, "i2c error brightness");
489 static void setcontrast(struct gspca_dev *gspca_dev)
491 struct sd *sd = (struct sd *) gspca_dev;
495 gain = sd->contrast >> 4;
496 /* red and blue gain */
497 rgb_value = gain << 4 | gain;
498 reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
501 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
504 /* this function is called at probe time */
505 static int sd_config(struct gspca_dev *gspca_dev,
506 const struct usb_device_id *id)
508 struct sd *sd = (struct sd *) gspca_dev;
514 sd->fr_h_sz = 12; /* default size of the frame header */
515 /* vendor = id->idVendor; */
516 product = id->idProduct;
517 /* switch (vendor) { */
518 /* case 0x0c45: * Sonix */
520 case 0x6001: /* SN9C102 */
521 case 0x6005: /* SN9C101 */
522 case 0x6007: /* SN9C101 */
523 sd->sensor = SENSOR_TAS5110;
526 case 0x6009: /* SN9C101 */
527 case 0x600d: /* SN9C101 */
528 case 0x6029: /* SN9C101 */
529 sd->sensor = SENSOR_PAS106;
532 case 0x6011: /* SN9C101 - SN9C101G */
533 sd->sensor = SENSOR_OV6650;
536 case 0x6019: /* SN9C101 */
537 case 0x602c: /* SN9C102 */
538 case 0x602e: /* SN9C102 */
539 sd->sensor = SENSOR_OV7630;
541 case 0x60b0: /* SN9C103 */
542 sd->sensor = SENSOR_OV7630_3;
543 sd->fr_h_sz = 18; /* size of frame header */
545 case 0x6024: /* SN9C102 */
546 case 0x6025: /* SN9C102 */
547 sd->sensor = SENSOR_TAS5130CXX;
549 case 0x6028: /* SN9C102 */
550 sd->sensor = SENSOR_PAS202;
552 case 0x602d: /* SN9C102 */
553 sd->sensor = SENSOR_HV7131R;
555 case 0x60af: /* SN9C103 */
556 sd->sensor = SENSOR_PAS202;
557 sd->fr_h_sz = 18; /* size of frame header (?) */
563 cam = &gspca_dev->cam;
564 cam->dev_name = (char *) id->driver_info;
567 cam->cam_mode = vga_mode;
568 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
570 cam->cam_mode = sif_mode;
571 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
573 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
574 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
575 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
576 reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
580 /* this function is called at open time */
581 static int sd_open(struct gspca_dev *gspca_dev)
585 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
586 if (ByteReceive != 0x10)
591 static void pas106_i2cinit(struct usb_device *dev)
595 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
597 i = ARRAY_SIZE(pas106_data);
598 data = pas106_data[0];
600 memcpy(&i2c1[2], data, 2);
601 /* copy 2 bytes from the template */
602 if (i2c_w(dev, i2c1) < 0)
603 PDEBUG(D_ERR, "i2c error pas106");
608 /* -- start the camera -- */
609 static void sd_start(struct gspca_dev *gspca_dev)
611 struct sd *sd = (struct sd *) gspca_dev;
612 struct usb_device *dev = gspca_dev->dev;
618 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
619 switch (sd->sensor) {
621 sn9c10x = initHv7131;
623 reg17_19[1] = (mode << 4) | 0x8a;
627 sn9c10x = initOv6650;
629 reg17_19[1] = (mode << 4) | 0x8b;
633 sn9c10x = initOv7630;
635 reg17_19[1] = (mode << 4) | COMP2;
636 reg17_19[2] = MCK_INIT1;
638 case SENSOR_OV7630_3:
639 sn9c10x = initOv7630_3;
641 reg17_19[1] = (mode << 4) | COMP2;
642 reg17_19[2] = MCK_INIT1;
645 sn9c10x = initPas106;
646 reg17_19[0] = 0x24; /* 0x28 */
647 reg17_19[1] = (mode << 4) | COMP1;
648 reg17_19[2] = MCK_INIT1;
651 sn9c10x = initPas202;
652 reg17_19[0] = mode ? 0x24 : 0x20;
653 reg17_19[1] = (mode << 4) | 0x89;
657 sn9c10x = initTas5110;
659 reg17_19[1] = (mode << 4) | 0x86;
660 reg17_19[2] = 0x2b; /* 0xf3; */
663 /* case SENSOR_TAS5130CXX: */
664 sn9c10x = initTas5130;
666 reg17_19[1] = (mode << 4) | COMP;
667 reg17_19[2] = mode ? 0x23 : 0x43;
670 switch (sd->sensor) {
676 case SENSOR_OV7630_3:
683 reg17 = sn9c10x[0x17 - 1];
688 /* reg 0x01 bit 2 video transfert on */
689 reg_w(dev, 0x01, ®01, 1);
690 /* reg 0x17 SensorClk enable inv Clk 0x60 */
691 reg_w(dev, 0x17, ®17, 1);
692 /*fixme: for ov7630 102
693 reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
694 /* Set the registers from the template */
695 reg_w(dev, 0x01, sn9c10x, l);
696 switch (sd->sensor) {
698 i2c_w_vector(dev, hv7131_sensor_init,
699 sizeof hv7131_sensor_init);
702 i2c_w_vector(dev, ov6650_sensor_init,
703 sizeof ov6650_sensor_init);
706 i2c_w_vector(dev, ov7630_sensor_init_com,
707 sizeof ov7630_sensor_init_com);
709 i2c_w_vector(dev, ov7630_sensor_init,
710 sizeof ov7630_sensor_init);
712 case SENSOR_OV7630_3:
713 i2c_w_vector(dev, ov7630_sensor_init_com,
714 sizeof ov7630_sensor_init_com);
716 i2c_w_vector(dev, ov7630_sensor_init_3,
717 sizeof ov7630_sensor_init_3);
723 i2c_w_vector(dev, pas202_sensor_init,
724 sizeof pas202_sensor_init);
727 i2c_w_vector(dev, tas5110_sensor_init,
728 sizeof tas5110_sensor_init);
731 /* case SENSOR_TAS5130CXX: */
732 i2c_w_vector(dev, tas5130_sensor_init,
733 sizeof tas5130_sensor_init);
736 /* H_size V_size 0x28, 0x1e maybe 640x480 */
737 reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
738 /* compression register */
739 reg_w(dev, 0x18, ®17_19[1], 1);
740 /* H_start */ /*fixme: not ov7630*/
741 reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
742 /* V_START */ /*fixme: not ov7630*/
743 reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
744 /* reset 0x17 SensorClk enable inv Clk 0x60 */
745 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
746 reg_w(dev, 0x17, ®17_19[0], 1);
747 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
748 reg_w(dev, 0x19, ®17_19[2], 1);
749 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
750 reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
751 /* Enable video transfert */
752 reg_w(dev, 0x01, &sn9c10x[0], 1);
754 reg_w(dev, 0x18, ®17_19[1], 2);
757 setcontrast(gspca_dev);
758 setbrightness(gspca_dev);
761 static void sd_stopN(struct gspca_dev *gspca_dev)
765 ByteSend = 0x09; /* 0X00 */
766 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
769 static void sd_stop0(struct gspca_dev *gspca_dev)
773 static void sd_close(struct gspca_dev *gspca_dev)
777 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
778 struct gspca_frame *frame, /* target */
779 unsigned char *data, /* isoc packet */
780 int len) /* iso packet length */
785 if (len > 6 && len < 24) {
786 for (i = 0; i < len - 6; i++) {
787 if (data[0 + i] == 0xff
788 && data[1 + i] == 0xff
789 && data[2 + i] == 0x00
790 && data[3 + i] == 0xc4
791 && data[4 + i] == 0xc4
792 && data[5 + i] == 0x96) { /* start of frame */
793 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
795 sd = (struct sd *) gspca_dev;
796 data += i + sd->fr_h_sz;
797 len -= i + sd->fr_h_sz;
798 gspca_frame_add(gspca_dev, FIRST_PACKET,
804 gspca_frame_add(gspca_dev, INTER_PACKET,
808 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
810 struct sd *sd = (struct sd *) gspca_dev;
812 sd->brightness = val;
813 if (gspca_dev->streaming)
814 setbrightness(gspca_dev);
818 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
820 struct sd *sd = (struct sd *) gspca_dev;
822 *val = sd->brightness;
826 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
828 struct sd *sd = (struct sd *) gspca_dev;
831 if (gspca_dev->streaming)
832 setcontrast(gspca_dev);
836 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
838 struct sd *sd = (struct sd *) gspca_dev;
844 /* sub-driver description */
845 static struct sd_desc sd_desc = {
848 .nctrls = ARRAY_SIZE(sd_ctrls),
855 .pkt_scan = sd_pkt_scan,
858 /* -- module initialisation -- */
859 #define DVNM(name) .driver_info = (kernel_ulong_t) name
860 static __devinitdata struct usb_device_id device_table[] = {
861 #ifndef CONFIG_USB_SN9C102
862 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
863 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
864 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
865 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
866 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
867 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
868 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
869 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
870 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
871 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
872 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
873 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
874 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
875 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
876 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
877 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
881 MODULE_DEVICE_TABLE(usb, device_table);
883 /* -- device connect -- */
884 static int sd_probe(struct usb_interface *intf,
885 const struct usb_device_id *id)
887 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
891 static struct usb_driver sd_driver = {
893 .id_table = device_table,
895 .disconnect = gspca_disconnect,
898 /* -- module insert / remove -- */
899 static int __init sd_mod_init(void)
901 if (usb_register(&sd_driver) < 0)
903 PDEBUG(D_PROBE, "v%s registered", version);
906 static void __exit sd_mod_exit(void)
908 usb_deregister(&sd_driver);
909 PDEBUG(D_PROBE, "deregistered");
912 module_init(sd_mod_init);
913 module_exit(sd_mod_exit);