blob: 735d4260f2f87d22d461cfb2177cc429eab1ddd6 [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 Moine739570b2008-07-14 09:38:29 -0300413 if (len > sizeof gspca_dev->usb_buf) {
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
429static void reg_w_big(struct gspca_dev *gspca_dev,
430 __u16 value,
431 const __u8 *buffer,
432 int len)
433{
434 __u8 *tmpbuf;
435
436 tmpbuf = kmalloc(len, GFP_KERNEL);
Hans de Goede0d2a7222008-07-03 08:15:22 -0300437 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300438 usb_control_msg(gspca_dev->dev,
439 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300440 0x08, /* request */
441 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
442 value,
443 0, /* index */
Hans de Goede0d2a7222008-07-03 08:15:22 -0300444 tmpbuf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300446 kfree(tmpbuf);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300447}
448
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300449static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450{
451 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300452
453 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300454 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 while (retry--) {
456 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300457 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300458 if (gspca_dev->usb_buf[0] & 0x04) {
459 if (gspca_dev->usb_buf[0] & 0x08)
460 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300462 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463 }
464 return -1;
465}
466
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300467static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 const __u8 buffer[][8], int len)
469{
470 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300471 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300472 len -= 8;
473 if (len <= 0)
474 break;
475 buffer++;
476 }
477}
478
479static void setbrightness(struct gspca_dev *gspca_dev)
480{
481 struct sd *sd = (struct sd *) gspca_dev;
482 __u8 value;
483
484 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300485 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300486 case SENSOR_OV7630: {
487 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300488 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300489
490 /* change reg 0x06 */
Hans de Goedea975a522008-07-16 15:29:11 -0300491 i2cOV[1] = sd->sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300493 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494 goto err;
495 break;
496 }
497 case SENSOR_PAS106: {
498 __u8 i2c1[] =
499 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
500
501 i2c1[3] = sd->brightness >> 3;
502 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300503 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 goto err;
505 i2c1[3] = 0x01;
506 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300507 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 goto err;
509 break;
510 }
511 case SENSOR_PAS202: {
512 /* __u8 i2cpexpo1[] =
513 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
514 __u8 i2cpexpo[] =
515 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
516 __u8 i2cp202[] =
517 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
518 static __u8 i2cpdoit[] =
519 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
520
521 /* change reg 0x10 */
522 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300523/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300525/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300526 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300529 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 goto err;
531 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 goto err;
536 break;
537 }
Hans de Goededcef3232008-07-10 10:40:53 -0300538 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 __u8 i2c[] =
540 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
541
542 value = 0xff - sd->brightness;
543 i2c[4] = value;
544 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300545 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546 goto err;
547 break;
548 }
549 }
550 return;
551err:
552 PDEBUG(D_ERR, "i2c error brightness");
553}
Hans de Goededcef3232008-07-10 10:40:53 -0300554
555static void setsensorgain(struct gspca_dev *gspca_dev)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300558 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300559
560 switch (sd->sensor) {
561
562 case SENSOR_TAS5110: {
563 __u8 i2c[] =
564 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
565
Hans de Goedea975a522008-07-16 15:29:11 -0300566 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300567 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300568 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300569 break;
570 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300571
Hans de Goedea975a522008-07-16 15:29:11 -0300572 case SENSOR_OV6650:
573 gain >>= 1;
574 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300575 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300576 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300577
Hans de Goedea975a522008-07-16 15:29:11 -0300578 i2c[1] = sd->sensor_addr;
579 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300580 if (i2c_w(gspca_dev, i2c) < 0)
581 goto err;
582 break;
583 }
Hans de Goededcef3232008-07-10 10:40:53 -0300584 }
585 return;
586err:
587 PDEBUG(D_ERR, "i2c error gain");
588}
589
590static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591{
592 struct sd *sd = (struct sd *) gspca_dev;
593 __u8 gain;
594 __u8 rgb_value;
595
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300596 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300597
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 /* red and blue gain */
599 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 /* green gain */
602 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300603 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300604
605 if (sd->sensor_has_gain)
606 setsensorgain(gspca_dev);
607}
608
609static void setexposure(struct gspca_dev *gspca_dev)
610{
611 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300612
613 switch (sd->sensor) {
614 case SENSOR_TAS5110: {
615 __u8 reg;
616
617 /* register 19's high nibble contains the sn9c10x clock divider
618 The high nibble configures the no fps according to the
619 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300620 reg = 120 * sd->exposure / 1000;
621 if (reg < 2)
622 reg = 2;
623 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300624 reg = 15;
625 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300627 break;
628 }
Hans de Goedea975a522008-07-16 15:29:11 -0300629 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300630 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300631 /* The ov6650 / ov7630 have 2 registers which both influence
632 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300633 according to: fps = 30 / (low_nibble + 1)
634
635 The fps configures the maximum exposure setting, but it is
636 possible to use less exposure then what the fps maximum
637 allows by setting register 10. register 10 configures the
638 actual exposure as quotient of the full exposure, with 0
639 being no exposure at all (not very usefull) and reg10_max
640 being max exposure possible at that framerate.
641
642 The code maps our 0 - 510 ms exposure ctrl to these 2
643 registers, trying to keep fps as high as possible.
644 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300645 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
646 int reg10, reg11, reg10_max;
647
Hans de Goede66f35822008-07-16 10:16:28 -0300648 /* ov6645 datasheet says reg10_max is 9a, but that uses
649 tline * 2 * reg10 as formula for calculating texpo, the
650 ov6650 probably uses the same formula as the 7730 which uses
651 tline * 4 * reg10, which explains why the reg10max we've
652 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300653 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300654 if (sd->sensor == SENSOR_OV6650) {
655 reg10_max = 0x4d;
656 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
657 } else
658 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300659
660 reg11 = (60 * sd->exposure + 999) / 1000;
661 if (reg11 < 1)
662 reg11 = 1;
663 else if (reg11 > 16)
664 reg11 = 16;
665
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300666 /* In 640x480, if the reg11 has less than 3, the image is
667 unstable (not enough bandwidth). */
668 if (gspca_dev->width == 640 && reg11 < 3)
669 reg11 = 3;
670
Hans de Goedef4d52022008-07-15 09:36:42 -0300671 /* frame exposure time in ms = 1000 * reg11 / 30 ->
672 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
673 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300674
675 /* Don't allow this to get below 10 when using autogain, the
676 steps become very large (relatively) when below 10 causing
677 the image to oscilate from much too dark, to much too bright
678 and back again. */
679 if (sd->autogain && reg10 < 10)
680 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300681 else if (reg10 > reg10_max)
682 reg10 = reg10_max;
683
684 /* Write reg 10 and reg11 low nibble */
Hans de Goedea975a522008-07-16 15:29:11 -0300685 i2c[1] = sd->sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300686 i2c[3] = reg10;
687 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300688
689 /* If register 11 didn't change, don't change it */
690 if (sd->reg11 == reg11 )
691 i2c[0] = 0xa0;
692
693 if (i2c_w(gspca_dev, i2c) == 0)
694 sd->reg11 = reg11;
695 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300696 PDEBUG(D_ERR, "i2c error exposure");
697 break;
698 }
Hans de Goededcef3232008-07-10 10:40:53 -0300699 }
700}
701
Hans de Goede66f35822008-07-16 10:16:28 -0300702static void setfreq(struct gspca_dev *gspca_dev)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300707 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300708 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300709 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300710 compensation, for the ov6650 this is identical to ov6630
711 0x2b register, see ov6630 datasheet.
712 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300713 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300714 switch (sd->freq) {
715 default:
716/* case 0: * no filter*/
717/* case 2: * 60 hz */
718 i2c[3] = 0;
719 break;
720 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300721 i2c[3] = (sd->sensor == SENSOR_OV6650)
722 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300723 break;
724 }
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300725 i2c[1] = sd->sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300726 if (i2c_w(gspca_dev, i2c) < 0)
727 PDEBUG(D_ERR, "i2c error setfreq");
728 break;
729 }
730 }
731}
732
Hans de Goededcef3232008-07-10 10:40:53 -0300733static void do_autogain(struct gspca_dev *gspca_dev)
734{
735 struct sd *sd = (struct sd *) gspca_dev;
736 int avg_lum = atomic_read(&sd->avg_lum);
737
738 if (avg_lum == -1)
739 return;
740
741 if (sd->autogain_ignore_frames > 0)
742 sd->autogain_ignore_frames--;
743 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
744 sd->brightness * DESIRED_AVG_LUM / 127,
Hans de Goedea975a522008-07-16 15:29:11 -0300745 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
746 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
747 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300748 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300749 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750}
751
752/* this function is called at probe time */
753static int sd_config(struct gspca_dev *gspca_dev,
754 const struct usb_device_id *id)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 int sif = 0;
759
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300760 /* copy the webcam info from the device id */
761 sd->sensor = (id->driver_info >> 24) & 0xff;
762 if (id->driver_info & (F_GAIN << 16))
763 sd->sensor_has_gain = 1;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300764 if (id->driver_info & (F_SIF << 16))
765 sif = 1;
766 if (id->driver_info & (F_H18 << 16))
767 sd->fr_h_sz = 18; /* size of frame header */
768 else
769 sd->fr_h_sz = 12;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300770 gspca_dev->ctrl_dis = (id->driver_info >> 8) & 0xff;
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300771 sd->sensor_addr = id->driver_info & 0xff;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300772
773 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774 cam->epaddr = 0x01;
775 if (!sif) {
776 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300777 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778 } else {
779 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300780 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 }
Hans de Goededcef3232008-07-10 10:40:53 -0300782 sd->brightness = BRIGHTNESS_DEF;
783 sd->gain = GAIN_DEF;
784 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300785 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
786 sd->autogain = 0; /* Disable do_autogain callback */
787 else
788 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300789 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300790
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 return 0;
792}
793
794/* this function is called at open time */
795static int sd_open(struct gspca_dev *gspca_dev)
796{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300797 reg_r(gspca_dev, 0x00);
798 if (gspca_dev->usb_buf[0] != 0x10)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300799 return -ENODEV;
800 return 0;
801}
802
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300803static void pas106_i2cinit(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300804{
805 int i;
806 const __u8 *data;
807 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
808
809 i = ARRAY_SIZE(pas106_data);
810 data = pas106_data[0];
811 while (--i >= 0) {
812 memcpy(&i2c1[2], data, 2);
813 /* copy 2 bytes from the template */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300814 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300815 PDEBUG(D_ERR, "i2c error pas106");
816 data += 2;
817 }
818}
819
820/* -- start the camera -- */
821static void sd_start(struct gspca_dev *gspca_dev)
822{
823 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede6af492e2008-07-22 07:09:33 -0300824 int mode, l = 0x1f;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300825 const __u8 *sn9c10x;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826 __u8 reg17_19[3];
827
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300828 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 switch (sd->sensor) {
830 case SENSOR_HV7131R:
831 sn9c10x = initHv7131;
832 reg17_19[0] = 0x60;
833 reg17_19[1] = (mode << 4) | 0x8a;
834 reg17_19[2] = 0x20;
835 break;
836 case SENSOR_OV6650:
837 sn9c10x = initOv6650;
838 reg17_19[0] = 0x68;
839 reg17_19[1] = (mode << 4) | 0x8b;
840 reg17_19[2] = 0x20;
841 break;
842 case SENSOR_OV7630:
Hans de Goede6af492e2008-07-22 07:09:33 -0300843 if (sd->fr_h_sz == 18) { /* SN9C103 */
844 sn9c10x = initOv7630_3;
845 l = sizeof initOv7630_3;
846 } else
847 sn9c10x = initOv7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 reg17_19[0] = 0x68;
849 reg17_19[1] = (mode << 4) | COMP2;
850 reg17_19[2] = MCK_INIT1;
851 break;
852 case SENSOR_PAS106:
853 sn9c10x = initPas106;
854 reg17_19[0] = 0x24; /* 0x28 */
855 reg17_19[1] = (mode << 4) | COMP1;
856 reg17_19[2] = MCK_INIT1;
857 break;
858 case SENSOR_PAS202:
859 sn9c10x = initPas202;
860 reg17_19[0] = mode ? 0x24 : 0x20;
861 reg17_19[1] = (mode << 4) | 0x89;
862 reg17_19[2] = 0x20;
863 break;
864 case SENSOR_TAS5110:
865 sn9c10x = initTas5110;
866 reg17_19[0] = 0x60;
867 reg17_19[1] = (mode << 4) | 0x86;
868 reg17_19[2] = 0x2b; /* 0xf3; */
869 break;
870 default:
871/* case SENSOR_TAS5130CXX: */
872 sn9c10x = initTas5130;
873 reg17_19[0] = 0x60;
874 reg17_19[1] = (mode << 4) | COMP;
875 reg17_19[2] = mode ? 0x23 : 0x43;
876 break;
877 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300878
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300880 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300882 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883 /* Set the registers from the template */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300884 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 switch (sd->sensor) {
886 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300887 i2c_w_vector(gspca_dev, hv7131_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 sizeof hv7131_sensor_init);
889 break;
890 case SENSOR_OV6650:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300891 i2c_w_vector(gspca_dev, ov6650_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300892 sizeof ov6650_sensor_init);
893 break;
894 case SENSOR_OV7630:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300895 i2c_w_vector(gspca_dev, ov7630_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896 sizeof ov7630_sensor_init);
Hans de Goede6af492e2008-07-22 07:09:33 -0300897 if (sd->fr_h_sz == 18) { /* SN9C103 */
898 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
899 0x00, 0x00, 0x10 };
900 i2c_w(gspca_dev, i2c);
901 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902 break;
903 case SENSOR_PAS106:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300904 pas106_i2cinit(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 break;
906 case SENSOR_PAS202:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300907 i2c_w_vector(gspca_dev, pas202_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 sizeof pas202_sensor_init);
909 break;
910 case SENSOR_TAS5110:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300911 i2c_w_vector(gspca_dev, tas5110_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 sizeof tas5110_sensor_init);
913 break;
914 default:
915/* case SENSOR_TAS5130CXX: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300916 i2c_w_vector(gspca_dev, tas5130_sensor_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 sizeof tas5130_sensor_init);
918 break;
919 }
Hans de Goede3647fea2008-07-15 05:36:30 -0300920 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
921 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 /* compression register */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300923 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300924 /* H_start */
925 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
926 /* V_START */
927 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 /* reset 0x17 SensorClk enable inv Clk 0x60 */
929 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300930 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Andoni Zubimendi794af522008-07-16 08:33:14 -0300932 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300934 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300936 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 /* Compression */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300938 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939 msleep(20);
940
Hans de Goede6af492e2008-07-22 07:09:33 -0300941 sd->reg11 = -1;
942
Hans de Goededcef3232008-07-10 10:40:53 -0300943 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300945 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300946 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300947
Hans de Goede6af492e2008-07-22 07:09:33 -0300948 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300949 sd->autogain_ignore_frames = 0;
950 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951}
952
953static void sd_stopN(struct gspca_dev *gspca_dev)
954{
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300955 __u8 ByteSend;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956
957 ByteSend = 0x09; /* 0X00 */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300958 reg_w(gspca_dev, 0x01, &ByteSend, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959}
960
961static void sd_stop0(struct gspca_dev *gspca_dev)
962{
963}
964
965static void sd_close(struct gspca_dev *gspca_dev)
966{
967}
968
969static void sd_pkt_scan(struct gspca_dev *gspca_dev,
970 struct gspca_frame *frame, /* target */
971 unsigned char *data, /* isoc packet */
972 int len) /* iso packet length */
973{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300974 int i;
Hans de Goededcef3232008-07-10 10:40:53 -0300975 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300976
Hans de Goedec36260ee2008-07-16 09:56:07 -0300977 /* frames start with:
978 * ff ff 00 c4 c4 96 synchro
979 * 00 (unknown)
980 * xx (frame sequence / size / compression)
981 * (xx) (idem - extra byte for sn9c103)
982 * ll mm brightness sum inside auto exposure
983 * ll mm brightness sum outside auto exposure
984 * (xx xx xx xx xx) audio values for snc103
985 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300986 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300987 for (i = 0; i < len - 6; i++) {
988 if (data[0 + i] == 0xff
989 && data[1 + i] == 0xff
990 && data[2 + i] == 0x00
991 && data[3 + i] == 0xc4
992 && data[4 + i] == 0xc4
993 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -0300994 int lum = -1;
995 int pkt_type = LAST_PACKET;
996
Hans de Goedec36260ee2008-07-16 09:56:07 -0300997 if (len - i < sd->fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -0300998 PDEBUG(D_STREAM, "packet too short to"
999 " get avg brightness");
1000 } else if (sd->fr_h_sz == 12) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001001 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001002 } else {
Hans de Goede6af492e2008-07-22 07:09:33 -03001003 lum = data[i + 9] +
1004 (data[i + 10] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001005 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001006 if (lum == 0) {
1007 lum = -1;
1008 sd->frames_to_drop = 2;
1009 }
1010 atomic_set(&sd->avg_lum, lum);
1011
1012 if (sd->frames_to_drop) {
1013 sd->frames_to_drop--;
1014 pkt_type = DISCARD_PACKET;
1015 }
1016
1017 frame = gspca_frame_add(gspca_dev, pkt_type,
1018 frame, data, 0);
Andoni Zubimendi553b9fa2008-07-06 07:27:19 -03001019 data += i + sd->fr_h_sz;
1020 len -= i + sd->fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 gspca_frame_add(gspca_dev, FIRST_PACKET,
1022 frame, data, len);
1023 return;
1024 }
1025 }
1026 }
1027 gspca_frame_add(gspca_dev, INTER_PACKET,
1028 frame, data, len);
1029}
1030
1031static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1032{
1033 struct sd *sd = (struct sd *) gspca_dev;
1034
1035 sd->brightness = val;
1036 if (gspca_dev->streaming)
1037 setbrightness(gspca_dev);
1038 return 0;
1039}
1040
1041static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
1044
1045 *val = sd->brightness;
1046 return 0;
1047}
1048
Hans de Goededcef3232008-07-10 10:40:53 -03001049static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052
Hans de Goededcef3232008-07-10 10:40:53 -03001053 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001055 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 return 0;
1057}
1058
Hans de Goededcef3232008-07-10 10:40:53 -03001059static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001060{
1061 struct sd *sd = (struct sd *) gspca_dev;
1062
Hans de Goededcef3232008-07-10 10:40:53 -03001063 *val = sd->gain;
1064 return 0;
1065}
1066
1067static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1068{
1069 struct sd *sd = (struct sd *) gspca_dev;
1070
1071 sd->exposure = val;
1072 if (gspca_dev->streaming)
1073 setexposure(gspca_dev);
1074 return 0;
1075}
1076
1077static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080
1081 *val = sd->exposure;
1082 return 0;
1083}
1084
1085static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1086{
1087 struct sd *sd = (struct sd *) gspca_dev;
1088
1089 sd->autogain = val;
1090 /* when switching to autogain set defaults to make sure
1091 we are on a valid point of the autogain gain /
1092 exposure knee graph, and give this change time to
1093 take effect before doing autogain. */
1094 if (sd->autogain) {
1095 sd->exposure = EXPOSURE_DEF;
1096 sd->gain = GAIN_DEF;
1097 if (gspca_dev->streaming) {
1098 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1099 setexposure(gspca_dev);
1100 setgain(gspca_dev);
1101 }
1102 }
1103
1104 return 0;
1105}
1106
1107static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110
1111 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 return 0;
1113}
1114
Hans de Goede66f35822008-07-16 10:16:28 -03001115static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1116{
1117 struct sd *sd = (struct sd *) gspca_dev;
1118
1119 sd->freq = val;
1120 if (gspca_dev->streaming)
1121 setfreq(gspca_dev);
1122 return 0;
1123}
1124
1125static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1126{
1127 struct sd *sd = (struct sd *) gspca_dev;
1128
1129 *val = sd->freq;
1130 return 0;
1131}
1132
1133static int sd_querymenu(struct gspca_dev *gspca_dev,
1134 struct v4l2_querymenu *menu)
1135{
1136 switch (menu->id) {
1137 case V4L2_CID_POWER_LINE_FREQUENCY:
1138 switch (menu->index) {
1139 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1140 strcpy((char *) menu->name, "NoFliker");
1141 return 0;
1142 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1143 strcpy((char *) menu->name, "50 Hz");
1144 return 0;
1145 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1146 strcpy((char *) menu->name, "60 Hz");
1147 return 0;
1148 }
1149 break;
1150 }
1151 return -EINVAL;
1152}
1153
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001154/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001155static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001156 .name = MODULE_NAME,
1157 .ctrls = sd_ctrls,
1158 .nctrls = ARRAY_SIZE(sd_ctrls),
1159 .config = sd_config,
1160 .open = sd_open,
1161 .start = sd_start,
1162 .stopN = sd_stopN,
1163 .stop0 = sd_stop0,
1164 .close = sd_close,
1165 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001166 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001167 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001168};
1169
1170/* -- module initialisation -- */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001171#define SFCI(sensor, flags, disable_ctrls, i2c_addr) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001172 .driver_info = (SENSOR_ ## sensor << 24) \
1173 | ((flags) << 16) \
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001174 | ((disable_ctrls) << 8) \
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001175 | (i2c_addr)
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001176#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
1177#define NO_FREQ (1 << FREQ_IDX)
1178#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
1179
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180static __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001181#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001182 {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001183 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001184 {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001185 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001186 {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001187 SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001188 {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001189 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001190 {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001191 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001192#endif
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001193 {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001194 SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001195#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001196 {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001197 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001198 {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001199 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001200 {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001201 SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001202 {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001203 SFCI(PAS202, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001204 {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001205 SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001206 {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001207 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001208 {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001209 SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001210 {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001211 SFCI(OV7630, F_GAIN, 0, 0x21)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001212 {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001213 SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)},
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001214 {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001215 SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001216#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 {}
1218};
1219MODULE_DEVICE_TABLE(usb, device_table);
1220
1221/* -- device connect -- */
1222static int sd_probe(struct usb_interface *intf,
1223 const struct usb_device_id *id)
1224{
1225 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1226 THIS_MODULE);
1227}
1228
1229static struct usb_driver sd_driver = {
1230 .name = MODULE_NAME,
1231 .id_table = device_table,
1232 .probe = sd_probe,
1233 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001234#ifdef CONFIG_PM
1235 .suspend = gspca_suspend,
1236 .resume = gspca_resume,
1237#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238};
1239
1240/* -- module insert / remove -- */
1241static int __init sd_mod_init(void)
1242{
1243 if (usb_register(&sd_driver) < 0)
1244 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001245 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001246 return 0;
1247}
1248static void __exit sd_mod_exit(void)
1249{
1250 usb_deregister(&sd_driver);
1251 PDEBUG(D_PROBE, "deregistered");
1252}
1253
1254module_init(sd_mod_init);
1255module_exit(sd_mod_exit);