blob: 7850efa41096280135010abc2824e01077caf715 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
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
11 * any later version.
12 *
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.
17 *
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
21 */
22
23#define MODULE_NAME "sonixb"
24
25#include "gspca.h"
26
Hans de Goede0d2a7222008-07-03 08:15:22 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 3)
28static const char version[] = "2.1.3";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SN9C102 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 unsigned char brightness;
39 unsigned char contrast;
40
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
50};
51
52#define COMP2 0x8f
53#define COMP 0xc7 /* 0x87 //0x07 */
54#define COMP1 0xc9 /* 0x89 //0x09 */
55
56#define MCK_INIT 0x63
57#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
58
59#define SYS_CLK 0x04
60
61/* V4L2 controls supported by the driver */
62static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
66
67static struct ctrl sd_ctrls[] = {
68#define SD_BRIGHTNESS 0
69 {
70 {
71 .id = V4L2_CID_BRIGHTNESS,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Brightness",
74 .minimum = 0,
75 .maximum = 255,
76 .step = 1,
77 .default_value = 127,
78 },
79 .set = sd_setbrightness,
80 .get = sd_getbrightness,
81 },
82#define SD_CONTRAST 1
83 {
84 {
85 .id = V4L2_CID_CONTRAST,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Contrast",
88 .minimum = 0,
89 .maximum = 255,
90 .step = 1,
91 .default_value = 127,
92 },
93 .set = sd_setcontrast,
94 .get = sd_getcontrast,
95 },
96};
97
98/* fixme: should have V4L2_PIX_FMT_SN9C10X */
99static 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},
103};
104static struct cam_mode sif_mode[] = {
105 {V4L2_PIX_FMT_SN9C10X, 176, 144, 1},
106 {V4L2_PIX_FMT_SN9C10X, 352, 288, 0},
107};
108
109static const __u8 probe_ov7630[] = {0x08, 0x44};
110
111static const __u8 initHv7131[] = {
112 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
113 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
117};
118static 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},
124};
125static 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
130};
131static const __u8 ov6650_sensor_init[][8] =
132{
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 */
170};
171static 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 */
178};
179static 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 */
186};
187static 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},
207};
208static 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 */
214};
215static 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},
224};
225
226static const __u8 initPas106[] = {
227 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
228 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
230 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
231 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
232};
233/* compression 0x86 mckinit1 0x2b */
234static 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 */
261};
262static const __u8 initPas202[] = {
263 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
264 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
266 0x28, 0x1e, 0x28, 0x89, 0x30,
267 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
268};
269static 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},
282
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},
291};
292
293static const __u8 initTas5110[] = {
294 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
295 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
299};
300static 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},
304};
305
306static const __u8 initTas5130[] = {
307 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
308 0x00, 0x00,
309 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
310 0x28, 0x1e, 0x60, COMP, MCK_INIT,
311 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
312};
313static 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},
319};
320
321static void reg_r(struct usb_device *dev,
322 __u16 value, __u8 *buffer)
323{
324 usb_control_msg(dev,
325 usb_rcvctrlpipe(dev, 0),
326 0, /* request */
327 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
328 value,
329 0, /* index */
330 buffer, 1,
331 500);
332}
333
334static void reg_w(struct usb_device *dev,
335 __u16 value,
336 const __u8 *buffer,
337 __u16 len)
338{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300339 __u8 tmpbuf[32];
340
341#ifdef CONFIG_VIDEO_ADV_DEBUG
342 if (len > sizeof tmpbuf) {
343 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
344 return;
345 }
346#endif
347 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300348 usb_control_msg(dev,
349 usb_sndctrlpipe(dev, 0),
350 0x08, /* request */
351 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
352 value,
353 0, /* index */
Hans de Goede0d2a7222008-07-03 08:15:22 -0300354 tmpbuf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300355 500);
356}
357
358static int i2c_w(struct usb_device *dev, const __u8 *buffer)
359{
360 int retry = 60;
361 __u8 ByteReceive;
362
363 /* is i2c ready */
364 reg_w(dev, 0x08, buffer, 8);
365 while (retry--) {
366 msleep(10);
367 reg_r(dev, 0x08, &ByteReceive);
368 if (ByteReceive == 4)
369 return 0;
370 }
371 return -1;
372}
373
374static void i2c_w_vector(struct usb_device *dev,
375 const __u8 buffer[][8], int len)
376{
377 for (;;) {
378 reg_w(dev, 0x08, *buffer, 8);
379 len -= 8;
380 if (len <= 0)
381 break;
382 buffer++;
383 }
384}
385
386static void setbrightness(struct gspca_dev *gspca_dev)
387{
388 struct sd *sd = (struct sd *) gspca_dev;
389 __u8 value;
390
391 switch (sd->sensor) {
392 case SENSOR_OV6650: {
393 __u8 i2cOV6650[] =
394 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
395
396 i2cOV6650[3] = sd->brightness;
397 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
398 goto err;
399 break;
400 }
401 case SENSOR_OV7630: {
402 __u8 i2cOV[] =
403 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
404
405 /* change reg 0x06 */
406 i2cOV[3] = sd->brightness;
407 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
408 goto err;
409 break;
410 }
411 case SENSOR_PAS106: {
412 __u8 i2c1[] =
413 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
414
415 i2c1[3] = sd->brightness >> 3;
416 i2c1[2] = 0x0e;
417 if (i2c_w(gspca_dev->dev, i2c1) < 0)
418 goto err;
419 i2c1[3] = 0x01;
420 i2c1[2] = 0x13;
421 if (i2c_w(gspca_dev->dev, i2c1) < 0)
422 goto err;
423 break;
424 }
425 case SENSOR_PAS202: {
426 /* __u8 i2cpexpo1[] =
427 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
428 __u8 i2cpexpo[] =
429 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
430 __u8 i2cp202[] =
431 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
432 static __u8 i2cpdoit[] =
433 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
434
435 /* change reg 0x10 */
436 i2cpexpo[4] = 0xff - sd->brightness;
437/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
438 goto err; */
439/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
440 goto err; */
441 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
442 goto err;
443 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
444 goto err;
445 i2cp202[3] = sd->brightness >> 3;
446 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
447 goto err;
448 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
449 goto err;
450 break;
451 }
452 case SENSOR_TAS5130CXX:
453 case SENSOR_TAS5110: {
454 __u8 i2c[] =
455 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
456
457 value = 0xff - sd->brightness;
458 i2c[4] = value;
459 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
460 if (i2c_w(gspca_dev->dev, i2c) < 0)
461 goto err;
462 break;
463 }
464 }
465 return;
466err:
467 PDEBUG(D_ERR, "i2c error brightness");
468}
469static void setcontrast(struct gspca_dev *gspca_dev)
470{
471 struct sd *sd = (struct sd *) gspca_dev;
472 __u8 gain;
473 __u8 rgb_value;
474
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);
479 /* green gain */
480 rgb_value = gain;
481 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
482}
483
484/* this function is called at probe time */
485static int sd_config(struct gspca_dev *gspca_dev,
486 const struct usb_device_id *id)
487{
488 struct sd *sd = (struct sd *) gspca_dev;
489 struct cam *cam;
490/* __u16 vendor; */
491 __u16 product;
492 int sif = 0;
493
494/* vendor = id->idVendor; */
495 product = id->idProduct;
496/* switch (vendor) { */
497/* case 0x0c45: * Sonix */
498 switch (product) {
499 case 0x6001: /* SN9C102 */
500 case 0x6005: /* SN9C101 */
501 case 0x6007: /* SN9C101 */
502 sd->sensor = SENSOR_TAS5110;
503 sif = 1;
504 break;
505 case 0x6009: /* SN9C101 */
506 case 0x600d: /* SN9C101 */
507 case 0x6029: /* SN9C101 */
508 sd->sensor = SENSOR_PAS106;
509 sif = 1;
510 break;
511 case 0x6011: /* SN9C101 - SN9C101G */
512 sd->sensor = SENSOR_OV6650;
513 sif = 1;
514 break;
515 case 0x6019: /* SN9C101 */
516 case 0x602c: /* SN9C102 */
517 case 0x602e: /* SN9C102 */
518 sd->sensor = SENSOR_OV7630;
519 break;
520 case 0x60b0: /* SN9C103 */
521 sd->sensor = SENSOR_OV7630_3;
522 break;
523 case 0x6024: /* SN9C102 */
524 case 0x6025: /* SN9C102 */
525 sd->sensor = SENSOR_TAS5130CXX;
526 break;
527 case 0x6028: /* SN9C102 */
528 sd->sensor = SENSOR_PAS202;
529 break;
530 case 0x602d: /* SN9C102 */
531 sd->sensor = SENSOR_HV7131R;
532 break;
533 case 0x60af: /* SN9C103 */
534 sd->sensor = SENSOR_PAS202;
535 break;
536 }
537/* break; */
538/* } */
539
540 cam = &gspca_dev->cam;
541 cam->dev_name = (char *) id->driver_info;
542 cam->epaddr = 0x01;
543 if (!sif) {
544 cam->cam_mode = vga_mode;
545 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
546 } else {
547 cam->cam_mode = sif_mode;
548 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
549 }
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);
554 return 0;
555}
556
557/* this function is called at open time */
558static int sd_open(struct gspca_dev *gspca_dev)
559{
560 __u8 ByteReceive;
561
562 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
563 if (ByteReceive != 0x10)
564 return -ENODEV;
565 return 0;
566}
567
568static void pas106_i2cinit(struct usb_device *dev)
569{
570 int i;
571 const __u8 *data;
572 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
573
574 i = ARRAY_SIZE(pas106_data);
575 data = pas106_data[0];
576 while (--i >= 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");
581 data += 2;
582 }
583}
584
585/* -- start the camera -- */
586static void sd_start(struct gspca_dev *gspca_dev)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589 struct usb_device *dev = gspca_dev->dev;
590 int mode, l;
591 const __u8 *sn9c10x;
592 __u8 reg01, reg17;
593 __u8 reg17_19[3];
594
595 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
596 switch (sd->sensor) {
597 case SENSOR_HV7131R:
598 sn9c10x = initHv7131;
599 reg17_19[0] = 0x60;
600 reg17_19[1] = (mode << 4) | 0x8a;
601 reg17_19[2] = 0x20;
602 break;
603 case SENSOR_OV6650:
604 sn9c10x = initOv6650;
605 reg17_19[0] = 0x68;
606 reg17_19[1] = (mode << 4) | 0x8b;
607 reg17_19[2] = 0x20;
608 break;
609 case SENSOR_OV7630:
610 sn9c10x = initOv7630;
611 reg17_19[0] = 0x68;
612 reg17_19[1] = (mode << 4) | COMP2;
613 reg17_19[2] = MCK_INIT1;
614 break;
615 case SENSOR_OV7630_3:
616 sn9c10x = initOv7630_3;
617 reg17_19[0] = 0x68;
618 reg17_19[1] = (mode << 4) | COMP2;
619 reg17_19[2] = MCK_INIT1;
620 break;
621 case SENSOR_PAS106:
622 sn9c10x = initPas106;
623 reg17_19[0] = 0x24; /* 0x28 */
624 reg17_19[1] = (mode << 4) | COMP1;
625 reg17_19[2] = MCK_INIT1;
626 break;
627 case SENSOR_PAS202:
628 sn9c10x = initPas202;
629 reg17_19[0] = mode ? 0x24 : 0x20;
630 reg17_19[1] = (mode << 4) | 0x89;
631 reg17_19[2] = 0x20;
632 break;
633 case SENSOR_TAS5110:
634 sn9c10x = initTas5110;
635 reg17_19[0] = 0x60;
636 reg17_19[1] = (mode << 4) | 0x86;
637 reg17_19[2] = 0x2b; /* 0xf3; */
638 break;
639 default:
640/* case SENSOR_TAS5130CXX: */
641 sn9c10x = initTas5130;
642 reg17_19[0] = 0x60;
643 reg17_19[1] = (mode << 4) | COMP;
644 reg17_19[2] = mode ? 0x23 : 0x43;
645 break;
646 }
647 switch (sd->sensor) {
648 case SENSOR_OV7630:
649 reg01 = 0x06;
650 reg17 = 0x29;
651 l = 0x10;
652 break;
653 case SENSOR_OV7630_3:
654 reg01 = 0x44;
655 reg17 = 0x68;
656 l = 0x10;
657 break;
658 default:
659 reg01 = sn9c10x[0];
660 reg17 = sn9c10x[0x17 - 1];
661 l = 0x1f;
662 break;
663 }
664
665 /* reg 0x01 bit 2 video transfert on */
666 reg_w(dev, 0x01, &reg01, 1);
667 /* reg 0x17 SensorClk enable inv Clk 0x60 */
668 reg_w(dev, 0x17, &reg17, 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) {
674 case SENSOR_HV7131R:
675 i2c_w_vector(dev, hv7131_sensor_init,
676 sizeof hv7131_sensor_init);
677 break;
678 case SENSOR_OV6650:
679 i2c_w_vector(dev, ov6650_sensor_init,
680 sizeof ov6650_sensor_init);
681 break;
682 case SENSOR_OV7630:
683 i2c_w_vector(dev, ov7630_sensor_init_com,
684 sizeof ov7630_sensor_init_com);
685 msleep(200);
686 i2c_w_vector(dev, ov7630_sensor_init,
687 sizeof ov7630_sensor_init);
688 break;
689 case SENSOR_OV7630_3:
690 i2c_w_vector(dev, ov7630_sensor_init_com,
691 sizeof ov7630_sensor_init_com);
692 msleep(200);
693 i2c_w_vector(dev, ov7630_sensor_init_3,
694 sizeof ov7630_sensor_init_3);
695 break;
696 case SENSOR_PAS106:
697 pas106_i2cinit(dev);
698 break;
699 case SENSOR_PAS202:
700 i2c_w_vector(dev, pas202_sensor_init,
701 sizeof pas202_sensor_init);
702 break;
703 case SENSOR_TAS5110:
704 i2c_w_vector(dev, tas5110_sensor_init,
705 sizeof tas5110_sensor_init);
706 break;
707 default:
708/* case SENSOR_TAS5130CXX: */
709 i2c_w_vector(dev, tas5130_sensor_init,
710 sizeof tas5130_sensor_init);
711 break;
712 }
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, &reg17_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, &reg17_19[0], 1);
724 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
725 reg_w(dev, 0x19, &reg17_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);
730 /* Compression */
731 reg_w(dev, 0x18, &reg17_19[1], 2);
732 msleep(20);
733
734 setcontrast(gspca_dev);
735 setbrightness(gspca_dev);
736}
737
738static void sd_stopN(struct gspca_dev *gspca_dev)
739{
740 __u8 ByteSend = 0;
741
742 ByteSend = 0x09; /* 0X00 */
743 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
744}
745
746static void sd_stop0(struct gspca_dev *gspca_dev)
747{
748}
749
750static void sd_close(struct gspca_dev *gspca_dev)
751{
752}
753
754static 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 */
758{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300759 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300760
761 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300762 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,
770 frame, data, 0);
771 data += i + 12;
772 len -= i + 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300773 gspca_frame_add(gspca_dev, FIRST_PACKET,
774 frame, data, len);
775 return;
776 }
777 }
778 }
779 gspca_frame_add(gspca_dev, INTER_PACKET,
780 frame, data, len);
781}
782
783static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 sd->brightness = val;
788 if (gspca_dev->streaming)
789 setbrightness(gspca_dev);
790 return 0;
791}
792
793static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
796
797 *val = sd->brightness;
798 return 0;
799}
800
801static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
802{
803 struct sd *sd = (struct sd *) gspca_dev;
804
805 sd->contrast = val;
806 if (gspca_dev->streaming)
807 setcontrast(gspca_dev);
808 return 0;
809}
810
811static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
812{
813 struct sd *sd = (struct sd *) gspca_dev;
814
815 *val = sd->contrast;
816 return 0;
817}
818
819/* sub-driver description */
820static struct sd_desc sd_desc = {
821 .name = MODULE_NAME,
822 .ctrls = sd_ctrls,
823 .nctrls = ARRAY_SIZE(sd_ctrls),
824 .config = sd_config,
825 .open = sd_open,
826 .start = sd_start,
827 .stopN = sd_stopN,
828 .stop0 = sd_stop0,
829 .close = sd_close,
830 .pkt_scan = sd_pkt_scan,
831};
832
833/* -- module initialisation -- */
834#define DVNM(name) .driver_info = (kernel_ulong_t) name
835static __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")},
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300841 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 {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")},
852 {}
853};
854MODULE_DEVICE_TABLE(usb, device_table);
855
856/* -- device connect -- */
857static int sd_probe(struct usb_interface *intf,
858 const struct usb_device_id *id)
859{
860 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
861 THIS_MODULE);
862}
863
864static struct usb_driver sd_driver = {
865 .name = MODULE_NAME,
866 .id_table = device_table,
867 .probe = sd_probe,
868 .disconnect = gspca_disconnect,
869};
870
871/* -- module insert / remove -- */
872static int __init sd_mod_init(void)
873{
874 if (usb_register(&sd_driver) < 0)
875 return -1;
876 PDEBUG(D_PROBE, "v%s registered", version);
877 return 0;
878}
879static void __exit sd_mod_exit(void)
880{
881 usb_deregister(&sd_driver);
882 PDEBUG(D_PROBE, "deregistered");
883}
884
885module_init(sd_mod_init);
886module_exit(sd_mod_exit);