blob: 95a6a8e98b9763b713dd677c3993de93bd256afd [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
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -030041 unsigned char fr_h_sz; /* size of frame header */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030042 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
51};
52
53#define COMP2 0x8f
54#define COMP 0xc7 /* 0x87 //0x07 */
55#define COMP1 0xc9 /* 0x89 //0x09 */
56
57#define MCK_INIT 0x63
58#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
59
60#define SYS_CLK 0x04
61
62/* V4L2 controls supported by the driver */
63static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67
68static struct ctrl sd_ctrls[] = {
69#define SD_BRIGHTNESS 0
70 {
71 {
72 .id = V4L2_CID_BRIGHTNESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Brightness",
75 .minimum = 0,
76 .maximum = 255,
77 .step = 1,
78 .default_value = 127,
79 },
80 .set = sd_setbrightness,
81 .get = sd_getbrightness,
82 },
83#define SD_CONTRAST 1
84 {
85 {
86 .id = V4L2_CID_CONTRAST,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Contrast",
89 .minimum = 0,
90 .maximum = 255,
91 .step = 1,
92 .default_value = 127,
93 },
94 .set = sd_setcontrast,
95 .get = sd_getcontrast,
96 },
97};
98
Jean-Francois Moinec2446b32008-07-05 11:49:20 -030099static struct v4l2_pix_format vga_mode[] = {
100 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
101 .bytesperline = 160,
102 .sizeimage = 160 * 120,
103 .colorspace = V4L2_COLORSPACE_SRGB,
104 .priv = 2},
105 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240,
108 .colorspace = V4L2_COLORSPACE_SRGB,
109 .priv = 1},
110 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
111 .bytesperline = 640,
112 .sizeimage = 640 * 480,
113 .colorspace = V4L2_COLORSPACE_SRGB,
114 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115};
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300116static struct v4l2_pix_format sif_mode[] = {
117 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
118 .bytesperline = 176,
119 .sizeimage = 176 * 144,
120 .colorspace = V4L2_COLORSPACE_SRGB,
121 .priv = 1},
122 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
123 .bytesperline = 352,
124 .sizeimage = 352 * 288,
125 .colorspace = V4L2_COLORSPACE_SRGB,
126 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127};
128
129static const __u8 probe_ov7630[] = {0x08, 0x44};
130
131static const __u8 initHv7131[] = {
132 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
133 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
137};
138static 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},
144};
145static 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
150};
151static const __u8 ov6650_sensor_init[][8] =
152{
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 */
190};
191static 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 */
198};
199static 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 */
206};
207static 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},
227};
228static 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 */
234};
235static 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},
244};
245
246static const __u8 initPas106[] = {
247 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
248 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
250 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
251 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
252};
253/* compression 0x86 mckinit1 0x2b */
254static 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 */
281};
282static const __u8 initPas202[] = {
283 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
284 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
286 0x28, 0x1e, 0x28, 0x89, 0x30,
287 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
288};
289static 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},
302
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},
311};
312
313static const __u8 initTas5110[] = {
314 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
315 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
319};
320static 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},
324};
325
326static const __u8 initTas5130[] = {
327 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
328 0x00, 0x00,
329 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
330 0x28, 0x1e, 0x60, COMP, MCK_INIT,
331 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
332};
333static 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},
339};
340
341static void reg_r(struct usb_device *dev,
342 __u16 value, __u8 *buffer)
343{
344 usb_control_msg(dev,
345 usb_rcvctrlpipe(dev, 0),
346 0, /* request */
347 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
348 value,
349 0, /* index */
350 buffer, 1,
351 500);
352}
353
354static void reg_w(struct usb_device *dev,
355 __u16 value,
356 const __u8 *buffer,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300357 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300359 __u8 tmpbuf[32];
360
361#ifdef CONFIG_VIDEO_ADV_DEBUG
362 if (len > sizeof tmpbuf) {
363 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
364 return;
365 }
366#endif
367 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300368 usb_control_msg(dev,
369 usb_sndctrlpipe(dev, 0),
370 0x08, /* request */
371 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
372 value,
373 0, /* index */
Hans de Goede0d2a7222008-07-03 08:15:22 -0300374 tmpbuf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300375 500);
376}
377
378static int i2c_w(struct usb_device *dev, const __u8 *buffer)
379{
380 int retry = 60;
381 __u8 ByteReceive;
382
383 /* is i2c ready */
384 reg_w(dev, 0x08, buffer, 8);
385 while (retry--) {
386 msleep(10);
387 reg_r(dev, 0x08, &ByteReceive);
388 if (ByteReceive == 4)
389 return 0;
390 }
391 return -1;
392}
393
394static void i2c_w_vector(struct usb_device *dev,
395 const __u8 buffer[][8], int len)
396{
397 for (;;) {
398 reg_w(dev, 0x08, *buffer, 8);
399 len -= 8;
400 if (len <= 0)
401 break;
402 buffer++;
403 }
404}
405
406static void setbrightness(struct gspca_dev *gspca_dev)
407{
408 struct sd *sd = (struct sd *) gspca_dev;
409 __u8 value;
410
411 switch (sd->sensor) {
412 case SENSOR_OV6650: {
413 __u8 i2cOV6650[] =
414 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
415
416 i2cOV6650[3] = sd->brightness;
417 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
418 goto err;
419 break;
420 }
421 case SENSOR_OV7630: {
422 __u8 i2cOV[] =
423 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
424
425 /* change reg 0x06 */
426 i2cOV[3] = sd->brightness;
427 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
428 goto err;
429 break;
430 }
431 case SENSOR_PAS106: {
432 __u8 i2c1[] =
433 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
434
435 i2c1[3] = sd->brightness >> 3;
436 i2c1[2] = 0x0e;
437 if (i2c_w(gspca_dev->dev, i2c1) < 0)
438 goto err;
439 i2c1[3] = 0x01;
440 i2c1[2] = 0x13;
441 if (i2c_w(gspca_dev->dev, i2c1) < 0)
442 goto err;
443 break;
444 }
445 case SENSOR_PAS202: {
446 /* __u8 i2cpexpo1[] =
447 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
448 __u8 i2cpexpo[] =
449 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
450 __u8 i2cp202[] =
451 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
452 static __u8 i2cpdoit[] =
453 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
454
455 /* change reg 0x10 */
456 i2cpexpo[4] = 0xff - sd->brightness;
457/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
458 goto err; */
459/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
460 goto err; */
461 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
462 goto err;
463 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
464 goto err;
465 i2cp202[3] = sd->brightness >> 3;
466 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
467 goto err;
468 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
469 goto err;
470 break;
471 }
472 case SENSOR_TAS5130CXX:
473 case SENSOR_TAS5110: {
474 __u8 i2c[] =
475 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
476
477 value = 0xff - sd->brightness;
478 i2c[4] = value;
479 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
480 if (i2c_w(gspca_dev->dev, i2c) < 0)
481 goto err;
482 break;
483 }
484 }
485 return;
486err:
487 PDEBUG(D_ERR, "i2c error brightness");
488}
489static void setcontrast(struct gspca_dev *gspca_dev)
490{
491 struct sd *sd = (struct sd *) gspca_dev;
492 __u8 gain;
493 __u8 rgb_value;
494
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);
499 /* green gain */
500 rgb_value = gain;
501 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
502}
503
504/* this function is called at probe time */
505static int sd_config(struct gspca_dev *gspca_dev,
506 const struct usb_device_id *id)
507{
508 struct sd *sd = (struct sd *) gspca_dev;
509 struct cam *cam;
510/* __u16 vendor; */
511 __u16 product;
512 int sif = 0;
513
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300514 sd->fr_h_sz = 12; /* default size of the frame header */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515/* vendor = id->idVendor; */
516 product = id->idProduct;
517/* switch (vendor) { */
518/* case 0x0c45: * Sonix */
519 switch (product) {
520 case 0x6001: /* SN9C102 */
521 case 0x6005: /* SN9C101 */
522 case 0x6007: /* SN9C101 */
523 sd->sensor = SENSOR_TAS5110;
524 sif = 1;
525 break;
526 case 0x6009: /* SN9C101 */
527 case 0x600d: /* SN9C101 */
528 case 0x6029: /* SN9C101 */
529 sd->sensor = SENSOR_PAS106;
530 sif = 1;
531 break;
532 case 0x6011: /* SN9C101 - SN9C101G */
533 sd->sensor = SENSOR_OV6650;
534 sif = 1;
535 break;
536 case 0x6019: /* SN9C101 */
537 case 0x602c: /* SN9C102 */
538 case 0x602e: /* SN9C102 */
539 sd->sensor = SENSOR_OV7630;
540 break;
541 case 0x60b0: /* SN9C103 */
542 sd->sensor = SENSOR_OV7630_3;
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300543 sd->fr_h_sz = 18; /* size of frame header */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544 break;
545 case 0x6024: /* SN9C102 */
546 case 0x6025: /* SN9C102 */
547 sd->sensor = SENSOR_TAS5130CXX;
548 break;
549 case 0x6028: /* SN9C102 */
550 sd->sensor = SENSOR_PAS202;
551 break;
552 case 0x602d: /* SN9C102 */
553 sd->sensor = SENSOR_HV7131R;
554 break;
555 case 0x60af: /* SN9C103 */
556 sd->sensor = SENSOR_PAS202;
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300557 sd->fr_h_sz = 18; /* size of frame header (?) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300558 break;
559 }
560/* break; */
561/* } */
562
563 cam = &gspca_dev->cam;
564 cam->dev_name = (char *) id->driver_info;
565 cam->epaddr = 0x01;
566 if (!sif) {
567 cam->cam_mode = vga_mode;
568 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
569 } else {
570 cam->cam_mode = sif_mode;
571 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
572 }
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);
577 return 0;
578}
579
580/* this function is called at open time */
581static int sd_open(struct gspca_dev *gspca_dev)
582{
583 __u8 ByteReceive;
584
585 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
586 if (ByteReceive != 0x10)
587 return -ENODEV;
588 return 0;
589}
590
591static void pas106_i2cinit(struct usb_device *dev)
592{
593 int i;
594 const __u8 *data;
595 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
596
597 i = ARRAY_SIZE(pas106_data);
598 data = pas106_data[0];
599 while (--i >= 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");
604 data += 2;
605 }
606}
607
608/* -- start the camera -- */
609static void sd_start(struct gspca_dev *gspca_dev)
610{
611 struct sd *sd = (struct sd *) gspca_dev;
612 struct usb_device *dev = gspca_dev->dev;
613 int mode, l;
614 const __u8 *sn9c10x;
615 __u8 reg01, reg17;
616 __u8 reg17_19[3];
617
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300618 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 switch (sd->sensor) {
620 case SENSOR_HV7131R:
621 sn9c10x = initHv7131;
622 reg17_19[0] = 0x60;
623 reg17_19[1] = (mode << 4) | 0x8a;
624 reg17_19[2] = 0x20;
625 break;
626 case SENSOR_OV6650:
627 sn9c10x = initOv6650;
628 reg17_19[0] = 0x68;
629 reg17_19[1] = (mode << 4) | 0x8b;
630 reg17_19[2] = 0x20;
631 break;
632 case SENSOR_OV7630:
633 sn9c10x = initOv7630;
634 reg17_19[0] = 0x68;
635 reg17_19[1] = (mode << 4) | COMP2;
636 reg17_19[2] = MCK_INIT1;
637 break;
638 case SENSOR_OV7630_3:
639 sn9c10x = initOv7630_3;
640 reg17_19[0] = 0x68;
641 reg17_19[1] = (mode << 4) | COMP2;
642 reg17_19[2] = MCK_INIT1;
643 break;
644 case SENSOR_PAS106:
645 sn9c10x = initPas106;
646 reg17_19[0] = 0x24; /* 0x28 */
647 reg17_19[1] = (mode << 4) | COMP1;
648 reg17_19[2] = MCK_INIT1;
649 break;
650 case SENSOR_PAS202:
651 sn9c10x = initPas202;
652 reg17_19[0] = mode ? 0x24 : 0x20;
653 reg17_19[1] = (mode << 4) | 0x89;
654 reg17_19[2] = 0x20;
655 break;
656 case SENSOR_TAS5110:
657 sn9c10x = initTas5110;
658 reg17_19[0] = 0x60;
659 reg17_19[1] = (mode << 4) | 0x86;
660 reg17_19[2] = 0x2b; /* 0xf3; */
661 break;
662 default:
663/* case SENSOR_TAS5130CXX: */
664 sn9c10x = initTas5130;
665 reg17_19[0] = 0x60;
666 reg17_19[1] = (mode << 4) | COMP;
667 reg17_19[2] = mode ? 0x23 : 0x43;
668 break;
669 }
670 switch (sd->sensor) {
671 case SENSOR_OV7630:
672 reg01 = 0x06;
673 reg17 = 0x29;
674 l = 0x10;
675 break;
676 case SENSOR_OV7630_3:
677 reg01 = 0x44;
678 reg17 = 0x68;
679 l = 0x10;
680 break;
681 default:
682 reg01 = sn9c10x[0];
683 reg17 = sn9c10x[0x17 - 1];
684 l = 0x1f;
685 break;
686 }
687
688 /* reg 0x01 bit 2 video transfert on */
689 reg_w(dev, 0x01, &reg01, 1);
690 /* reg 0x17 SensorClk enable inv Clk 0x60 */
691 reg_w(dev, 0x17, &reg17, 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) {
697 case SENSOR_HV7131R:
698 i2c_w_vector(dev, hv7131_sensor_init,
699 sizeof hv7131_sensor_init);
700 break;
701 case SENSOR_OV6650:
702 i2c_w_vector(dev, ov6650_sensor_init,
703 sizeof ov6650_sensor_init);
704 break;
705 case SENSOR_OV7630:
706 i2c_w_vector(dev, ov7630_sensor_init_com,
707 sizeof ov7630_sensor_init_com);
708 msleep(200);
709 i2c_w_vector(dev, ov7630_sensor_init,
710 sizeof ov7630_sensor_init);
711 break;
712 case SENSOR_OV7630_3:
713 i2c_w_vector(dev, ov7630_sensor_init_com,
714 sizeof ov7630_sensor_init_com);
715 msleep(200);
716 i2c_w_vector(dev, ov7630_sensor_init_3,
717 sizeof ov7630_sensor_init_3);
718 break;
719 case SENSOR_PAS106:
720 pas106_i2cinit(dev);
721 break;
722 case SENSOR_PAS202:
723 i2c_w_vector(dev, pas202_sensor_init,
724 sizeof pas202_sensor_init);
725 break;
726 case SENSOR_TAS5110:
727 i2c_w_vector(dev, tas5110_sensor_init,
728 sizeof tas5110_sensor_init);
729 break;
730 default:
731/* case SENSOR_TAS5130CXX: */
732 i2c_w_vector(dev, tas5130_sensor_init,
733 sizeof tas5130_sensor_init);
734 break;
735 }
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, &reg17_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, &reg17_19[0], 1);
747 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
748 reg_w(dev, 0x19, &reg17_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);
753 /* Compression */
754 reg_w(dev, 0x18, &reg17_19[1], 2);
755 msleep(20);
756
757 setcontrast(gspca_dev);
758 setbrightness(gspca_dev);
759}
760
761static void sd_stopN(struct gspca_dev *gspca_dev)
762{
763 __u8 ByteSend = 0;
764
765 ByteSend = 0x09; /* 0X00 */
766 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
767}
768
769static void sd_stop0(struct gspca_dev *gspca_dev)
770{
771}
772
773static void sd_close(struct gspca_dev *gspca_dev)
774{
775}
776
777static 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 */
781{
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300782 struct sd *sd;
Hans de Goede0d2a7222008-07-03 08:15:22 -0300783 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784
785 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300786 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,
794 frame, data, 0);
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300795 sd = (struct sd *) gspca_dev;
796 data += i + sd->fr_h_sz;
797 len -= i + sd->fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798 gspca_frame_add(gspca_dev, FIRST_PACKET,
799 frame, data, len);
800 return;
801 }
802 }
803 }
804 gspca_frame_add(gspca_dev, INTER_PACKET,
805 frame, data, len);
806}
807
808static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
809{
810 struct sd *sd = (struct sd *) gspca_dev;
811
812 sd->brightness = val;
813 if (gspca_dev->streaming)
814 setbrightness(gspca_dev);
815 return 0;
816}
817
818static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
819{
820 struct sd *sd = (struct sd *) gspca_dev;
821
822 *val = sd->brightness;
823 return 0;
824}
825
826static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
827{
828 struct sd *sd = (struct sd *) gspca_dev;
829
830 sd->contrast = val;
831 if (gspca_dev->streaming)
832 setcontrast(gspca_dev);
833 return 0;
834}
835
836static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
837{
838 struct sd *sd = (struct sd *) gspca_dev;
839
840 *val = sd->contrast;
841 return 0;
842}
843
844/* sub-driver description */
845static struct sd_desc sd_desc = {
846 .name = MODULE_NAME,
847 .ctrls = sd_ctrls,
848 .nctrls = ARRAY_SIZE(sd_ctrls),
849 .config = sd_config,
850 .open = sd_open,
851 .start = sd_start,
852 .stopN = sd_stopN,
853 .stop0 = sd_stop0,
854 .close = sd_close,
855 .pkt_scan = sd_pkt_scan,
856};
857
858/* -- module initialisation -- */
859#define DVNM(name) .driver_info = (kernel_ulong_t) name
860static __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -0300861#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862 {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")},
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300867 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 {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")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -0300878#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 {}
880};
881MODULE_DEVICE_TABLE(usb, device_table);
882
883/* -- device connect -- */
884static int sd_probe(struct usb_interface *intf,
885 const struct usb_device_id *id)
886{
887 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
888 THIS_MODULE);
889}
890
891static struct usb_driver sd_driver = {
892 .name = MODULE_NAME,
893 .id_table = device_table,
894 .probe = sd_probe,
895 .disconnect = gspca_disconnect,
896};
897
898/* -- module insert / remove -- */
899static int __init sd_mod_init(void)
900{
901 if (usb_register(&sd_driver) < 0)
902 return -1;
903 PDEBUG(D_PROBE, "v%s registered", version);
904 return 0;
905}
906static void __exit sd_mod_exit(void)
907{
908 usb_deregister(&sd_driver);
909 PDEBUG(D_PROBE, "deregistered");
910}
911
912module_init(sd_mod_init);
913module_exit(sd_mod_exit);