blob: 5745687363174f1d3ebc4e8d9d10773c0a5078d1 [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
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
28static const char version[] = "2.1.5";
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
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030098static struct v4l2_pix_format vga_mode[] = {
99 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
100 .bytesperline = 160,
101 .sizeimage = 160 * 120,
102 .colorspace = V4L2_COLORSPACE_SRGB,
103 .priv = 2},
104 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
105 .bytesperline = 320,
106 .sizeimage = 320 * 240,
107 .colorspace = V4L2_COLORSPACE_SRGB,
108 .priv = 1},
109 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
110 .bytesperline = 640,
111 .sizeimage = 640 * 480,
112 .colorspace = V4L2_COLORSPACE_SRGB,
113 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300114};
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300115static struct v4l2_pix_format sif_mode[] = {
116 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
117 .bytesperline = 176,
118 .sizeimage = 176 * 144,
119 .colorspace = V4L2_COLORSPACE_SRGB,
120 .priv = 1},
121 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
122 .bytesperline = 352,
123 .sizeimage = 352 * 288,
124 .colorspace = V4L2_COLORSPACE_SRGB,
125 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300126};
127
128static const __u8 probe_ov7630[] = {0x08, 0x44};
129
130static const __u8 initHv7131[] = {
131 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
132 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
134 0x28, 0x1e, 0x60, 0x8a, 0x20,
135 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
136};
137static const __u8 hv7131_sensor_init[][8] = {
138 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
139 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
140 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
141 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
142 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
143};
144static const __u8 initOv6650[] = {
145 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
146 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
148 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
149};
150static const __u8 ov6650_sensor_init[][8] =
151{
152 /* Bright, contrast, etc are set througth SCBB interface.
153 * AVCAP on win2 do not send any data on this controls. */
154 /* Anyway, some registers appears to alter bright and constrat */
155 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
156 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
157 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
158/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
159 * THIS SET GREEN SCREEN
160 * (pixels could be innverted in decode kind of "brg",
161 * but blue wont be there. Avoid this data ... */
162 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
163 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
164 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
165 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
166 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
167 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
168 {0xa0, 0x60, 0x10, 0x5d, 0x99, 0x04, 0x94, 0x16},
169 {0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
170 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
171 {0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
172 {0xa0, 0x60, 0x11, 0xc0, 0x99, 0x04, 0x94, 0x16},
173 {0xa0, 0x60, 0x00, 0x16, 0x99, 0x04, 0x94, 0x15}, /* bright / Lumino */
174 {0xa0, 0x60, 0x2b, 0xab, 0x99, 0x04, 0x94, 0x15},
175 /* ?flicker o brillo */
176 {0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
177 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
178 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
179 {0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
180 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
181 {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
182 {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
183 /* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
184 {0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
185 /* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
186/* {0xa0, 0x60, 0x11, 0xc1, 0x99, 0x04, 0x94, 0x16}, */
187 {0xa0, 0x60, 0x00, 0x17, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
188 {0xa0, 0x60, 0x00, 0x18, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
189};
190static const __u8 initOv7630[] = {
191 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
192 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
193 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
194 0x28, 0x1e, /* H & V sizes r15 .. r16 */
195 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
196 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
197};
198static const __u8 initOv7630_3[] = {
199 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
200 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
201 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
202 0x28, 0x1e, /* H & V sizes r15 .. r16 */
203 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
204 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
205};
206static const __u8 ov7630_sensor_init_com[][8] = {
207 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
208 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
209/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
210 {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
211 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
212 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
213 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
214 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
215 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
216 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
217 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
218/* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
219 {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
220 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
221 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
222 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
223 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
224 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
225 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
226};
227static const __u8 ov7630_sensor_init[][8] = {
228 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
229 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
230 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
231 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
232 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
233};
234static const __u8 ov7630_sensor_init_3[][8] = {
235 {0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
236 {0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
237 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
238 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
239/* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
240 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
241/* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
242 {0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
243};
244
245static const __u8 initPas106[] = {
246 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
247 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
249 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
250 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
251};
252/* compression 0x86 mckinit1 0x2b */
253static const __u8 pas106_data[][2] = {
254 {0x02, 0x04}, /* Pixel Clock Divider 6 */
255 {0x03, 0x13}, /* Frame Time MSB */
256/* {0x03, 0x12}, * Frame Time MSB */
257 {0x04, 0x06}, /* Frame Time LSB */
258/* {0x04, 0x05}, * Frame Time LSB */
259 {0x05, 0x65}, /* Shutter Time Line Offset */
260/* {0x05, 0x6d}, * Shutter Time Line Offset */
261/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
262 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
263 {0x07, 0xc1}, /* Black Level Subtract Sign */
264/* {0x07, 0x00}, * Black Level Subtract Sign */
265 {0x08, 0x06}, /* Black Level Subtract Level */
266 {0x08, 0x06}, /* Black Level Subtract Level */
267/* {0x08, 0x01}, * Black Level Subtract Level */
268 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
269 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
270 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
271 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
272 {0x0d, 0x00}, /* Color GainH Pixel */
273 {0x0e, 0x0e}, /* Global Gain */
274 {0x0f, 0x00}, /* Contrast */
275 {0x10, 0x06}, /* H&V synchro polarity */
276 {0x11, 0x06}, /* ?default */
277 {0x12, 0x06}, /* DAC scale */
278 {0x14, 0x02}, /* ?default */
279 {0x13, 0x01}, /* Validate Settings */
280};
281static const __u8 initPas202[] = {
282 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
283 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
285 0x28, 0x1e, 0x28, 0x89, 0x30,
286 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
287};
288static const __u8 pas202_sensor_init[][8] = {
289 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
290 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
291 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
292 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
293 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
294 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
295 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
296 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
297 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
298 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
299 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
300 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
301
302 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
303 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
304 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
305 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
306 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
307 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
308 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
309 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
310};
311
312static const __u8 initTas5110[] = {
313 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
314 0x00, 0x00,
315 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
316 0x16, 0x12, 0x60, 0x86, 0x2b,
317 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
318};
319static const __u8 tas5110_sensor_init[][8] = {
320 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
321 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
322 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
323};
324
325static const __u8 initTas5130[] = {
326 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
327 0x00, 0x00,
328 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
329 0x28, 0x1e, 0x60, COMP, MCK_INIT,
330 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
331};
332static const __u8 tas5130_sensor_init[][8] = {
333/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
334 * shutter 0x47 short exposure? */
335 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
336 /* shutter 0x01 long exposure */
337 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
338};
339
340static void reg_r(struct usb_device *dev,
341 __u16 value, __u8 *buffer)
342{
343 usb_control_msg(dev,
344 usb_rcvctrlpipe(dev, 0),
345 0, /* request */
346 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
347 value,
348 0, /* index */
349 buffer, 1,
350 500);
351}
352
353static void reg_w(struct usb_device *dev,
354 __u16 value,
355 const __u8 *buffer,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300356 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300358 __u8 tmpbuf[32];
359
360#ifdef CONFIG_VIDEO_ADV_DEBUG
361 if (len > sizeof tmpbuf) {
362 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
363 return;
364 }
365#endif
366 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367 usb_control_msg(dev,
368 usb_sndctrlpipe(dev, 0),
369 0x08, /* request */
370 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
371 value,
372 0, /* index */
Hans de Goede0d2a7222008-07-03 08:15:22 -0300373 tmpbuf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374 500);
375}
376
377static int i2c_w(struct usb_device *dev, const __u8 *buffer)
378{
379 int retry = 60;
380 __u8 ByteReceive;
381
382 /* is i2c ready */
383 reg_w(dev, 0x08, buffer, 8);
384 while (retry--) {
385 msleep(10);
386 reg_r(dev, 0x08, &ByteReceive);
387 if (ByteReceive == 4)
388 return 0;
389 }
390 return -1;
391}
392
393static void i2c_w_vector(struct usb_device *dev,
394 const __u8 buffer[][8], int len)
395{
396 for (;;) {
397 reg_w(dev, 0x08, *buffer, 8);
398 len -= 8;
399 if (len <= 0)
400 break;
401 buffer++;
402 }
403}
404
405static void setbrightness(struct gspca_dev *gspca_dev)
406{
407 struct sd *sd = (struct sd *) gspca_dev;
408 __u8 value;
409
410 switch (sd->sensor) {
411 case SENSOR_OV6650: {
412 __u8 i2cOV6650[] =
413 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
414
415 i2cOV6650[3] = sd->brightness;
416 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
417 goto err;
418 break;
419 }
420 case SENSOR_OV7630: {
421 __u8 i2cOV[] =
422 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
423
424 /* change reg 0x06 */
425 i2cOV[3] = sd->brightness;
426 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
427 goto err;
428 break;
429 }
430 case SENSOR_PAS106: {
431 __u8 i2c1[] =
432 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
433
434 i2c1[3] = sd->brightness >> 3;
435 i2c1[2] = 0x0e;
436 if (i2c_w(gspca_dev->dev, i2c1) < 0)
437 goto err;
438 i2c1[3] = 0x01;
439 i2c1[2] = 0x13;
440 if (i2c_w(gspca_dev->dev, i2c1) < 0)
441 goto err;
442 break;
443 }
444 case SENSOR_PAS202: {
445 /* __u8 i2cpexpo1[] =
446 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
447 __u8 i2cpexpo[] =
448 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
449 __u8 i2cp202[] =
450 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
451 static __u8 i2cpdoit[] =
452 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
453
454 /* change reg 0x10 */
455 i2cpexpo[4] = 0xff - sd->brightness;
456/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
457 goto err; */
458/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
459 goto err; */
460 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
461 goto err;
462 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
463 goto err;
464 i2cp202[3] = sd->brightness >> 3;
465 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
466 goto err;
467 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
468 goto err;
469 break;
470 }
471 case SENSOR_TAS5130CXX:
472 case SENSOR_TAS5110: {
473 __u8 i2c[] =
474 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
475
476 value = 0xff - sd->brightness;
477 i2c[4] = value;
478 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
479 if (i2c_w(gspca_dev->dev, i2c) < 0)
480 goto err;
481 break;
482 }
483 }
484 return;
485err:
486 PDEBUG(D_ERR, "i2c error brightness");
487}
488static void setcontrast(struct gspca_dev *gspca_dev)
489{
490 struct sd *sd = (struct sd *) gspca_dev;
491 __u8 gain;
492 __u8 rgb_value;
493
494 gain = sd->contrast >> 4;
495 /* red and blue gain */
496 rgb_value = gain << 4 | gain;
497 reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
498 /* green gain */
499 rgb_value = gain;
500 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
501}
502
503/* this function is called at probe time */
504static int sd_config(struct gspca_dev *gspca_dev,
505 const struct usb_device_id *id)
506{
507 struct sd *sd = (struct sd *) gspca_dev;
508 struct cam *cam;
509/* __u16 vendor; */
510 __u16 product;
511 int sif = 0;
512
513/* vendor = id->idVendor; */
514 product = id->idProduct;
515/* switch (vendor) { */
516/* case 0x0c45: * Sonix */
517 switch (product) {
518 case 0x6001: /* SN9C102 */
519 case 0x6005: /* SN9C101 */
520 case 0x6007: /* SN9C101 */
521 sd->sensor = SENSOR_TAS5110;
522 sif = 1;
523 break;
524 case 0x6009: /* SN9C101 */
525 case 0x600d: /* SN9C101 */
526 case 0x6029: /* SN9C101 */
527 sd->sensor = SENSOR_PAS106;
528 sif = 1;
529 break;
530 case 0x6011: /* SN9C101 - SN9C101G */
531 sd->sensor = SENSOR_OV6650;
532 sif = 1;
533 break;
534 case 0x6019: /* SN9C101 */
535 case 0x602c: /* SN9C102 */
536 case 0x602e: /* SN9C102 */
537 sd->sensor = SENSOR_OV7630;
538 break;
539 case 0x60b0: /* SN9C103 */
540 sd->sensor = SENSOR_OV7630_3;
541 break;
542 case 0x6024: /* SN9C102 */
543 case 0x6025: /* SN9C102 */
544 sd->sensor = SENSOR_TAS5130CXX;
545 break;
546 case 0x6028: /* SN9C102 */
547 sd->sensor = SENSOR_PAS202;
548 break;
549 case 0x602d: /* SN9C102 */
550 sd->sensor = SENSOR_HV7131R;
551 break;
552 case 0x60af: /* SN9C103 */
553 sd->sensor = SENSOR_PAS202;
554 break;
555 }
556/* break; */
557/* } */
558
559 cam = &gspca_dev->cam;
560 cam->dev_name = (char *) id->driver_info;
561 cam->epaddr = 0x01;
562 if (!sif) {
563 cam->cam_mode = vga_mode;
564 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
565 } else {
566 cam->cam_mode = sif_mode;
567 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
568 }
569 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
570 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
571 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
572 reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
573 return 0;
574}
575
576/* this function is called at open time */
577static int sd_open(struct gspca_dev *gspca_dev)
578{
579 __u8 ByteReceive;
580
581 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
582 if (ByteReceive != 0x10)
583 return -ENODEV;
584 return 0;
585}
586
587static void pas106_i2cinit(struct usb_device *dev)
588{
589 int i;
590 const __u8 *data;
591 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
592
593 i = ARRAY_SIZE(pas106_data);
594 data = pas106_data[0];
595 while (--i >= 0) {
596 memcpy(&i2c1[2], data, 2);
597 /* copy 2 bytes from the template */
598 if (i2c_w(dev, i2c1) < 0)
599 PDEBUG(D_ERR, "i2c error pas106");
600 data += 2;
601 }
602}
603
604/* -- start the camera -- */
605static void sd_start(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608 struct usb_device *dev = gspca_dev->dev;
609 int mode, l;
610 const __u8 *sn9c10x;
611 __u8 reg01, reg17;
612 __u8 reg17_19[3];
613
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300614 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615 switch (sd->sensor) {
616 case SENSOR_HV7131R:
617 sn9c10x = initHv7131;
618 reg17_19[0] = 0x60;
619 reg17_19[1] = (mode << 4) | 0x8a;
620 reg17_19[2] = 0x20;
621 break;
622 case SENSOR_OV6650:
623 sn9c10x = initOv6650;
624 reg17_19[0] = 0x68;
625 reg17_19[1] = (mode << 4) | 0x8b;
626 reg17_19[2] = 0x20;
627 break;
628 case SENSOR_OV7630:
629 sn9c10x = initOv7630;
630 reg17_19[0] = 0x68;
631 reg17_19[1] = (mode << 4) | COMP2;
632 reg17_19[2] = MCK_INIT1;
633 break;
634 case SENSOR_OV7630_3:
635 sn9c10x = initOv7630_3;
636 reg17_19[0] = 0x68;
637 reg17_19[1] = (mode << 4) | COMP2;
638 reg17_19[2] = MCK_INIT1;
639 break;
640 case SENSOR_PAS106:
641 sn9c10x = initPas106;
642 reg17_19[0] = 0x24; /* 0x28 */
643 reg17_19[1] = (mode << 4) | COMP1;
644 reg17_19[2] = MCK_INIT1;
645 break;
646 case SENSOR_PAS202:
647 sn9c10x = initPas202;
648 reg17_19[0] = mode ? 0x24 : 0x20;
649 reg17_19[1] = (mode << 4) | 0x89;
650 reg17_19[2] = 0x20;
651 break;
652 case SENSOR_TAS5110:
653 sn9c10x = initTas5110;
654 reg17_19[0] = 0x60;
655 reg17_19[1] = (mode << 4) | 0x86;
656 reg17_19[2] = 0x2b; /* 0xf3; */
657 break;
658 default:
659/* case SENSOR_TAS5130CXX: */
660 sn9c10x = initTas5130;
661 reg17_19[0] = 0x60;
662 reg17_19[1] = (mode << 4) | COMP;
663 reg17_19[2] = mode ? 0x23 : 0x43;
664 break;
665 }
666 switch (sd->sensor) {
667 case SENSOR_OV7630:
668 reg01 = 0x06;
669 reg17 = 0x29;
670 l = 0x10;
671 break;
672 case SENSOR_OV7630_3:
673 reg01 = 0x44;
674 reg17 = 0x68;
675 l = 0x10;
676 break;
677 default:
678 reg01 = sn9c10x[0];
679 reg17 = sn9c10x[0x17 - 1];
680 l = 0x1f;
681 break;
682 }
683
684 /* reg 0x01 bit 2 video transfert on */
685 reg_w(dev, 0x01, &reg01, 1);
686 /* reg 0x17 SensorClk enable inv Clk 0x60 */
687 reg_w(dev, 0x17, &reg17, 1);
688/*fixme: for ov7630 102
689 reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
690 /* Set the registers from the template */
691 reg_w(dev, 0x01, sn9c10x, l);
692 switch (sd->sensor) {
693 case SENSOR_HV7131R:
694 i2c_w_vector(dev, hv7131_sensor_init,
695 sizeof hv7131_sensor_init);
696 break;
697 case SENSOR_OV6650:
698 i2c_w_vector(dev, ov6650_sensor_init,
699 sizeof ov6650_sensor_init);
700 break;
701 case SENSOR_OV7630:
702 i2c_w_vector(dev, ov7630_sensor_init_com,
703 sizeof ov7630_sensor_init_com);
704 msleep(200);
705 i2c_w_vector(dev, ov7630_sensor_init,
706 sizeof ov7630_sensor_init);
707 break;
708 case SENSOR_OV7630_3:
709 i2c_w_vector(dev, ov7630_sensor_init_com,
710 sizeof ov7630_sensor_init_com);
711 msleep(200);
712 i2c_w_vector(dev, ov7630_sensor_init_3,
713 sizeof ov7630_sensor_init_3);
714 break;
715 case SENSOR_PAS106:
716 pas106_i2cinit(dev);
717 break;
718 case SENSOR_PAS202:
719 i2c_w_vector(dev, pas202_sensor_init,
720 sizeof pas202_sensor_init);
721 break;
722 case SENSOR_TAS5110:
723 i2c_w_vector(dev, tas5110_sensor_init,
724 sizeof tas5110_sensor_init);
725 break;
726 default:
727/* case SENSOR_TAS5130CXX: */
728 i2c_w_vector(dev, tas5130_sensor_init,
729 sizeof tas5130_sensor_init);
730 break;
731 }
732 /* H_size V_size 0x28, 0x1e maybe 640x480 */
733 reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
734 /* compression register */
735 reg_w(dev, 0x18, &reg17_19[1], 1);
736 /* H_start */ /*fixme: not ov7630*/
737 reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
738 /* V_START */ /*fixme: not ov7630*/
739 reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
740 /* reset 0x17 SensorClk enable inv Clk 0x60 */
741 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
742 reg_w(dev, 0x17, &reg17_19[0], 1);
743 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
744 reg_w(dev, 0x19, &reg17_19[2], 1);
745 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
746 reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
747 /* Enable video transfert */
748 reg_w(dev, 0x01, &sn9c10x[0], 1);
749 /* Compression */
750 reg_w(dev, 0x18, &reg17_19[1], 2);
751 msleep(20);
752
753 setcontrast(gspca_dev);
754 setbrightness(gspca_dev);
755}
756
757static void sd_stopN(struct gspca_dev *gspca_dev)
758{
759 __u8 ByteSend = 0;
760
761 ByteSend = 0x09; /* 0X00 */
762 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
763}
764
765static void sd_stop0(struct gspca_dev *gspca_dev)
766{
767}
768
769static void sd_close(struct gspca_dev *gspca_dev)
770{
771}
772
773static void sd_pkt_scan(struct gspca_dev *gspca_dev,
774 struct gspca_frame *frame, /* target */
775 unsigned char *data, /* isoc packet */
776 int len) /* iso packet length */
777{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300778 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779
780 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300781 for (i = 0; i < len - 6; i++) {
782 if (data[0 + i] == 0xff
783 && data[1 + i] == 0xff
784 && data[2 + i] == 0x00
785 && data[3 + i] == 0xc4
786 && data[4 + i] == 0xc4
787 && data[5 + i] == 0x96) { /* start of frame */
788 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
789 frame, data, 0);
790 data += i + 12;
791 len -= i + 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 gspca_frame_add(gspca_dev, FIRST_PACKET,
793 frame, data, len);
794 return;
795 }
796 }
797 }
798 gspca_frame_add(gspca_dev, INTER_PACKET,
799 frame, data, len);
800}
801
802static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805
806 sd->brightness = val;
807 if (gspca_dev->streaming)
808 setbrightness(gspca_dev);
809 return 0;
810}
811
812static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
813{
814 struct sd *sd = (struct sd *) gspca_dev;
815
816 *val = sd->brightness;
817 return 0;
818}
819
820static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
821{
822 struct sd *sd = (struct sd *) gspca_dev;
823
824 sd->contrast = val;
825 if (gspca_dev->streaming)
826 setcontrast(gspca_dev);
827 return 0;
828}
829
830static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
831{
832 struct sd *sd = (struct sd *) gspca_dev;
833
834 *val = sd->contrast;
835 return 0;
836}
837
838/* sub-driver description */
839static struct sd_desc sd_desc = {
840 .name = MODULE_NAME,
841 .ctrls = sd_ctrls,
842 .nctrls = ARRAY_SIZE(sd_ctrls),
843 .config = sd_config,
844 .open = sd_open,
845 .start = sd_start,
846 .stopN = sd_stopN,
847 .stop0 = sd_stop0,
848 .close = sd_close,
849 .pkt_scan = sd_pkt_scan,
850};
851
852/* -- module initialisation -- */
853#define DVNM(name) .driver_info = (kernel_ulong_t) name
854static __devinitdata struct usb_device_id device_table[] = {
855 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
856 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
857 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
858 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
859 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300860 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300861 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
862 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
863 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
864 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
865 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
866 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
867 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
868 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
869 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
870 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
871 {}
872};
873MODULE_DEVICE_TABLE(usb, device_table);
874
875/* -- device connect -- */
876static int sd_probe(struct usb_interface *intf,
877 const struct usb_device_id *id)
878{
879 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
880 THIS_MODULE);
881}
882
883static struct usb_driver sd_driver = {
884 .name = MODULE_NAME,
885 .id_table = device_table,
886 .probe = sd_probe,
887 .disconnect = gspca_disconnect,
888};
889
890/* -- module insert / remove -- */
891static int __init sd_mod_init(void)
892{
893 if (usb_register(&sd_driver) < 0)
894 return -1;
895 PDEBUG(D_PROBE, "v%s registered", version);
896 return 0;
897}
898static void __exit sd_mod_exit(void)
899{
900 usb_deregister(&sd_driver);
901 PDEBUG(D_PROBE, "deregistered");
902}
903
904module_init(sd_mod_init);
905module_exit(sd_mod_exit);