blob: 162beb3feadb124f54785063e6fb13060e89c88f [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 Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030034 atomic_t avg_lum;
35
Hans de Goedead5ef80d2008-07-14 10:11:42 -030036 unsigned char gain;
37 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030038 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030039 unsigned char autogain;
40 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030041 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030042 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -030044 unsigned char fr_h_sz; /* size of frame header */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030045 char sensor; /* Type of image sensor chip */
46#define SENSOR_HV7131R 0
47#define SENSOR_OV6650 1
48#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030049#define SENSOR_PAS106 3
50#define SENSOR_PAS202 4
51#define SENSOR_TAS5110 5
52#define SENSOR_TAS5130CXX 6
Hans de Goedea975a522008-07-16 15:29:11 -030053 char sensor_has_gain;
54 __u8 sensor_addr;
Hans de Goede6af492e2008-07-22 07:09:33 -030055 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056};
57
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030058/* flags used in the device id table */
59#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030060#define F_SIF 0x02 /* sif or vga */
61#define F_H18 0x04 /* long (18 b) or short (12 b) frame header */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030062
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063#define COMP2 0x8f
64#define COMP 0xc7 /* 0x87 //0x07 */
65#define COMP1 0xc9 /* 0x89 //0x09 */
66
67#define MCK_INIT 0x63
68#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
69
70#define SYS_CLK 0x04
71
Hans de Goededcef3232008-07-10 10:40:53 -030072/* We calculate the autogain at the end of the transfer of a frame, at this
73 moment a frame with the old settings is being transmitted, and a frame is
74 being captured with the old settings. So if we adjust the autogain we must
75 ignore atleast the 2 next frames for the new settings to come into effect
76 before doing any other adjustments */
77#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goedead5ef80d2008-07-14 10:11:42 -030078#define AUTOGAIN_DEADZONE 1000
Hans de Goededcef3232008-07-10 10:40:53 -030079#define DESIRED_AVG_LUM 7000
80
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -030084static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -030090static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030092
93static struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -030094#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030095 {
96 {
97 .id = V4L2_CID_BRIGHTNESS,
98 .type = V4L2_CTRL_TYPE_INTEGER,
99 .name = "Brightness",
100 .minimum = 0,
101 .maximum = 255,
102 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300103#define BRIGHTNESS_DEF 127
104 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300105 },
106 .set = sd_setbrightness,
107 .get = sd_getbrightness,
108 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300109#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300110 {
111 {
Hans de Goededcef3232008-07-10 10:40:53 -0300112 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300113 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300114 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300116 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300118#define GAIN_DEF 127
119#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300120 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121 },
Hans de Goededcef3232008-07-10 10:40:53 -0300122 .set = sd_setgain,
123 .get = sd_getgain,
124 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300125#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300126 {
127 {
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300131#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
132#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300133 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300134 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300135 .step = 1,
136 .default_value = EXPOSURE_DEF,
137 .flags = 0,
138 },
139 .set = sd_setexposure,
140 .get = sd_getexposure,
141 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300142#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300143 {
144 {
145 .id = V4L2_CID_AUTOGAIN,
146 .type = V4L2_CTRL_TYPE_BOOLEAN,
147 .name = "Automatic Gain (and Exposure)",
148 .minimum = 0,
149 .maximum = 1,
150 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300151#define AUTOGAIN_DEF 1
152 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300153 .flags = 0,
154 },
155 .set = sd_setautogain,
156 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300158#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300159 {
160 {
161 .id = V4L2_CID_POWER_LINE_FREQUENCY,
162 .type = V4L2_CTRL_TYPE_MENU,
163 .name = "Light frequency filter",
164 .minimum = 0,
165 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
166 .step = 1,
167#define FREQ_DEF 1
168 .default_value = FREQ_DEF,
169 },
170 .set = sd_setfreq,
171 .get = sd_getfreq,
172 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173};
174
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300175static struct v4l2_pix_format vga_mode[] = {
176 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .bytesperline = 160,
178 .sizeimage = 160 * 120,
179 .colorspace = V4L2_COLORSPACE_SRGB,
180 .priv = 2},
181 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
182 .bytesperline = 320,
183 .sizeimage = 320 * 240,
184 .colorspace = V4L2_COLORSPACE_SRGB,
185 .priv = 1},
186 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
187 .bytesperline = 640,
188 .sizeimage = 640 * 480,
189 .colorspace = V4L2_COLORSPACE_SRGB,
190 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300191};
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300192static struct v4l2_pix_format sif_mode[] = {
193 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
194 .bytesperline = 176,
195 .sizeimage = 176 * 144,
196 .colorspace = V4L2_COLORSPACE_SRGB,
197 .priv = 1},
198 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
199 .bytesperline = 352,
200 .sizeimage = 352 * 288,
201 .colorspace = V4L2_COLORSPACE_SRGB,
202 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300203};
204
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300205static const __u8 initHv7131[] = {
206 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
207 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
209 0x28, 0x1e, 0x60, 0x8a, 0x20,
210 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
211};
212static const __u8 hv7131_sensor_init[][8] = {
213 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
214 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
215 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
216 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
217 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
218};
219static const __u8 initOv6650[] = {
220 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
221 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
223 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
224};
225static const __u8 ov6650_sensor_init[][8] =
226{
227 /* Bright, contrast, etc are set througth SCBB interface.
228 * AVCAP on win2 do not send any data on this controls. */
229 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300230
231 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300232 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300233 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300234 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300235 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
237/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
238 * THIS SET GREEN SCREEN
239 * (pixels could be innverted in decode kind of "brg",
240 * but blue wont be there. Avoid this data ... */
241 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
242 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
243 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300244 /* Enable rgb brightness control */
245 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
246 /* HDG: Note windows uses the line below, which sets both register 0x60
247 and 0x61 I believe these registers of the ov6650 are identical as
248 those of the ov7630, because if this is true the windows settings
249 add a bit additional red gain and a lot additional blue gain, which
250 matches my findings that the windows settings make blue much too
251 blue and red a little too red.
252 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300253 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300254 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
255 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300256};
Hans de Goededcef3232008-07-10 10:40:53 -0300257
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300258static const __u8 initOv7630[] = {
259 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
260 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
261 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
262 0x28, 0x1e, /* H & V sizes r15 .. r16 */
263 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
264 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
265};
266static const __u8 initOv7630_3[] = {
267 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
268 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300269 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300270 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300271 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
272 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
273 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
274 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300275};
Hans de Goede6af492e2008-07-22 07:09:33 -0300276static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300277 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
278 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
279/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300280 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
282 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
283 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
284 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
285 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
286 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
287 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300288 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
289/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300290 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
291 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
292 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
293 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
294 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
295 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
296};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297
298static const __u8 initPas106[] = {
299 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
300 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
302 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
303 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
304};
305/* compression 0x86 mckinit1 0x2b */
306static const __u8 pas106_data[][2] = {
307 {0x02, 0x04}, /* Pixel Clock Divider 6 */
308 {0x03, 0x13}, /* Frame Time MSB */
309/* {0x03, 0x12}, * Frame Time MSB */
310 {0x04, 0x06}, /* Frame Time LSB */
311/* {0x04, 0x05}, * Frame Time LSB */
312 {0x05, 0x65}, /* Shutter Time Line Offset */
313/* {0x05, 0x6d}, * Shutter Time Line Offset */
314/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
315 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
316 {0x07, 0xc1}, /* Black Level Subtract Sign */
317/* {0x07, 0x00}, * Black Level Subtract Sign */
318 {0x08, 0x06}, /* Black Level Subtract Level */
319 {0x08, 0x06}, /* Black Level Subtract Level */
320/* {0x08, 0x01}, * Black Level Subtract Level */
321 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
322 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
323 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
324 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
325 {0x0d, 0x00}, /* Color GainH Pixel */
326 {0x0e, 0x0e}, /* Global Gain */
327 {0x0f, 0x00}, /* Contrast */
328 {0x10, 0x06}, /* H&V synchro polarity */
329 {0x11, 0x06}, /* ?default */
330 {0x12, 0x06}, /* DAC scale */
331 {0x14, 0x02}, /* ?default */
332 {0x13, 0x01}, /* Validate Settings */
333};
334static const __u8 initPas202[] = {
335 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
336 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
338 0x28, 0x1e, 0x28, 0x89, 0x30,
339 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
340};
341static const __u8 pas202_sensor_init[][8] = {
342 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
343 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
344 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
345 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
346 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
347 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
348 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
349 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
350 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
351 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
352 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
353 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
354
355 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
356 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
357 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
358 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
359 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
360 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
361 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
362 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
363};
364
365static const __u8 initTas5110[] = {
366 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
367 0x00, 0x00,
368 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
369 0x16, 0x12, 0x60, 0x86, 0x2b,
370 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
371};
372static const __u8 tas5110_sensor_init[][8] = {
373 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
374 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
375 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
376};
377
378static const __u8 initTas5130[] = {
379 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
380 0x00, 0x00,
381 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
382 0x28, 0x1e, 0x60, COMP, MCK_INIT,
383 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
384};
385static const __u8 tas5130_sensor_init[][8] = {
386/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
387 * shutter 0x47 short exposure? */
388 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
389 /* shutter 0x01 long exposure */
390 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
391};
392
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300393/* get one byte in gspca_dev->usb_buf */
394static void reg_r(struct gspca_dev *gspca_dev,
395 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300396{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300397 usb_control_msg(gspca_dev->dev,
398 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399 0, /* request */
400 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
401 value,
402 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300403 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300404 500);
405}
406
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300407static void reg_w(struct gspca_dev *gspca_dev,
408 __u16 value,
409 const __u8 *buffer,
410 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300411{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300412#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300413 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300414 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
415 return;
416 }
417#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300418 memcpy(gspca_dev->usb_buf, buffer, len);
419 usb_control_msg(gspca_dev->dev,
420 usb_sndctrlpipe(gspca_dev->dev, 0),
421 0x08, /* request */
422 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
423 value,
424 0, /* index */
425 gspca_dev->usb_buf, len,
426 500);
427}
428
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300429static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300430{
431 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432
433 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300434 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435 while (retry--) {
436 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300437 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300438 if (gspca_dev->usb_buf[0] & 0x04) {
439 if (gspca_dev->usb_buf[0] & 0x08)
440 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300441 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300442 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300443 }
444 return -1;
445}
446
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300447static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300448 const __u8 buffer[][8], int len)
449{
450 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300451 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452 len -= 8;
453 if (len <= 0)
454 break;
455 buffer++;
456 }
457}
458
459static void setbrightness(struct gspca_dev *gspca_dev)
460{
461 struct sd *sd = (struct sd *) gspca_dev;
462 __u8 value;
463
464 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300465 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300466 case SENSOR_OV7630: {
467 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300468 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300469
470 /* change reg 0x06 */
Hans de Goedea975a522008-07-16 15:29:11 -0300471 i2cOV[1] = sd->sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300473 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300474 goto err;
475 break;
476 }
477 case SENSOR_PAS106: {
478 __u8 i2c1[] =
479 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
480
481 i2c1[3] = sd->brightness >> 3;
482 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300483 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300484 goto err;
485 i2c1[3] = 0x01;
486 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300487 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 goto err;
489 break;
490 }
491 case SENSOR_PAS202: {
492 /* __u8 i2cpexpo1[] =
493 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
494 __u8 i2cpexpo[] =
495 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
496 __u8 i2cp202[] =
497 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
498 static __u8 i2cpdoit[] =
499 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
500
501 /* change reg 0x10 */
502 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300503/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300505/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300507 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300509 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510 goto err;
511 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300512 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300514 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515 goto err;
516 break;
517 }
Hans de Goededcef3232008-07-10 10:40:53 -0300518 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 __u8 i2c[] =
520 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
521
522 value = 0xff - sd->brightness;
523 i2c[4] = value;
524 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300525 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300526 goto err;
527 break;
528 }
529 }
530 return;
531err:
532 PDEBUG(D_ERR, "i2c error brightness");
533}
Hans de Goededcef3232008-07-10 10:40:53 -0300534
535static void setsensorgain(struct gspca_dev *gspca_dev)
536{
537 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300538 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300539
540 switch (sd->sensor) {
541
542 case SENSOR_TAS5110: {
543 __u8 i2c[] =
544 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
545
Hans de Goedea975a522008-07-16 15:29:11 -0300546 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300548 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300549 break;
550 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300551
Hans de Goedea975a522008-07-16 15:29:11 -0300552 case SENSOR_OV6650:
553 gain >>= 1;
554 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300555 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300556 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300557
Hans de Goedea975a522008-07-16 15:29:11 -0300558 i2c[1] = sd->sensor_addr;
559 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300560 if (i2c_w(gspca_dev, i2c) < 0)
561 goto err;
562 break;
563 }
Hans de Goededcef3232008-07-10 10:40:53 -0300564 }
565 return;
566err:
567 PDEBUG(D_ERR, "i2c error gain");
568}
569
570static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571{
572 struct sd *sd = (struct sd *) gspca_dev;
573 __u8 gain;
574 __u8 rgb_value;
575
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300576 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300577
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 /* red and blue gain */
579 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300580 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 /* green gain */
582 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300583 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300584
585 if (sd->sensor_has_gain)
586 setsensorgain(gspca_dev);
587}
588
589static void setexposure(struct gspca_dev *gspca_dev)
590{
591 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300592
593 switch (sd->sensor) {
594 case SENSOR_TAS5110: {
595 __u8 reg;
596
597 /* register 19's high nibble contains the sn9c10x clock divider
598 The high nibble configures the no fps according to the
599 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300600 reg = 120 * sd->exposure / 1000;
601 if (reg < 2)
602 reg = 2;
603 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300604 reg = 15;
605 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300606 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300607 break;
608 }
Hans de Goedea975a522008-07-16 15:29:11 -0300609 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300610 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300611 /* The ov6650 / ov7630 have 2 registers which both influence
612 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300613 according to: fps = 30 / (low_nibble + 1)
614
615 The fps configures the maximum exposure setting, but it is
616 possible to use less exposure then what the fps maximum
617 allows by setting register 10. register 10 configures the
618 actual exposure as quotient of the full exposure, with 0
619 being no exposure at all (not very usefull) and reg10_max
620 being max exposure possible at that framerate.
621
622 The code maps our 0 - 510 ms exposure ctrl to these 2
623 registers, trying to keep fps as high as possible.
624 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300625 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
626 int reg10, reg11, reg10_max;
627
Hans de Goede66f35822008-07-16 10:16:28 -0300628 /* ov6645 datasheet says reg10_max is 9a, but that uses
629 tline * 2 * reg10 as formula for calculating texpo, the
630 ov6650 probably uses the same formula as the 7730 which uses
631 tline * 4 * reg10, which explains why the reg10max we've
632 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300633 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300634 if (sd->sensor == SENSOR_OV6650) {
635 reg10_max = 0x4d;
636 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
637 } else
638 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300639
640 reg11 = (60 * sd->exposure + 999) / 1000;
641 if (reg11 < 1)
642 reg11 = 1;
643 else if (reg11 > 16)
644 reg11 = 16;
645
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300646 /* In 640x480, if the reg11 has less than 3, the image is
647 unstable (not enough bandwidth). */
648 if (gspca_dev->width == 640 && reg11 < 3)
649 reg11 = 3;
650
Hans de Goedef4d52022008-07-15 09:36:42 -0300651 /* frame exposure time in ms = 1000 * reg11 / 30 ->
652 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
653 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300654
655 /* Don't allow this to get below 10 when using autogain, the
656 steps become very large (relatively) when below 10 causing
657 the image to oscilate from much too dark, to much too bright
658 and back again. */
659 if (sd->autogain && reg10 < 10)
660 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300661 else if (reg10 > reg10_max)
662 reg10 = reg10_max;
663
664 /* Write reg 10 and reg11 low nibble */
Hans de Goedea975a522008-07-16 15:29:11 -0300665 i2c[1] = sd->sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300666 i2c[3] = reg10;
667 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300668
669 /* If register 11 didn't change, don't change it */
670 if (sd->reg11 == reg11 )
671 i2c[0] = 0xa0;
672
673 if (i2c_w(gspca_dev, i2c) == 0)
674 sd->reg11 = reg11;
675 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300676 PDEBUG(D_ERR, "i2c error exposure");
677 break;
678 }
Hans de Goededcef3232008-07-10 10:40:53 -0300679 }
680}
681
Hans de Goede66f35822008-07-16 10:16:28 -0300682static void setfreq(struct gspca_dev *gspca_dev)
683{
684 struct sd *sd = (struct sd *) gspca_dev;
685
686 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300687 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300688 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300689 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300690 compensation, for the ov6650 this is identical to ov6630
691 0x2b register, see ov6630 datasheet.
692 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300693 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300694 switch (sd->freq) {
695 default:
696/* case 0: * no filter*/
697/* case 2: * 60 hz */
698 i2c[3] = 0;
699 break;
700 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300701 i2c[3] = (sd->sensor == SENSOR_OV6650)
702 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300703 break;
704 }
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300705 i2c[1] = sd->sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300706 if (i2c_w(gspca_dev, i2c) < 0)
707 PDEBUG(D_ERR, "i2c error setfreq");
708 break;
709 }
710 }
711}
712
Hans de Goededcef3232008-07-10 10:40:53 -0300713static void do_autogain(struct gspca_dev *gspca_dev)
714{
715 struct sd *sd = (struct sd *) gspca_dev;
716 int avg_lum = atomic_read(&sd->avg_lum);
717
718 if (avg_lum == -1)
719 return;
720
721 if (sd->autogain_ignore_frames > 0)
722 sd->autogain_ignore_frames--;
723 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
724 sd->brightness * DESIRED_AVG_LUM / 127,
Hans de Goedea975a522008-07-16 15:29:11 -0300725 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
726 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
727 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300728 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300729 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730}
731
732/* this function is called at probe time */
733static int sd_config(struct gspca_dev *gspca_dev,
734 const struct usb_device_id *id)
735{
736 struct sd *sd = (struct sd *) gspca_dev;
737 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300738 int sif = 0;
Hans de Goede65f33392008-09-03 17:12:15 -0300739 const __u8 stop = 0x09; /* Disable stream turn of LED */
740
741 reg_r(gspca_dev, 0x00);
742 if (gspca_dev->usb_buf[0] != 0x10)
743 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300745 /* copy the webcam info from the device id */
746 sd->sensor = (id->driver_info >> 24) & 0xff;
747 if (id->driver_info & (F_GAIN << 16))
748 sd->sensor_has_gain = 1;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300749 if (id->driver_info & (F_SIF << 16))
750 sif = 1;
751 if (id->driver_info & (F_H18 << 16))
752 sd->fr_h_sz = 18; /* size of frame header */
753 else
754 sd->fr_h_sz = 12;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300755 gspca_dev->ctrl_dis = (id->driver_info >> 8) & 0xff;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300756 sd->sensor_addr = id->driver_info & 0xff;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757
758 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759 cam->epaddr = 0x01;
760 if (!sif) {
761 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300762 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300763 } else {
764 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300765 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300766 }
Hans de Goededcef3232008-07-10 10:40:53 -0300767 sd->brightness = BRIGHTNESS_DEF;
768 sd->gain = GAIN_DEF;
769 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300770 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
771 sd->autogain = 0; /* Disable do_autogain callback */
772 else
773 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300774 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300775
Hans de Goede65f33392008-09-03 17:12:15 -0300776 /* Disable stream turn of LED */
777 reg_w(gspca_dev, 0x01, &stop, 1);
778
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300779 return 0;
780}
781
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300782/* this function is called at probe and resume time */
783static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300784{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300785 return 0;
786}
787
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300788static void pas106_i2cinit(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789{
790 int i;
791 const __u8 *data;
792 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
793
794 i = ARRAY_SIZE(pas106_data);
795 data = pas106_data[0];
796 while (--i >= 0) {
797 memcpy(&i2c1[2], data, 2);
798 /* copy 2 bytes from the template */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300799 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800 PDEBUG(D_ERR, "i2c error pas106");
801 data += 2;
802 }
803}
804
805/* -- start the camera -- */
806static void sd_start(struct gspca_dev *gspca_dev)
807{
808 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede6af492e2008-07-22 07:09:33 -0300809 int mode, l = 0x1f;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810 const __u8 *sn9c10x;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 __u8 reg17_19[3];
812
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300813 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300814 switch (sd->sensor) {
815 case SENSOR_HV7131R:
816 sn9c10x = initHv7131;
817 reg17_19[0] = 0x60;
818 reg17_19[1] = (mode << 4) | 0x8a;
819 reg17_19[2] = 0x20;
820 break;
821 case SENSOR_OV6650:
822 sn9c10x = initOv6650;
823 reg17_19[0] = 0x68;
824 reg17_19[1] = (mode << 4) | 0x8b;
825 reg17_19[2] = 0x20;
826 break;
827 case SENSOR_OV7630:
Hans de Goede6af492e2008-07-22 07:09:33 -0300828 if (sd->fr_h_sz == 18) { /* SN9C103 */
829 sn9c10x = initOv7630_3;
830 l = sizeof initOv7630_3;
831 } else
832 sn9c10x = initOv7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 reg17_19[0] = 0x68;
834 reg17_19[1] = (mode << 4) | COMP2;
835 reg17_19[2] = MCK_INIT1;
836 break;
837 case SENSOR_PAS106:
838 sn9c10x = initPas106;
839 reg17_19[0] = 0x24; /* 0x28 */
840 reg17_19[1] = (mode << 4) | COMP1;
841 reg17_19[2] = MCK_INIT1;
842 break;
843 case SENSOR_PAS202:
844 sn9c10x = initPas202;
845 reg17_19[0] = mode ? 0x24 : 0x20;
846 reg17_19[1] = (mode << 4) | 0x89;
847 reg17_19[2] = 0x20;
848 break;
849 case SENSOR_TAS5110:
850 sn9c10x = initTas5110;
851 reg17_19[0] = 0x60;
852 reg17_19[1] = (mode << 4) | 0x86;
853 reg17_19[2] = 0x2b; /* 0xf3; */
854 break;
855 default:
856/* case SENSOR_TAS5130CXX: */
857 sn9c10x = initTas5130;
858 reg17_19[0] = 0x60;
859 reg17_19[1] = (mode << 4) | COMP;
860 reg17_19[2] = mode ? 0x23 : 0x43;
861 break;
862 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300863
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300865 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300867 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300869 reg_w(gspca_dev, 0x01, sn9c10x, l);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870 switch (sd->sensor) {
871 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300872 i2c_w_vector(gspca_dev, hv7131_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 sizeof hv7131_sensor_init);
874 break;
875 case SENSOR_OV6650:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300876 i2c_w_vector(gspca_dev, ov6650_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 sizeof ov6650_sensor_init);
878 break;
879 case SENSOR_OV7630:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300880 i2c_w_vector(gspca_dev, ov7630_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881 sizeof ov7630_sensor_init);
Hans de Goede6af492e2008-07-22 07:09:33 -0300882 if (sd->fr_h_sz == 18) { /* SN9C103 */
883 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
884 0x00, 0x00, 0x10 };
885 i2c_w(gspca_dev, i2c);
886 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887 break;
888 case SENSOR_PAS106:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300889 pas106_i2cinit(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 break;
891 case SENSOR_PAS202:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300892 i2c_w_vector(gspca_dev, pas202_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 sizeof pas202_sensor_init);
894 break;
895 case SENSOR_TAS5110:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300896 i2c_w_vector(gspca_dev, tas5110_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300897 sizeof tas5110_sensor_init);
898 break;
899 default:
900/* case SENSOR_TAS5130CXX: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300901 i2c_w_vector(gspca_dev, tas5130_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902 sizeof tas5130_sensor_init);
903 break;
904 }
Hans de Goede3647fea2008-07-15 05:36:30 -0300905 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
906 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 /* compression register */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300908 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300909 /* H_start */
910 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
911 /* V_START */
912 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913 /* reset 0x17 SensorClk enable inv Clk 0x60 */
914 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300915 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Andoni Zubimendi794af522008-07-16 08:33:14 -0300917 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300919 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300921 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 /* Compression */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300923 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924 msleep(20);
925
Hans de Goede6af492e2008-07-22 07:09:33 -0300926 sd->reg11 = -1;
927
Hans de Goededcef3232008-07-10 10:40:53 -0300928 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300930 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300931 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300932
Hans de Goede6af492e2008-07-22 07:09:33 -0300933 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300934 sd->autogain_ignore_frames = 0;
935 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936}
937
938static void sd_stopN(struct gspca_dev *gspca_dev)
939{
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300940 __u8 ByteSend;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941
942 ByteSend = 0x09; /* 0X00 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300943 reg_w(gspca_dev, 0x01, &ByteSend, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944}
945
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946static void sd_pkt_scan(struct gspca_dev *gspca_dev,
947 struct gspca_frame *frame, /* target */
948 unsigned char *data, /* isoc packet */
949 int len) /* iso packet length */
950{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300951 int i;
Hans de Goededcef3232008-07-10 10:40:53 -0300952 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953
Hans de Goedec36260ee2008-07-16 09:56:07 -0300954 /* frames start with:
955 * ff ff 00 c4 c4 96 synchro
956 * 00 (unknown)
957 * xx (frame sequence / size / compression)
958 * (xx) (idem - extra byte for sn9c103)
959 * ll mm brightness sum inside auto exposure
960 * ll mm brightness sum outside auto exposure
961 * (xx xx xx xx xx) audio values for snc103
962 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300964 for (i = 0; i < len - 6; i++) {
965 if (data[0 + i] == 0xff
966 && data[1 + i] == 0xff
967 && data[2 + i] == 0x00
968 && data[3 + i] == 0xc4
969 && data[4 + i] == 0xc4
970 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -0300971 int lum = -1;
972 int pkt_type = LAST_PACKET;
973
Hans de Goedec36260ee2008-07-16 09:56:07 -0300974 if (len - i < sd->fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -0300975 PDEBUG(D_STREAM, "packet too short to"
976 " get avg brightness");
977 } else if (sd->fr_h_sz == 12) {
Hans de Goede6af492e2008-07-22 07:09:33 -0300978 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -0300979 } else {
Hans de Goede6af492e2008-07-22 07:09:33 -0300980 lum = data[i + 9] +
981 (data[i + 10] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -0300982 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300983 if (lum == 0) {
984 lum = -1;
985 sd->frames_to_drop = 2;
986 }
987 atomic_set(&sd->avg_lum, lum);
988
989 if (sd->frames_to_drop) {
990 sd->frames_to_drop--;
991 pkt_type = DISCARD_PACKET;
992 }
993
994 frame = gspca_frame_add(gspca_dev, pkt_type,
995 frame, data, 0);
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -0300996 data += i + sd->fr_h_sz;
997 len -= i + sd->fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998 gspca_frame_add(gspca_dev, FIRST_PACKET,
999 frame, data, len);
1000 return;
1001 }
1002 }
1003 }
1004 gspca_frame_add(gspca_dev, INTER_PACKET,
1005 frame, data, len);
1006}
1007
1008static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1009{
1010 struct sd *sd = (struct sd *) gspca_dev;
1011
1012 sd->brightness = val;
1013 if (gspca_dev->streaming)
1014 setbrightness(gspca_dev);
1015 return 0;
1016}
1017
1018static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1019{
1020 struct sd *sd = (struct sd *) gspca_dev;
1021
1022 *val = sd->brightness;
1023 return 0;
1024}
1025
Hans de Goededcef3232008-07-10 10:40:53 -03001026static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027{
1028 struct sd *sd = (struct sd *) gspca_dev;
1029
Hans de Goededcef3232008-07-10 10:40:53 -03001030 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001032 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001033 return 0;
1034}
1035
Hans de Goededcef3232008-07-10 10:40:53 -03001036static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039
Hans de Goededcef3232008-07-10 10:40:53 -03001040 *val = sd->gain;
1041 return 0;
1042}
1043
1044static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
1048 sd->exposure = val;
1049 if (gspca_dev->streaming)
1050 setexposure(gspca_dev);
1051 return 0;
1052}
1053
1054static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1055{
1056 struct sd *sd = (struct sd *) gspca_dev;
1057
1058 *val = sd->exposure;
1059 return 0;
1060}
1061
1062static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1063{
1064 struct sd *sd = (struct sd *) gspca_dev;
1065
1066 sd->autogain = val;
1067 /* when switching to autogain set defaults to make sure
1068 we are on a valid point of the autogain gain /
1069 exposure knee graph, and give this change time to
1070 take effect before doing autogain. */
1071 if (sd->autogain) {
1072 sd->exposure = EXPOSURE_DEF;
1073 sd->gain = GAIN_DEF;
1074 if (gspca_dev->streaming) {
1075 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1076 setexposure(gspca_dev);
1077 setgain(gspca_dev);
1078 }
1079 }
1080
1081 return 0;
1082}
1083
1084static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089 return 0;
1090}
1091
Hans de Goede66f35822008-07-16 10:16:28 -03001092static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1093{
1094 struct sd *sd = (struct sd *) gspca_dev;
1095
1096 sd->freq = val;
1097 if (gspca_dev->streaming)
1098 setfreq(gspca_dev);
1099 return 0;
1100}
1101
1102static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1103{
1104 struct sd *sd = (struct sd *) gspca_dev;
1105
1106 *val = sd->freq;
1107 return 0;
1108}
1109
1110static int sd_querymenu(struct gspca_dev *gspca_dev,
1111 struct v4l2_querymenu *menu)
1112{
1113 switch (menu->id) {
1114 case V4L2_CID_POWER_LINE_FREQUENCY:
1115 switch (menu->index) {
1116 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1117 strcpy((char *) menu->name, "NoFliker");
1118 return 0;
1119 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1120 strcpy((char *) menu->name, "50 Hz");
1121 return 0;
1122 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1123 strcpy((char *) menu->name, "60 Hz");
1124 return 0;
1125 }
1126 break;
1127 }
1128 return -EINVAL;
1129}
1130
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001131/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001132static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001133 .name = MODULE_NAME,
1134 .ctrls = sd_ctrls,
1135 .nctrls = ARRAY_SIZE(sd_ctrls),
1136 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001137 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001138 .start = sd_start,
1139 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001141 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001142 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001143};
1144
1145/* -- module initialisation -- */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001146#define SFCI(sensor, flags, disable_ctrls, i2c_addr) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001147 .driver_info = (SENSOR_ ## sensor << 24) \
1148 | ((flags) << 16) \
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001149 | ((disable_ctrls) << 8) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001150 | (i2c_addr)
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001151#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
1152#define NO_FREQ (1 << FREQ_IDX)
1153#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
1154
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001155static __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001156#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001157 {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001158 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001159 {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001160 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001161 {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001162 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001163 {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001164 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001165 {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001166 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001167#endif
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001168 {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001169 SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001170#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001171 {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001172 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001173 {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001174 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001175 {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001176 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001177 {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001178 SFCI(PAS202, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001179 {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001180 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001181 {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001182 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001183 {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001184 SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001185 {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001186 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001187 {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001188 SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001189 {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001190 SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001191#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001192 {}
1193};
1194MODULE_DEVICE_TABLE(usb, device_table);
1195
1196/* -- device connect -- */
1197static int sd_probe(struct usb_interface *intf,
1198 const struct usb_device_id *id)
1199{
1200 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1201 THIS_MODULE);
1202}
1203
1204static struct usb_driver sd_driver = {
1205 .name = MODULE_NAME,
1206 .id_table = device_table,
1207 .probe = sd_probe,
1208 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001209#ifdef CONFIG_PM
1210 .suspend = gspca_suspend,
1211 .resume = gspca_resume,
1212#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001213};
1214
1215/* -- module insert / remove -- */
1216static int __init sd_mod_init(void)
1217{
1218 if (usb_register(&sd_driver) < 0)
1219 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001220 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001221 return 0;
1222}
1223static void __exit sd_mod_exit(void)
1224{
1225 usb_deregister(&sd_driver);
1226 PDEBUG(D_PROBE, "deregistered");
1227}
1228
1229module_init(sd_mod_init);
1230module_exit(sd_mod_exit);