V4L/DVB (8157): gspca: all subdrivers
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / gspca / sonixb.c
CommitLineData
6a7eba24
JFM
1/*
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
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
28static const char version[] = "2.1.0";
29
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{
339 usb_control_msg(dev,
340 usb_sndctrlpipe(dev, 0),
341 0x08, /* request */
342 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
343 value,
344 0, /* index */
345 (__u8 *) buffer, len,
346 500);
347}
348
349static int i2c_w(struct usb_device *dev, const __u8 *buffer)
350{
351 int retry = 60;
352 __u8 ByteReceive;
353
354 /* is i2c ready */
355 reg_w(dev, 0x08, buffer, 8);
356 while (retry--) {
357 msleep(10);
358 reg_r(dev, 0x08, &ByteReceive);
359 if (ByteReceive == 4)
360 return 0;
361 }
362 return -1;
363}
364
365static void i2c_w_vector(struct usb_device *dev,
366 const __u8 buffer[][8], int len)
367{
368 for (;;) {
369 reg_w(dev, 0x08, *buffer, 8);
370 len -= 8;
371 if (len <= 0)
372 break;
373 buffer++;
374 }
375}
376
377static void setbrightness(struct gspca_dev *gspca_dev)
378{
379 struct sd *sd = (struct sd *) gspca_dev;
380 __u8 value;
381
382 switch (sd->sensor) {
383 case SENSOR_OV6650: {
384 __u8 i2cOV6650[] =
385 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
386
387 i2cOV6650[3] = sd->brightness;
388 if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
389 goto err;
390 break;
391 }
392 case SENSOR_OV7630: {
393 __u8 i2cOV[] =
394 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
395
396 /* change reg 0x06 */
397 i2cOV[3] = sd->brightness;
398 if (i2c_w(gspca_dev->dev, i2cOV) < 0)
399 goto err;
400 break;
401 }
402 case SENSOR_PAS106: {
403 __u8 i2c1[] =
404 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
405
406 i2c1[3] = sd->brightness >> 3;
407 i2c1[2] = 0x0e;
408 if (i2c_w(gspca_dev->dev, i2c1) < 0)
409 goto err;
410 i2c1[3] = 0x01;
411 i2c1[2] = 0x13;
412 if (i2c_w(gspca_dev->dev, i2c1) < 0)
413 goto err;
414 break;
415 }
416 case SENSOR_PAS202: {
417 /* __u8 i2cpexpo1[] =
418 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
419 __u8 i2cpexpo[] =
420 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
421 __u8 i2cp202[] =
422 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
423 static __u8 i2cpdoit[] =
424 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
425
426 /* change reg 0x10 */
427 i2cpexpo[4] = 0xff - sd->brightness;
428/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
429 goto err; */
430/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
431 goto err; */
432 if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
433 goto err;
434 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
435 goto err;
436 i2cp202[3] = sd->brightness >> 3;
437 if (i2c_w(gspca_dev->dev, i2cp202) < 0)
438 goto err;
439 if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
440 goto err;
441 break;
442 }
443 case SENSOR_TAS5130CXX:
444 case SENSOR_TAS5110: {
445 __u8 i2c[] =
446 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
447
448 value = 0xff - sd->brightness;
449 i2c[4] = value;
450 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
451 if (i2c_w(gspca_dev->dev, i2c) < 0)
452 goto err;
453 break;
454 }
455 }
456 return;
457err:
458 PDEBUG(D_ERR, "i2c error brightness");
459}
460static void setcontrast(struct gspca_dev *gspca_dev)
461{
462 struct sd *sd = (struct sd *) gspca_dev;
463 __u8 gain;
464 __u8 rgb_value;
465
466 gain = sd->contrast >> 4;
467 /* red and blue gain */
468 rgb_value = gain << 4 | gain;
469 reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
470 /* green gain */
471 rgb_value = gain;
472 reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
473}
474
475/* this function is called at probe time */
476static int sd_config(struct gspca_dev *gspca_dev,
477 const struct usb_device_id *id)
478{
479 struct sd *sd = (struct sd *) gspca_dev;
480 struct cam *cam;
481/* __u16 vendor; */
482 __u16 product;
483 int sif = 0;
484
485/* vendor = id->idVendor; */
486 product = id->idProduct;
487/* switch (vendor) { */
488/* case 0x0c45: * Sonix */
489 switch (product) {
490 case 0x6001: /* SN9C102 */
491 case 0x6005: /* SN9C101 */
492 case 0x6007: /* SN9C101 */
493 sd->sensor = SENSOR_TAS5110;
494 sif = 1;
495 break;
496 case 0x6009: /* SN9C101 */
497 case 0x600d: /* SN9C101 */
498 case 0x6029: /* SN9C101 */
499 sd->sensor = SENSOR_PAS106;
500 sif = 1;
501 break;
502 case 0x6011: /* SN9C101 - SN9C101G */
503 sd->sensor = SENSOR_OV6650;
504 sif = 1;
505 break;
506 case 0x6019: /* SN9C101 */
507 case 0x602c: /* SN9C102 */
508 case 0x602e: /* SN9C102 */
509 sd->sensor = SENSOR_OV7630;
510 break;
511 case 0x60b0: /* SN9C103 */
512 sd->sensor = SENSOR_OV7630_3;
513 break;
514 case 0x6024: /* SN9C102 */
515 case 0x6025: /* SN9C102 */
516 sd->sensor = SENSOR_TAS5130CXX;
517 break;
518 case 0x6028: /* SN9C102 */
519 sd->sensor = SENSOR_PAS202;
520 break;
521 case 0x602d: /* SN9C102 */
522 sd->sensor = SENSOR_HV7131R;
523 break;
524 case 0x60af: /* SN9C103 */
525 sd->sensor = SENSOR_PAS202;
526 break;
527 }
528/* break; */
529/* } */
530
531 cam = &gspca_dev->cam;
532 cam->dev_name = (char *) id->driver_info;
533 cam->epaddr = 0x01;
534 if (!sif) {
535 cam->cam_mode = vga_mode;
536 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
537 } else {
538 cam->cam_mode = sif_mode;
539 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
540 }
541 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
542 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
543 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
544 reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
545 return 0;
546}
547
548/* this function is called at open time */
549static int sd_open(struct gspca_dev *gspca_dev)
550{
551 __u8 ByteReceive;
552
553 reg_r(gspca_dev->dev, 0x00, &ByteReceive);
554 if (ByteReceive != 0x10)
555 return -ENODEV;
556 return 0;
557}
558
559static void pas106_i2cinit(struct usb_device *dev)
560{
561 int i;
562 const __u8 *data;
563 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
564
565 i = ARRAY_SIZE(pas106_data);
566 data = pas106_data[0];
567 while (--i >= 0) {
568 memcpy(&i2c1[2], data, 2);
569 /* copy 2 bytes from the template */
570 if (i2c_w(dev, i2c1) < 0)
571 PDEBUG(D_ERR, "i2c error pas106");
572 data += 2;
573 }
574}
575
576/* -- start the camera -- */
577static void sd_start(struct gspca_dev *gspca_dev)
578{
579 struct sd *sd = (struct sd *) gspca_dev;
580 struct usb_device *dev = gspca_dev->dev;
581 int mode, l;
582 const __u8 *sn9c10x;
583 __u8 reg01, reg17;
584 __u8 reg17_19[3];
585
586 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
587 switch (sd->sensor) {
588 case SENSOR_HV7131R:
589 sn9c10x = initHv7131;
590 reg17_19[0] = 0x60;
591 reg17_19[1] = (mode << 4) | 0x8a;
592 reg17_19[2] = 0x20;
593 break;
594 case SENSOR_OV6650:
595 sn9c10x = initOv6650;
596 reg17_19[0] = 0x68;
597 reg17_19[1] = (mode << 4) | 0x8b;
598 reg17_19[2] = 0x20;
599 break;
600 case SENSOR_OV7630:
601 sn9c10x = initOv7630;
602 reg17_19[0] = 0x68;
603 reg17_19[1] = (mode << 4) | COMP2;
604 reg17_19[2] = MCK_INIT1;
605 break;
606 case SENSOR_OV7630_3:
607 sn9c10x = initOv7630_3;
608 reg17_19[0] = 0x68;
609 reg17_19[1] = (mode << 4) | COMP2;
610 reg17_19[2] = MCK_INIT1;
611 break;
612 case SENSOR_PAS106:
613 sn9c10x = initPas106;
614 reg17_19[0] = 0x24; /* 0x28 */
615 reg17_19[1] = (mode << 4) | COMP1;
616 reg17_19[2] = MCK_INIT1;
617 break;
618 case SENSOR_PAS202:
619 sn9c10x = initPas202;
620 reg17_19[0] = mode ? 0x24 : 0x20;
621 reg17_19[1] = (mode << 4) | 0x89;
622 reg17_19[2] = 0x20;
623 break;
624 case SENSOR_TAS5110:
625 sn9c10x = initTas5110;
626 reg17_19[0] = 0x60;
627 reg17_19[1] = (mode << 4) | 0x86;
628 reg17_19[2] = 0x2b; /* 0xf3; */
629 break;
630 default:
631/* case SENSOR_TAS5130CXX: */
632 sn9c10x = initTas5130;
633 reg17_19[0] = 0x60;
634 reg17_19[1] = (mode << 4) | COMP;
635 reg17_19[2] = mode ? 0x23 : 0x43;
636 break;
637 }
638 switch (sd->sensor) {
639 case SENSOR_OV7630:
640 reg01 = 0x06;
641 reg17 = 0x29;
642 l = 0x10;
643 break;
644 case SENSOR_OV7630_3:
645 reg01 = 0x44;
646 reg17 = 0x68;
647 l = 0x10;
648 break;
649 default:
650 reg01 = sn9c10x[0];
651 reg17 = sn9c10x[0x17 - 1];
652 l = 0x1f;
653 break;
654 }
655
656 /* reg 0x01 bit 2 video transfert on */
657 reg_w(dev, 0x01, &reg01, 1);
658 /* reg 0x17 SensorClk enable inv Clk 0x60 */
659 reg_w(dev, 0x17, &reg17, 1);
660/*fixme: for ov7630 102
661 reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
662 /* Set the registers from the template */
663 reg_w(dev, 0x01, sn9c10x, l);
664 switch (sd->sensor) {
665 case SENSOR_HV7131R:
666 i2c_w_vector(dev, hv7131_sensor_init,
667 sizeof hv7131_sensor_init);
668 break;
669 case SENSOR_OV6650:
670 i2c_w_vector(dev, ov6650_sensor_init,
671 sizeof ov6650_sensor_init);
672 break;
673 case SENSOR_OV7630:
674 i2c_w_vector(dev, ov7630_sensor_init_com,
675 sizeof ov7630_sensor_init_com);
676 msleep(200);
677 i2c_w_vector(dev, ov7630_sensor_init,
678 sizeof ov7630_sensor_init);
679 break;
680 case SENSOR_OV7630_3:
681 i2c_w_vector(dev, ov7630_sensor_init_com,
682 sizeof ov7630_sensor_init_com);
683 msleep(200);
684 i2c_w_vector(dev, ov7630_sensor_init_3,
685 sizeof ov7630_sensor_init_3);
686 break;
687 case SENSOR_PAS106:
688 pas106_i2cinit(dev);
689 break;
690 case SENSOR_PAS202:
691 i2c_w_vector(dev, pas202_sensor_init,
692 sizeof pas202_sensor_init);
693 break;
694 case SENSOR_TAS5110:
695 i2c_w_vector(dev, tas5110_sensor_init,
696 sizeof tas5110_sensor_init);
697 break;
698 default:
699/* case SENSOR_TAS5130CXX: */
700 i2c_w_vector(dev, tas5130_sensor_init,
701 sizeof tas5130_sensor_init);
702 break;
703 }
704 /* H_size V_size 0x28, 0x1e maybe 640x480 */
705 reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
706 /* compression register */
707 reg_w(dev, 0x18, &reg17_19[1], 1);
708 /* H_start */ /*fixme: not ov7630*/
709 reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
710 /* V_START */ /*fixme: not ov7630*/
711 reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
712 /* reset 0x17 SensorClk enable inv Clk 0x60 */
713 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
714 reg_w(dev, 0x17, &reg17_19[0], 1);
715 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
716 reg_w(dev, 0x19, &reg17_19[2], 1);
717 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
718 reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
719 /* Enable video transfert */
720 reg_w(dev, 0x01, &sn9c10x[0], 1);
721 /* Compression */
722 reg_w(dev, 0x18, &reg17_19[1], 2);
723 msleep(20);
724
725 setcontrast(gspca_dev);
726 setbrightness(gspca_dev);
727}
728
729static void sd_stopN(struct gspca_dev *gspca_dev)
730{
731 __u8 ByteSend = 0;
732
733 ByteSend = 0x09; /* 0X00 */
734 reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
735}
736
737static void sd_stop0(struct gspca_dev *gspca_dev)
738{
739}
740
741static void sd_close(struct gspca_dev *gspca_dev)
742{
743}
744
745static void sd_pkt_scan(struct gspca_dev *gspca_dev,
746 struct gspca_frame *frame, /* target */
747 unsigned char *data, /* isoc packet */
748 int len) /* iso packet length */
749{
750 int p;
751
752 if (len > 6 && len < 24) {
753 for (p = 0; p < len - 6; p++) {
754 if (data[0 + p] == 0xff
755 && data[1 + p] == 0xff
756 && data[2 + p] == 0x00
757 && data[3 + p] == 0xc4
758 && data[4 + p] == 0xc4
759 && data[5 + p] == 0x96) { /* start of frame */
760 frame = gspca_frame_add(gspca_dev,
761 LAST_PACKET,
762 frame,
763 data, 0);
764 data += 12;
765 len -= 12;
766 gspca_frame_add(gspca_dev, FIRST_PACKET,
767 frame, data, len);
768 return;
769 }
770 }
771 }
772 gspca_frame_add(gspca_dev, INTER_PACKET,
773 frame, data, len);
774}
775
776static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
777{
778 struct sd *sd = (struct sd *) gspca_dev;
779
780 sd->brightness = val;
781 if (gspca_dev->streaming)
782 setbrightness(gspca_dev);
783 return 0;
784}
785
786static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
787{
788 struct sd *sd = (struct sd *) gspca_dev;
789
790 *val = sd->brightness;
791 return 0;
792}
793
794static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
795{
796 struct sd *sd = (struct sd *) gspca_dev;
797
798 sd->contrast = val;
799 if (gspca_dev->streaming)
800 setcontrast(gspca_dev);
801 return 0;
802}
803
804static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
805{
806 struct sd *sd = (struct sd *) gspca_dev;
807
808 *val = sd->contrast;
809 return 0;
810}
811
812/* sub-driver description */
813static struct sd_desc sd_desc = {
814 .name = MODULE_NAME,
815 .ctrls = sd_ctrls,
816 .nctrls = ARRAY_SIZE(sd_ctrls),
817 .config = sd_config,
818 .open = sd_open,
819 .start = sd_start,
820 .stopN = sd_stopN,
821 .stop0 = sd_stop0,
822 .close = sd_close,
823 .pkt_scan = sd_pkt_scan,
824};
825
826/* -- module initialisation -- */
827#define DVNM(name) .driver_info = (kernel_ulong_t) name
828static __devinitdata struct usb_device_id device_table[] = {
829 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
830 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
831 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
832 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
833 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
834 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia-OV6650-SN9C101G")},
835 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
836 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
837 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
838 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
839 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
840 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
841 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
842 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
843 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
844 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
845 {}
846};
847MODULE_DEVICE_TABLE(usb, device_table);
848
849/* -- device connect -- */
850static int sd_probe(struct usb_interface *intf,
851 const struct usb_device_id *id)
852{
853 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
854 THIS_MODULE);
855}
856
857static struct usb_driver sd_driver = {
858 .name = MODULE_NAME,
859 .id_table = device_table,
860 .probe = sd_probe,
861 .disconnect = gspca_disconnect,
862};
863
864/* -- module insert / remove -- */
865static int __init sd_mod_init(void)
866{
867 if (usb_register(&sd_driver) < 0)
868 return -1;
869 PDEBUG(D_PROBE, "v%s registered", version);
870 return 0;
871}
872static void __exit sd_mod_exit(void)
873{
874 usb_deregister(&sd_driver);
875 PDEBUG(D_PROBE, "deregistered");
876}
877
878module_init(sd_mod_init);
879module_exit(sd_mod_exit);