blob: 73504a3f87b75ffdbc21e958b00ef0001a7e71a0 [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
Hans de Goede93627732008-09-04 16:20:12 -030023/* Some documentation on known sonixb registers:
24
25Reg Use
260x10 high nibble red gain low nibble blue gain
270x11 low nibble green gain
280x12 hstart
290x13 vstart
300x15 hsize (hsize = register-value * 16)
310x16 vsize (vsize = register-value * 16)
320x17 bit 0 toggle compression quality (according to sn9c102 driver)
330x18 bit 7 enables compression, bit 4-5 set image down scaling:
34 00 scale 1, 01 scale 1/2, 10, scale 1/4
350x19 high-nibble is sensor clock divider, changes exposure on sensors which
36 use a clock generated by the bridge. Some sensors have their own clock.
370x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
380x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
390x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
400x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
41*/
42
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030043#define MODULE_NAME "sonixb"
44
Hans de Goedef65e93d2010-01-31 10:35:15 -030045#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030046#include "gspca.h"
47
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030048MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
49MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
50MODULE_LICENSE("GPL");
51
52/* specific webcam descriptor */
53struct sd {
54 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030055 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030056 int prev_avg_lum;
Hans de Goede26984b02010-02-01 13:18:37 -030057 int exp_too_low_cnt;
58 int exp_too_high_cnt;
Hans de Goede2b3e2842010-12-12 08:55:04 -030059 int header_read;
60 u8 header[12]; /* Header without sof marker */
Hans de Goededcef3232008-07-10 10:40:53 -030061
Hans de Goede26984b02010-02-01 13:18:37 -030062 unsigned short exposure;
Hans de Goedead5ef80d2008-07-14 10:11:42 -030063 unsigned char gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030065 unsigned char autogain;
66 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030067 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030068 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030069
Hans de Goedef45f06b2008-09-03 17:12:21 -030070 __u8 bridge; /* Type of bridge */
71#define BRIDGE_101 0
72#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
73#define BRIDGE_103 1
74
75 __u8 sensor; /* Type of image sensor chip */
Hans de Goede00765f12010-12-12 15:55:03 -030076#define SENSOR_HV7131D 0
77#define SENSOR_HV7131R 1
78#define SENSOR_OV6650 2
79#define SENSOR_OV7630 3
80#define SENSOR_PAS106 4
81#define SENSOR_PAS202 5
82#define SENSOR_TAS5110C 6
83#define SENSOR_TAS5110D 7
84#define SENSOR_TAS5130CXX 8
Hans de Goede6af492e2008-07-22 07:09:33 -030085 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086};
87
Hans de Goedef45f06b2008-09-03 17:12:21 -030088typedef const __u8 sensor_init_t[8];
89
90struct sensor_data {
91 const __u8 *bridge_init[2];
92 int bridge_init_size[2];
93 sensor_init_t *sensor_init;
94 int sensor_init_size;
95 sensor_init_t *sensor_bridge_init[2];
96 int sensor_bridge_init_size[2];
97 int flags;
98 unsigned ctrl_dis;
99 __u8 sensor_addr;
100};
101
102/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300103#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300104#define F_SIF 0x02 /* sif or vga */
Hans de Goede26984b02010-02-01 13:18:37 -0300105#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
Hans de Goedec437d652008-09-03 17:12:22 -0300106
107/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
108#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300109#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300110
111/* ctrl_dis helper macros */
Hans de Goede26984b02010-02-01 13:18:37 -0300112#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
113 (1 << AUTOGAIN_IDX))
Hans de Goedef45f06b2008-09-03 17:12:21 -0300114#define NO_FREQ (1 << FREQ_IDX)
115#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300116
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117#define COMP2 0x8f
118#define COMP 0xc7 /* 0x87 //0x07 */
119#define COMP1 0xc9 /* 0x89 //0x09 */
120
121#define MCK_INIT 0x63
122#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
123
124#define SYS_CLK 0x04
125
Hans de Goedef45f06b2008-09-03 17:12:21 -0300126#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
127 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
128{ \
129 .bridge_init = { bridge_1, bridge_3 }, \
130 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
131 .sensor_init = sensor, \
132 .sensor_init_size = sizeof(sensor), \
133 .sensor_bridge_init = { sensor_1, sensor_3,}, \
134 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
135 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
136}
137
Hans de Goededcef3232008-07-10 10:40:53 -0300138/* We calculate the autogain at the end of the transfer of a frame, at this
Hans de Goede26984b02010-02-01 13:18:37 -0300139 moment a frame with the old settings is being captured and transmitted. So
140 if we adjust the gain or exposure we must ignore atleast the next frame for
141 the new settings to come into effect before doing any other adjustments. */
142#define AUTOGAIN_IGNORE_FRAMES 1
Hans de Goededcef3232008-07-10 10:40:53 -0300143
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300144/* V4L2 controls supported by the driver */
145static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
146static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300147static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
148static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
149static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
150static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
151static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
152static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300153static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
154static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300156static const struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300157#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158 {
159 {
160 .id = V4L2_CID_BRIGHTNESS,
161 .type = V4L2_CTRL_TYPE_INTEGER,
162 .name = "Brightness",
163 .minimum = 0,
164 .maximum = 255,
165 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300166#define BRIGHTNESS_DEF 127
167 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168 },
169 .set = sd_setbrightness,
170 .get = sd_getbrightness,
171 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300172#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173 {
174 {
Hans de Goededcef3232008-07-10 10:40:53 -0300175 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300177 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300179 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300181#define GAIN_DEF 127
Hans de Goede82e839c2010-02-03 14:37:30 -0300182#define GAIN_KNEE 230
Hans de Goededcef3232008-07-10 10:40:53 -0300183 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 },
Hans de Goededcef3232008-07-10 10:40:53 -0300185 .set = sd_setgain,
186 .get = sd_getgain,
187 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300188#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300189 {
190 {
191 .id = V4L2_CID_EXPOSURE,
192 .type = V4L2_CTRL_TYPE_INTEGER,
193 .name = "Exposure",
Hans de Goede421763e2010-02-10 18:57:40 -0300194#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
195#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
Hans de Goededcef3232008-07-10 10:40:53 -0300196 .minimum = 0,
Hans de Goede82e839c2010-02-03 14:37:30 -0300197 .maximum = 1023,
Hans de Goededcef3232008-07-10 10:40:53 -0300198 .step = 1,
199 .default_value = EXPOSURE_DEF,
200 .flags = 0,
201 },
202 .set = sd_setexposure,
203 .get = sd_getexposure,
204 },
Hans de Goede26984b02010-02-01 13:18:37 -0300205#define COARSE_EXPOSURE_IDX 3
206 {
207 {
208 .id = V4L2_CID_EXPOSURE,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "Exposure",
211#define COARSE_EXPOSURE_DEF 2 /* 30 fps */
212 .minimum = 2,
213 .maximum = 15,
214 .step = 1,
215 .default_value = COARSE_EXPOSURE_DEF,
216 .flags = 0,
217 },
218 .set = sd_setexposure,
219 .get = sd_getexposure,
220 },
221#define AUTOGAIN_IDX 4
Hans de Goededcef3232008-07-10 10:40:53 -0300222 {
223 {
224 .id = V4L2_CID_AUTOGAIN,
225 .type = V4L2_CTRL_TYPE_BOOLEAN,
226 .name = "Automatic Gain (and Exposure)",
227 .minimum = 0,
228 .maximum = 1,
229 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300230#define AUTOGAIN_DEF 1
231 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300232 .flags = 0,
233 },
234 .set = sd_setautogain,
235 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 },
Hans de Goede26984b02010-02-01 13:18:37 -0300237#define FREQ_IDX 5
Hans de Goede66f35822008-07-16 10:16:28 -0300238 {
239 {
240 .id = V4L2_CID_POWER_LINE_FREQUENCY,
241 .type = V4L2_CTRL_TYPE_MENU,
242 .name = "Light frequency filter",
243 .minimum = 0,
244 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
245 .step = 1,
Hans de Goede606f8422010-02-10 06:49:23 -0300246#define FREQ_DEF 0
Hans de Goede66f35822008-07-16 10:16:28 -0300247 .default_value = FREQ_DEF,
248 },
249 .set = sd_setfreq,
250 .get = sd_getfreq,
251 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252};
253
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300254static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300255 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
256 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300257 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300258 .colorspace = V4L2_COLORSPACE_SRGB,
259 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300260 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
261 .bytesperline = 160,
Hans de Goede5c515182008-09-03 17:12:22 -0300262 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300263 .colorspace = V4L2_COLORSPACE_SRGB,
264 .priv = 2},
265 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
266 .bytesperline = 320,
Hans de Goede5c515182008-09-03 17:12:22 -0300267 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300268 .colorspace = V4L2_COLORSPACE_SRGB,
269 .priv = 1},
270 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
271 .bytesperline = 640,
Hans de Goede5c515182008-09-03 17:12:22 -0300272 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300273 .colorspace = V4L2_COLORSPACE_SRGB,
274 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300275};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300276static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300277 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
278 .bytesperline = 160,
279 .sizeimage = 160 * 120,
280 .colorspace = V4L2_COLORSPACE_SRGB,
281 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
282 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
283 .bytesperline = 160,
284 .sizeimage = 160 * 120 * 5 / 4,
285 .colorspace = V4L2_COLORSPACE_SRGB,
286 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300287 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
288 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300289 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300290 .colorspace = V4L2_COLORSPACE_SRGB,
291 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300292 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
293 .bytesperline = 176,
Hans de Goede5c515182008-09-03 17:12:22 -0300294 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300295 .colorspace = V4L2_COLORSPACE_SRGB,
296 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300297 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
298 .bytesperline = 320,
299 .sizeimage = 320 * 240 * 5 / 4,
300 .colorspace = V4L2_COLORSPACE_SRGB,
301 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300302 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
303 .bytesperline = 352,
Hans de Goede5c515182008-09-03 17:12:22 -0300304 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300305 .colorspace = V4L2_COLORSPACE_SRGB,
306 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300307};
308
Hans de Goede00765f12010-12-12 15:55:03 -0300309static const __u8 initHv7131d[] = {
310 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
311 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
313 0x28, 0x1e, 0x60, 0x8e, 0x42,
314 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
315};
316static const __u8 hv7131d_sensor_init[][8] = {
317 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
318 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
319 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
320 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
321 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
322};
323
324static const __u8 initHv7131r[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300325 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
326 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300327 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300328 0x28, 0x1e, 0x60, 0x8a, 0x20,
329 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
330};
Hans de Goede00765f12010-12-12 15:55:03 -0300331static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300332 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
333 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
334 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
335 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
336 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
337};
338static const __u8 initOv6650[] = {
339 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
340 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300341 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300342 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300343};
Jean-François Moine780e3122010-10-19 04:29:10 -0300344static const __u8 ov6650_sensor_init[][8] = {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200345 /* Bright, contrast, etc are set through SCBB interface.
Jean-François Moine780e3122010-10-19 04:29:10 -0300346 * AVCAP on win2 do not send any data on this controls. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300347 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300348
349 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300350 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300351 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300352 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300353 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300354 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
355/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
356 * THIS SET GREEN SCREEN
357 * (pixels could be innverted in decode kind of "brg",
358 * but blue wont be there. Avoid this data ... */
359 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
360 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300361 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300362 /* Enable rgb brightness control */
363 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
364 /* HDG: Note windows uses the line below, which sets both register 0x60
365 and 0x61 I believe these registers of the ov6650 are identical as
366 those of the ov7630, because if this is true the windows settings
367 add a bit additional red gain and a lot additional blue gain, which
368 matches my findings that the windows settings make blue much too
369 blue and red a little too red.
370 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300371 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
373 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374};
Hans de Goededcef3232008-07-10 10:40:53 -0300375
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376static const __u8 initOv7630[] = {
377 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
378 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300379 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300380 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300381 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
383};
384static const __u8 initOv7630_3[] = {
385 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300386 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300387 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300388 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300389 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
390 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
391 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
392 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393};
Hans de Goede6af492e2008-07-22 07:09:33 -0300394static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300395 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
396 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
397/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300398 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300399 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
400 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
401 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
402 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
403 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
404 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
405 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300406 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
407/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300408 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
409 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
410 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
411 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
412 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
413 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
414};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300415
Hans de Goedef45f06b2008-09-03 17:12:21 -0300416static const __u8 ov7630_sensor_init_3[][8] = {
417 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
418};
419
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300420static const __u8 initPas106[] = {
421 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
422 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300423 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300424 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300425 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300426};
427/* compression 0x86 mckinit1 0x2b */
Hans de Goede421763e2010-02-10 18:57:40 -0300428
429/* "Known" PAS106B registers:
430 0x02 clock divider
431 0x03 Variable framerate bits 4-11
432 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
433 The variable framerate control must never be set lower then 300,
434 which sets the framerate at 90 / reg02, otherwise vsync is lost.
435 0x05 Shutter Time Line Offset, this can be used as an exposure control:
436 0 = use full frame time, 255 = no exposure at all
437 Note this may never be larger then "var-framerate control" / 2 - 2.
438 When var-framerate control is < 514, no exposure is reached at the max
439 allowed value for the framerate control value, rather then at 255.
440 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
441 only a very little bit, leave at 0xcd
442 0x07 offset sign bit (bit0 1 > negative offset)
443 0x08 offset
444 0x09 Blue Gain
445 0x0a Green1 Gain
446 0x0b Green2 Gain
447 0x0c Red Gain
448 0x0e Global gain
449 0x13 Write 1 to commit settings to sensor
450*/
451
Hans de Goedef45f06b2008-09-03 17:12:21 -0300452static const __u8 pas106_sensor_init[][8] = {
453 /* Pixel Clock Divider 6 */
454 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
455 /* Frame Time MSB (also seen as 0x12) */
456 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
457 /* Frame Time LSB (also seen as 0x05) */
458 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
459 /* Shutter Time Line Offset (also seen as 0x6d) */
460 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
461 /* Shutter Time Pixel Offset (also seen as 0xb1) */
462 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
463 /* Black Level Subtract Sign (also seen 0x00) */
464 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
465 /* Black Level Subtract Level (also seen 0x01) */
466 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
467 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
468 /* Color Gain B Pixel 5 a */
469 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
470 /* Color Gain G1 Pixel 1 5 */
471 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
472 /* Color Gain G2 Pixel 1 0 5 */
473 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
474 /* Color Gain R Pixel 3 1 */
475 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
476 /* Color GainH Pixel */
477 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
478 /* Global Gain */
479 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
480 /* Contrast */
481 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
482 /* H&V synchro polarity */
483 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
484 /* ?default */
485 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
486 /* DAC scale */
487 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
488 /* ?default */
489 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
490 /* Validate Settings */
491 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300492};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300493
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300494static const __u8 initPas202[] = {
495 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
496 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300497 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goede82e839c2010-02-03 14:37:30 -0300498 0x28, 0x1e, 0x20, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
500};
Hans de Goede82e839c2010-02-03 14:37:30 -0300501
502/* "Known" PAS202BCB registers:
503 0x02 clock divider
504 0x04 Variable framerate bits 6-11 (*)
505 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
506 0x07 Blue Gain
507 0x08 Green Gain
508 0x09 Red Gain
509 0x0b offset sign bit (bit0 1 > negative offset)
510 0x0c offset
511 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
512 leave at 1 otherwise we get a jump in our exposure control
513 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
514 0x10 Master gain 0 - 31
515 0x11 write 1 to apply changes
516 (*) The variable framerate control must never be set lower then 500
517 which sets the framerate at 30 / reg02, otherwise vsync is lost.
518*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519static const __u8 pas202_sensor_init[][8] = {
Hans de Goede82e839c2010-02-03 14:37:30 -0300520 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
521 to set it lower, but for some reason the bridge starts missing
522 vsync's then */
523 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
525 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300526 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300527 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
528 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
529 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
530 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
531 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
532 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533};
534
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300535static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
537 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300538 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 0x16, 0x12, 0x60, 0x86, 0x2b,
540 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
541};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300542/* Same as above, except a different hstart */
543static const __u8 initTas5110d[] = {
544 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
545 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300546 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300547 0x16, 0x12, 0x60, 0x86, 0x2b,
548 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
549};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550static const __u8 tas5110_sensor_init[][8] = {
551 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
552 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
553 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
554};
555
556static const __u8 initTas5130[] = {
557 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
558 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300559 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300560 0x28, 0x1e, 0x60, COMP, MCK_INIT,
561 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
562};
563static const __u8 tas5130_sensor_init[][8] = {
Jean-François Moine780e3122010-10-19 04:29:10 -0300564/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 * shutter 0x47 short exposure? */
566 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
567 /* shutter 0x01 long exposure */
568 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
569};
570
Hans Verkuild45b9b82008-09-04 03:33:43 -0300571static struct sensor_data sensor_data[] = {
Hans de Goede00765f12010-12-12 15:55:03 -0300572SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
573SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300574SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300575SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
576 F_GAIN, 0, 0x21),
Hans de Goede421763e2010-02-10 18:57:40 -0300577SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300578 0),
Hans de Goede82e839c2010-02-03 14:37:30 -0300579SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN,
580 NO_FREQ, 0),
Hans de Goede26984b02010-02-01 13:18:37 -0300581SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL,
582 F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
583SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL,
584 F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300585SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
586 0),
587};
588
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300589/* get one byte in gspca_dev->usb_buf */
590static void reg_r(struct gspca_dev *gspca_dev,
591 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300592{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300593 usb_control_msg(gspca_dev->dev,
594 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595 0, /* request */
596 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
597 value,
598 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300599 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600 500);
601}
602
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300603static void reg_w(struct gspca_dev *gspca_dev,
604 __u16 value,
605 const __u8 *buffer,
606 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300608#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300609 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300610 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
611 return;
612 }
613#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300614 memcpy(gspca_dev->usb_buf, buffer, len);
615 usb_control_msg(gspca_dev->dev,
616 usb_sndctrlpipe(gspca_dev->dev, 0),
617 0x08, /* request */
618 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
619 value,
620 0, /* index */
621 gspca_dev->usb_buf, len,
622 500);
623}
624
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300625static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626{
627 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628
629 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300630 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 while (retry--) {
632 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300633 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300634 if (gspca_dev->usb_buf[0] & 0x04) {
635 if (gspca_dev->usb_buf[0] & 0x08)
636 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300638 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 }
640 return -1;
641}
642
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300643static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300644 const __u8 buffer[][8], int len)
645{
646 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300647 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 len -= 8;
649 if (len <= 0)
650 break;
651 buffer++;
652 }
653}
654
655static void setbrightness(struct gspca_dev *gspca_dev)
656{
657 struct sd *sd = (struct sd *) gspca_dev;
658 __u8 value;
659
660 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300661 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 case SENSOR_OV7630: {
663 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300664 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665
666 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300667 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300669 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670 goto err;
671 break;
672 }
Hans de Goede421763e2010-02-10 18:57:40 -0300673 case SENSOR_PAS106:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300674 case SENSOR_PAS202: {
Hans de Goede82e839c2010-02-03 14:37:30 -0300675 __u8 i2cpbright[] =
676 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
Hans de Goede421763e2010-02-10 18:57:40 -0300677 __u8 i2cpdoit[] =
Hans de Goede82e839c2010-02-03 14:37:30 -0300678 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679
Hans de Goede421763e2010-02-10 18:57:40 -0300680 /* PAS106 uses reg 7 and 8 instead of b and c */
681 if (sd->sensor == SENSOR_PAS106) {
682 i2cpbright[2] = 7;
683 i2cpdoit[2] = 0x13;
684 }
685
Hans de Goede82e839c2010-02-03 14:37:30 -0300686 if (sd->brightness < 127) {
687 /* change reg 0x0b, signreg */
688 i2cpbright[3] = 0x01;
689 /* set reg 0x0c, offset */
690 i2cpbright[4] = 127 - sd->brightness;
691 } else
692 i2cpbright[4] = sd->brightness - 127;
693
694 if (i2c_w(gspca_dev, i2cpbright) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300696 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 goto err;
698 break;
699 }
Hans de Goededcef3232008-07-10 10:40:53 -0300700 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 __u8 i2c[] =
702 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
703
704 value = 0xff - sd->brightness;
705 i2c[4] = value;
706 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300707 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708 goto err;
709 break;
710 }
711 }
712 return;
713err:
714 PDEBUG(D_ERR, "i2c error brightness");
715}
Hans de Goededcef3232008-07-10 10:40:53 -0300716
717static void setsensorgain(struct gspca_dev *gspca_dev)
718{
719 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300720 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300721
722 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300723 case SENSOR_HV7131D: {
724 __u8 i2c[] =
725 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
Hans de Goededcef3232008-07-10 10:40:53 -0300726
Hans de Goede00765f12010-12-12 15:55:03 -0300727 i2c[3] = 0x3f - (sd->gain / 4);
728 i2c[4] = 0x3f - (sd->gain / 4);
729 i2c[5] = 0x3f - (sd->gain / 4);
730
731 if (i2c_w(gspca_dev, i2c) < 0)
732 goto err;
733 break;
734 }
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300735 case SENSOR_TAS5110C:
736 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300737 __u8 i2c[] =
738 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
739
Hans de Goedea975a522008-07-16 15:29:11 -0300740 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300741 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300742 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300743 break;
744 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300745
Hans de Goedea975a522008-07-16 15:29:11 -0300746 case SENSOR_OV6650:
747 gain >>= 1;
748 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300749 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300750 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300751
Hans de Goedef45f06b2008-09-03 17:12:21 -0300752 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300753 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300754 if (i2c_w(gspca_dev, i2c) < 0)
755 goto err;
756 break;
757 }
Hans de Goede421763e2010-02-10 18:57:40 -0300758 case SENSOR_PAS106:
Hans de Goede82e839c2010-02-03 14:37:30 -0300759 case SENSOR_PAS202: {
760 __u8 i2cpgain[] =
Hans de Goede421763e2010-02-10 18:57:40 -0300761 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede82e839c2010-02-03 14:37:30 -0300762 __u8 i2cpcolorgain[] =
763 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede421763e2010-02-10 18:57:40 -0300764 __u8 i2cpdoit[] =
765 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
766
767 /* PAS106 uses different regs (and has split green gains) */
768 if (sd->sensor == SENSOR_PAS106) {
769 i2cpgain[2] = 0x0e;
770 i2cpcolorgain[0] = 0xd0;
771 i2cpcolorgain[2] = 0x09;
772 i2cpdoit[2] = 0x13;
773 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300774
775 i2cpgain[3] = sd->gain >> 3;
776 i2cpcolorgain[3] = sd->gain >> 4;
777 i2cpcolorgain[4] = sd->gain >> 4;
778 i2cpcolorgain[5] = sd->gain >> 4;
Hans de Goede421763e2010-02-10 18:57:40 -0300779 i2cpcolorgain[6] = sd->gain >> 4;
Hans de Goede82e839c2010-02-03 14:37:30 -0300780
781 if (i2c_w(gspca_dev, i2cpgain) < 0)
782 goto err;
783 if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
784 goto err;
785 if (i2c_w(gspca_dev, i2cpdoit) < 0)
786 goto err;
787 break;
788 }
Hans de Goededcef3232008-07-10 10:40:53 -0300789 }
790 return;
791err:
792 PDEBUG(D_ERR, "i2c error gain");
793}
794
795static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300796{
797 struct sd *sd = (struct sd *) gspca_dev;
798 __u8 gain;
Hans de Goede4efcfa02010-02-01 07:48:17 -0300799 __u8 buf[2] = { 0, 0 };
800
801 if (sensor_data[sd->sensor].flags & F_GAIN) {
802 /* Use the sensor gain to do the actual gain */
803 setsensorgain(gspca_dev);
804 return;
805 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300807 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300808
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300809 /* red and blue gain */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300810 buf[0] = gain << 4 | gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 /* green gain */
Hans de Goede4efcfa02010-02-01 07:48:17 -0300812 buf[1] = gain;
813 reg_w(gspca_dev, 0x10, buf, 2);
Hans de Goededcef3232008-07-10 10:40:53 -0300814}
815
816static void setexposure(struct gspca_dev *gspca_dev)
817{
818 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300819
820 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300821 case SENSOR_HV7131D: {
822 /* Note the datasheet wrongly says line mode exposure uses reg
823 0x26 and 0x27, testing has shown 0x25 + 0x26 */
824 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
825 /* The HV7131D's exposure goes from 0 - 65535, we scale our
826 exposure of 0-1023 to 0-6138. There are 2 reasons for this:
827 1) This puts our exposure knee of 200 at approx the point
828 where the framerate starts dropping
829 2) At 6138 the framerate has already dropped to 2 fps,
830 going any lower makes little sense */
831 __u16 reg = sd->exposure * 6;
832 i2c[3] = reg >> 8;
833 i2c[4] = reg & 0xff;
834 if (i2c_w(gspca_dev, i2c) != 0)
835 goto err;
836 break;
837 }
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300838 case SENSOR_TAS5110C:
839 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300840 /* register 19's high nibble contains the sn9c10x clock divider
841 The high nibble configures the no fps according to the
842 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goede26984b02010-02-01 13:18:37 -0300843 __u8 reg = sd->exposure;
Hans de Goededcef3232008-07-10 10:40:53 -0300844 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300845 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300846 break;
847 }
Hans de Goedea975a522008-07-16 15:29:11 -0300848 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300849 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300850 /* The ov6650 / ov7630 have 2 registers which both influence
851 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300852 according to: fps = 30 / (low_nibble + 1)
853
854 The fps configures the maximum exposure setting, but it is
855 possible to use less exposure then what the fps maximum
856 allows by setting register 10. register 10 configures the
857 actual exposure as quotient of the full exposure, with 0
858 being no exposure at all (not very usefull) and reg10_max
859 being max exposure possible at that framerate.
860
861 The code maps our 0 - 510 ms exposure ctrl to these 2
862 registers, trying to keep fps as high as possible.
863 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300864 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
865 int reg10, reg11, reg10_max;
866
Hans de Goede66f35822008-07-16 10:16:28 -0300867 /* ov6645 datasheet says reg10_max is 9a, but that uses
868 tline * 2 * reg10 as formula for calculating texpo, the
869 ov6650 probably uses the same formula as the 7730 which uses
870 tline * 4 * reg10, which explains why the reg10max we've
871 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300872 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300873 if (sd->sensor == SENSOR_OV6650) {
874 reg10_max = 0x4d;
875 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
876 } else
877 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300878
Hans de Goede82e839c2010-02-03 14:37:30 -0300879 reg11 = (15 * sd->exposure + 999) / 1000;
Hans de Goedef4d52022008-07-15 09:36:42 -0300880 if (reg11 < 1)
881 reg11 = 1;
882 else if (reg11 > 16)
883 reg11 = 16;
884
Hans de Goede10bb7532010-02-04 06:10:55 -0300885 /* In 640x480, if the reg11 has less than 4, the image is
886 unstable (the bridge goes into a higher compression mode
887 which we have not reverse engineered yet). */
888 if (gspca_dev->width == 640 && reg11 < 4)
889 reg11 = 4;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300890
Hans de Goedef4d52022008-07-15 09:36:42 -0300891 /* frame exposure time in ms = 1000 * reg11 / 30 ->
Hans de Goede82e839c2010-02-03 14:37:30 -0300892 reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
893 reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300894
895 /* Don't allow this to get below 10 when using autogain, the
896 steps become very large (relatively) when below 10 causing
897 the image to oscilate from much too dark, to much too bright
898 and back again. */
899 if (sd->autogain && reg10 < 10)
900 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300901 else if (reg10 > reg10_max)
902 reg10 = reg10_max;
903
904 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300905 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300906 i2c[3] = reg10;
907 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300908
909 /* If register 11 didn't change, don't change it */
Jean-François Moine780e3122010-10-19 04:29:10 -0300910 if (sd->reg11 == reg11)
Hans de Goede6af492e2008-07-22 07:09:33 -0300911 i2c[0] = 0xa0;
912
913 if (i2c_w(gspca_dev, i2c) == 0)
914 sd->reg11 = reg11;
915 else
Hans de Goede82e839c2010-02-03 14:37:30 -0300916 goto err;
917 break;
918 }
919 case SENSOR_PAS202: {
920 __u8 i2cpframerate[] =
921 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
922 __u8 i2cpexpo[] =
923 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
924 const __u8 i2cpdoit[] =
925 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
926 int framerate_ctrl;
927
928 /* The exposure knee for the autogain algorithm is 200
929 (100 ms / 10 fps on other sensors), for values below this
930 use the control for setting the partial frame expose time,
931 above that use variable framerate. This way we run at max
932 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
933 is reached. Using the variable framerate control above 200
934 is better then playing around with both clockdiv + partial
935 frame exposure times (like we are doing with the ov chips),
936 as that sometimes leads to jumps in the exposure control,
937 which are bad for auto exposure. */
938 if (sd->exposure < 200) {
939 i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
940 framerate_ctrl = 500;
941 } else {
942 /* The PAS202's exposure control goes from 0 - 4095,
943 but anything below 500 causes vsync issues, so scale
944 our 200-1023 to 500-4095 */
945 framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
946 500;
947 }
948
949 i2cpframerate[3] = framerate_ctrl >> 6;
950 i2cpframerate[4] = framerate_ctrl & 0x3f;
951 if (i2c_w(gspca_dev, i2cpframerate) < 0)
952 goto err;
953 if (i2c_w(gspca_dev, i2cpexpo) < 0)
954 goto err;
955 if (i2c_w(gspca_dev, i2cpdoit) < 0)
956 goto err;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300957 break;
958 }
Hans de Goede421763e2010-02-10 18:57:40 -0300959 case SENSOR_PAS106: {
960 __u8 i2cpframerate[] =
961 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
962 __u8 i2cpexpo[] =
963 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
964 const __u8 i2cpdoit[] =
965 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
966 int framerate_ctrl;
967
968 /* For values below 150 use partial frame exposure, above
969 that use framerate ctrl */
970 if (sd->exposure < 150) {
971 i2cpexpo[3] = 150 - sd->exposure;
972 framerate_ctrl = 300;
973 } else {
974 /* The PAS106's exposure control goes from 0 - 4095,
975 but anything below 300 causes vsync issues, so scale
976 our 150-1023 to 300-4095 */
977 framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
978 300;
979 }
980
981 i2cpframerate[3] = framerate_ctrl >> 4;
982 i2cpframerate[4] = framerate_ctrl & 0x0f;
983 if (i2c_w(gspca_dev, i2cpframerate) < 0)
984 goto err;
985 if (i2c_w(gspca_dev, i2cpexpo) < 0)
986 goto err;
987 if (i2c_w(gspca_dev, i2cpdoit) < 0)
988 goto err;
989 break;
990 }
Hans de Goededcef3232008-07-10 10:40:53 -0300991 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300992 return;
993err:
994 PDEBUG(D_ERR, "i2c error exposure");
Hans de Goededcef3232008-07-10 10:40:53 -0300995}
996
Hans de Goede66f35822008-07-16 10:16:28 -0300997static void setfreq(struct gspca_dev *gspca_dev)
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000
1001 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -03001002 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -03001003 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -03001004 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -03001005 compensation, for the ov6650 this is identical to ov6630
1006 0x2b register, see ov6630 datasheet.
1007 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -03001008 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -03001009 switch (sd->freq) {
1010 default:
1011/* case 0: * no filter*/
1012/* case 2: * 60 hz */
1013 i2c[3] = 0;
1014 break;
1015 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -03001016 i2c[3] = (sd->sensor == SENSOR_OV6650)
1017 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -03001018 break;
1019 }
Hans de Goedef45f06b2008-09-03 17:12:21 -03001020 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -03001021 if (i2c_w(gspca_dev, i2c) < 0)
1022 PDEBUG(D_ERR, "i2c error setfreq");
1023 break;
1024 }
1025 }
1026}
1027
Hans de Goede26984b02010-02-01 13:18:37 -03001028#include "coarse_expo_autogain.h"
1029
Hans de Goededcef3232008-07-10 10:40:53 -03001030static void do_autogain(struct gspca_dev *gspca_dev)
1031{
Hans de Goede26984b02010-02-01 13:18:37 -03001032 int deadzone, desired_avg_lum, result;
Hans de Goededcef3232008-07-10 10:40:53 -03001033 struct sd *sd = (struct sd *) gspca_dev;
1034 int avg_lum = atomic_read(&sd->avg_lum);
1035
Hans de Goede26984b02010-02-01 13:18:37 -03001036 if (avg_lum == -1 || !sd->autogain)
Hans de Goededcef3232008-07-10 10:40:53 -03001037 return;
1038
Hans de Goede26984b02010-02-01 13:18:37 -03001039 if (sd->autogain_ignore_frames > 0) {
1040 sd->autogain_ignore_frames--;
1041 return;
1042 }
1043
Hans de Goede5017c7b2008-10-22 04:59:29 -03001044 /* SIF / VGA sensors have a different autoexposure area and thus
1045 different avg_lum values for the same picture brightness */
1046 if (sensor_data[sd->sensor].flags & F_SIF) {
Hans de Goede26984b02010-02-01 13:18:37 -03001047 deadzone = 500;
1048 /* SIF sensors tend to overexpose, so keep this small */
1049 desired_avg_lum = 5000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001050 } else {
Hans de Goede26984b02010-02-01 13:18:37 -03001051 deadzone = 1500;
Hans de Goede606f8422010-02-10 06:49:23 -03001052 desired_avg_lum = 18000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001053 }
1054
Hans de Goede26984b02010-02-01 13:18:37 -03001055 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
1056 result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
1057 sd->brightness * desired_avg_lum / 127,
1058 deadzone);
1059 else
1060 result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
1061 sd->brightness * desired_avg_lum / 127,
1062 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1063
1064 if (result) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -03001065 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -03001066 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -03001067 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -03001068 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001069}
1070
1071/* this function is called at probe time */
1072static int sd_config(struct gspca_dev *gspca_dev,
1073 const struct usb_device_id *id)
1074{
1075 struct sd *sd = (struct sd *) gspca_dev;
1076 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -03001077
1078 reg_r(gspca_dev, 0x00);
1079 if (gspca_dev->usb_buf[0] != 0x10)
1080 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001081
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001082 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001083 sd->sensor = id->driver_info >> 8;
1084 sd->bridge = id->driver_info & 0xff;
1085 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001086
1087 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001088 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001090 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 } else {
1092 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001093 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001094 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -03001095 cam->npkt = 36; /* 36 packets per ISOC message */
1096
Hans de Goededcef3232008-07-10 10:40:53 -03001097 sd->brightness = BRIGHTNESS_DEF;
1098 sd->gain = GAIN_DEF;
Hans de Goede26984b02010-02-01 13:18:37 -03001099 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
1100 sd->exposure = COARSE_EXPOSURE_DEF;
1101 gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
1102 } else {
1103 sd->exposure = EXPOSURE_DEF;
1104 gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
1105 }
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001106 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1107 sd->autogain = 0; /* Disable do_autogain callback */
1108 else
1109 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -03001110 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -03001111
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 return 0;
1113}
1114
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001115/* this function is called at probe and resume time */
1116static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001117{
Hans de Goede271315a2008-09-03 17:12:19 -03001118 const __u8 stop = 0x09; /* Disable stream turn of LED */
1119
1120 reg_w(gspca_dev, 0x01, &stop, 1);
1121
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001122 return 0;
1123}
1124
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001125/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001126static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127{
1128 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -03001129 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001130 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001131 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -03001132 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001133
Hans de Goede93627732008-09-04 16:20:12 -03001134 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001135 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
1136 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -03001137 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
1138 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001139 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001140 switch (sd->sensor) {
Hans de Goedef45f06b2008-09-03 17:12:21 -03001141 case SENSOR_TAS5130CXX:
1142 /* probably not mode specific at all most likely the upper
1143 nibble of 0x19 is exposure (clock divider) just as with
1144 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -03001145 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001146 break;
1147 }
Hans de Goedec437d652008-09-03 17:12:22 -03001148 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -03001149 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
1150 reg12_19[6] &= ~0x80;
1151
1152 /* Vga mode emulation on SIF sensor? */
1153 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
1154 reg12_19[0] += 16; /* 0x12: hstart adjust */
1155 reg12_19[1] += 24; /* 0x13: vstart adjust */
1156 reg12_19[3] = 320 / 16; /* 0x15: hsize */
1157 reg12_19[4] = 240 / 16; /* 0x16: vsize */
1158 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001159
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -03001161 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001162 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -03001163 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001164 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -03001165 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001166
1167 /* Init the sensor */
1168 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1169 sensor_data[sd->sensor].sensor_init_size);
1170 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
1171 i2c_w_vector(gspca_dev,
1172 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
1173 sensor_data[sd->sensor].sensor_bridge_init_size[
1174 sd->bridge]);
1175
Hans de Goede82e839c2010-02-03 14:37:30 -03001176 /* Mode specific sensor setup */
1177 switch (sd->sensor) {
1178 case SENSOR_PAS202: {
1179 const __u8 i2cpclockdiv[] =
1180 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1181 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1182 if (mode)
1183 i2c_w(gspca_dev, i2cpclockdiv);
1184 }
1185 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001186 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -03001187 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001188 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -03001189 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001190 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -03001191 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001192 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -03001193 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001194 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1195 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -03001196 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001197 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -03001198 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001200 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001202 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001203 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -03001204 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 msleep(20);
1206
Hans de Goede6af492e2008-07-22 07:09:33 -03001207 sd->reg11 = -1;
1208
Hans de Goededcef3232008-07-10 10:40:53 -03001209 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001211 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -03001212 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001213
Hans de Goede6af492e2008-07-22 07:09:33 -03001214 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001215 sd->autogain_ignore_frames = 0;
Hans de Goede26984b02010-02-01 13:18:37 -03001216 sd->exp_too_high_cnt = 0;
1217 sd->exp_too_low_cnt = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001218 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001219 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001220}
1221
1222static void sd_stopN(struct gspca_dev *gspca_dev)
1223{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001224 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001225}
1226
Hans de Goede2b3e2842010-12-12 08:55:04 -03001227static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001228{
Hans de Goededcef3232008-07-10 10:40:53 -03001229 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede2b3e2842010-12-12 08:55:04 -03001230 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001231
Hans de Goedec36260ee2008-07-16 09:56:07 -03001232 /* frames start with:
1233 * ff ff 00 c4 c4 96 synchro
1234 * 00 (unknown)
1235 * xx (frame sequence / size / compression)
1236 * (xx) (idem - extra byte for sn9c103)
1237 * ll mm brightness sum inside auto exposure
1238 * ll mm brightness sum outside auto exposure
1239 * (xx xx xx xx xx) audio values for snc103
1240 */
Hans de Goede2b3e2842010-12-12 08:55:04 -03001241 for (i = 0; i < len; i++) {
1242 switch (sd->header_read) {
1243 case 0:
1244 if (data[i] == 0xff)
1245 sd->header_read++;
1246 break;
1247 case 1:
1248 if (data[i] == 0xff)
1249 sd->header_read++;
1250 else
1251 sd->header_read = 0;
1252 break;
1253 case 2:
1254 if (data[i] == 0x00)
1255 sd->header_read++;
1256 else if (data[i] != 0xff)
1257 sd->header_read = 0;
1258 break;
1259 case 3:
1260 if (data[i] == 0xc4)
1261 sd->header_read++;
1262 else if (data[i] == 0xff)
1263 sd->header_read = 1;
1264 else
1265 sd->header_read = 0;
1266 break;
1267 case 4:
1268 if (data[i] == 0xc4)
1269 sd->header_read++;
1270 else if (data[i] == 0xff)
1271 sd->header_read = 1;
1272 else
1273 sd->header_read = 0;
1274 break;
1275 case 5:
1276 if (data[i] == 0x96)
1277 sd->header_read++;
1278 else if (data[i] == 0xff)
1279 sd->header_read = 1;
1280 else
1281 sd->header_read = 0;
1282 break;
1283 default:
1284 sd->header[sd->header_read - 6] = data[i];
1285 sd->header_read++;
1286 if (sd->header_read == header_size) {
1287 sd->header_read = 0;
1288 return data + i + 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289 }
1290 }
1291 }
Hans de Goede2b3e2842010-12-12 08:55:04 -03001292 return NULL;
1293}
1294
1295static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1296 u8 *data, /* isoc packet */
1297 int len) /* iso packet length */
1298{
1299 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1300 struct sd *sd = (struct sd *) gspca_dev;
1301 struct cam *cam = &gspca_dev->cam;
1302 u8 *sof;
1303
1304 sof = find_sof(gspca_dev, data, len);
1305 if (sof) {
1306 if (sd->bridge == BRIDGE_103) {
1307 fr_h_sz = 18;
1308 lum_offset = 3;
1309 } else {
1310 fr_h_sz = 12;
1311 lum_offset = 2;
1312 }
1313
1314 len_after_sof = len - (sof - data);
1315 len = (sof - data) - fr_h_sz;
1316 if (len < 0)
1317 len = 0;
1318 }
Hans de Goedec437d652008-09-03 17:12:22 -03001319
1320 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1321 /* In raw mode we sometimes get some garbage after the frame
1322 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001323 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001324 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1325
Jean-François Moineb192ca92010-06-27 03:08:19 -03001326 used = gspca_dev->image_len;
Hans de Goedec437d652008-09-03 17:12:22 -03001327 if (used + len > size)
1328 len = size - used;
1329 }
1330
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001331 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Hans de Goede2b3e2842010-12-12 08:55:04 -03001332
1333 if (sof) {
1334 int lum = sd->header[lum_offset] +
1335 (sd->header[lum_offset + 1] << 8);
1336
1337 /* When exposure changes midway a frame we
1338 get a lum of 0 in this case drop 2 frames
1339 as the frames directly after an exposure
1340 change have an unstable image. Sometimes lum
1341 *really* is 0 (cam used in low light with
1342 low exposure setting), so do not drop frames
1343 if the previous lum was 0 too. */
1344 if (lum == 0 && sd->prev_avg_lum != 0) {
1345 lum = -1;
1346 sd->frames_to_drop = 2;
1347 sd->prev_avg_lum = 0;
1348 } else
1349 sd->prev_avg_lum = lum;
1350 atomic_set(&sd->avg_lum, lum);
1351
1352 if (sd->frames_to_drop)
1353 sd->frames_to_drop--;
1354 else
1355 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1356
1357 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1358 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001359}
1360
1361static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1362{
1363 struct sd *sd = (struct sd *) gspca_dev;
1364
1365 sd->brightness = val;
1366 if (gspca_dev->streaming)
1367 setbrightness(gspca_dev);
1368 return 0;
1369}
1370
1371static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1372{
1373 struct sd *sd = (struct sd *) gspca_dev;
1374
1375 *val = sd->brightness;
1376 return 0;
1377}
1378
Hans de Goededcef3232008-07-10 10:40:53 -03001379static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001380{
1381 struct sd *sd = (struct sd *) gspca_dev;
1382
Hans de Goededcef3232008-07-10 10:40:53 -03001383 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001384 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001385 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001386 return 0;
1387}
1388
Hans de Goededcef3232008-07-10 10:40:53 -03001389static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001390{
1391 struct sd *sd = (struct sd *) gspca_dev;
1392
Hans de Goededcef3232008-07-10 10:40:53 -03001393 *val = sd->gain;
1394 return 0;
1395}
1396
1397static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400
1401 sd->exposure = val;
1402 if (gspca_dev->streaming)
1403 setexposure(gspca_dev);
1404 return 0;
1405}
1406
1407static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1408{
1409 struct sd *sd = (struct sd *) gspca_dev;
1410
1411 *val = sd->exposure;
1412 return 0;
1413}
1414
1415static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1416{
1417 struct sd *sd = (struct sd *) gspca_dev;
1418
1419 sd->autogain = val;
Hans de Goede26984b02010-02-01 13:18:37 -03001420 sd->exp_too_high_cnt = 0;
1421 sd->exp_too_low_cnt = 0;
1422
Hans de Goededcef3232008-07-10 10:40:53 -03001423 /* when switching to autogain set defaults to make sure
1424 we are on a valid point of the autogain gain /
1425 exposure knee graph, and give this change time to
1426 take effect before doing autogain. */
Hans de Goede26984b02010-02-01 13:18:37 -03001427 if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
Hans de Goededcef3232008-07-10 10:40:53 -03001428 sd->exposure = EXPOSURE_DEF;
1429 sd->gain = GAIN_DEF;
1430 if (gspca_dev->streaming) {
1431 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1432 setexposure(gspca_dev);
1433 setgain(gspca_dev);
1434 }
1435 }
1436
1437 return 0;
1438}
1439
1440static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1441{
1442 struct sd *sd = (struct sd *) gspca_dev;
1443
1444 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001445 return 0;
1446}
1447
Hans de Goede66f35822008-07-16 10:16:28 -03001448static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1449{
1450 struct sd *sd = (struct sd *) gspca_dev;
1451
1452 sd->freq = val;
1453 if (gspca_dev->streaming)
1454 setfreq(gspca_dev);
1455 return 0;
1456}
1457
1458static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1459{
1460 struct sd *sd = (struct sd *) gspca_dev;
1461
1462 *val = sd->freq;
1463 return 0;
1464}
1465
1466static int sd_querymenu(struct gspca_dev *gspca_dev,
1467 struct v4l2_querymenu *menu)
1468{
1469 switch (menu->id) {
1470 case V4L2_CID_POWER_LINE_FREQUENCY:
1471 switch (menu->index) {
1472 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1473 strcpy((char *) menu->name, "NoFliker");
1474 return 0;
1475 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1476 strcpy((char *) menu->name, "50 Hz");
1477 return 0;
1478 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1479 strcpy((char *) menu->name, "60 Hz");
1480 return 0;
1481 }
1482 break;
1483 }
1484 return -EINVAL;
1485}
1486
Jean-François Moine28566432010-10-01 07:33:26 -03001487#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001488static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1489 u8 *data, /* interrupt packet data */
1490 int len) /* interrupt packet length */
1491{
1492 int ret = -EINVAL;
1493
1494 if (len == 1 && data[0] == 1) {
1495 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1496 input_sync(gspca_dev->input_dev);
1497 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1498 input_sync(gspca_dev->input_dev);
1499 ret = 0;
1500 }
1501
1502 return ret;
1503}
1504#endif
1505
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001506/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001507static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001508 .name = MODULE_NAME,
1509 .ctrls = sd_ctrls,
1510 .nctrls = ARRAY_SIZE(sd_ctrls),
1511 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001512 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001513 .start = sd_start,
1514 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001515 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001516 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001517 .dq_callback = do_autogain,
Jean-François Moine28566432010-10-01 07:33:26 -03001518#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001519 .int_pkt_scan = sd_int_pkt_scan,
1520#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001521};
1522
1523/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001524#define SB(sensor, bridge) \
1525 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1526
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001527
Márton Németh37b372e2009-12-10 11:31:09 -03001528static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001529 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1530 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001531 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001532 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1533 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001534 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001535#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001536 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1537 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1538 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
Hans de Goede0e4b91c2010-02-10 20:29:43 -03001539#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001540 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1541 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001542 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1543 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001544 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001545 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001546 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001547 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
Hans de Goede4cce1652008-09-04 16:22:57 -03001548 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1549#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1550 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1551#endif
1552 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001553 {}
1554};
1555MODULE_DEVICE_TABLE(usb, device_table);
1556
1557/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001558static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001559 const struct usb_device_id *id)
1560{
1561 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1562 THIS_MODULE);
1563}
1564
1565static struct usb_driver sd_driver = {
1566 .name = MODULE_NAME,
1567 .id_table = device_table,
1568 .probe = sd_probe,
1569 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001570#ifdef CONFIG_PM
1571 .suspend = gspca_suspend,
1572 .resume = gspca_resume,
1573#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001574};
1575
1576/* -- module insert / remove -- */
1577static int __init sd_mod_init(void)
1578{
Jean-François Moine54826432010-09-13 04:53:03 -03001579 return usb_register(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001580}
1581static void __exit sd_mod_exit(void)
1582{
1583 usb_deregister(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001584}
1585
1586module_init(sd_mod_init);
1587module_exit(sd_mod_exit);