blob: 5c8420e5c02e5ed6803880ae7793a00fb503d627 [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
Hans de Goede0a76cb82011-01-05 13:55:43 -030026sn9c101 / sn9c102:
Hans de Goede93627732008-09-04 16:20:12 -0300270x10 high nibble red gain low nibble blue gain
280x11 low nibble green gain
Hans de Goede0a76cb82011-01-05 13:55:43 -030029sn9c103:
300x05 red gain 0-127
310x06 blue gain 0-127
320x07 green gain 0-127
33all:
340x08-0x0f i2c / 3wire registers
Hans de Goede93627732008-09-04 16:20:12 -0300350x12 hstart
360x13 vstart
370x15 hsize (hsize = register-value * 16)
380x16 vsize (vsize = register-value * 16)
390x17 bit 0 toggle compression quality (according to sn9c102 driver)
400x18 bit 7 enables compression, bit 4-5 set image down scaling:
41 00 scale 1, 01 scale 1/2, 10, scale 1/4
420x19 high-nibble is sensor clock divider, changes exposure on sensors which
43 use a clock generated by the bridge. Some sensors have their own clock.
440x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
450x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
460x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
470x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
48*/
49
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030050#define MODULE_NAME "sonixb"
51
Hans de Goedef65e93d2010-01-31 10:35:15 -030052#include <linux/input.h>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053#include "gspca.h"
54
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
56MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
57MODULE_LICENSE("GPL");
58
59/* specific webcam descriptor */
60struct sd {
61 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030062 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030063 int prev_avg_lum;
Hans de Goede26984b02010-02-01 13:18:37 -030064 int exp_too_low_cnt;
65 int exp_too_high_cnt;
Hans de Goede2b3e2842010-12-12 08:55:04 -030066 int header_read;
67 u8 header[12]; /* Header without sof marker */
Hans de Goededcef3232008-07-10 10:40:53 -030068
Hans de Goede26984b02010-02-01 13:18:37 -030069 unsigned short exposure;
Hans de Goedead5ef80d2008-07-14 10:11:42 -030070 unsigned char gain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030071 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030072 unsigned char autogain;
73 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030074 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030075 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076
Hans de Goedef45f06b2008-09-03 17:12:21 -030077 __u8 bridge; /* Type of bridge */
78#define BRIDGE_101 0
79#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
80#define BRIDGE_103 1
81
82 __u8 sensor; /* Type of image sensor chip */
Hans de Goede00765f12010-12-12 15:55:03 -030083#define SENSOR_HV7131D 0
84#define SENSOR_HV7131R 1
85#define SENSOR_OV6650 2
86#define SENSOR_OV7630 3
87#define SENSOR_PAS106 4
88#define SENSOR_PAS202 5
89#define SENSOR_TAS5110C 6
90#define SENSOR_TAS5110D 7
91#define SENSOR_TAS5130CXX 8
Hans de Goede6af492e2008-07-22 07:09:33 -030092 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093};
94
Hans de Goedef45f06b2008-09-03 17:12:21 -030095typedef const __u8 sensor_init_t[8];
96
97struct sensor_data {
Hans de Goede0a76cb82011-01-05 13:55:43 -030098 const __u8 *bridge_init;
Hans de Goedef45f06b2008-09-03 17:12:21 -030099 sensor_init_t *sensor_init;
100 int sensor_init_size;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300101 int flags;
102 unsigned ctrl_dis;
103 __u8 sensor_addr;
104};
105
106/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300107#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300108#define F_SIF 0x02 /* sif or vga */
Hans de Goede26984b02010-02-01 13:18:37 -0300109#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
Hans de Goedec437d652008-09-03 17:12:22 -0300110
111/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
112#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300113#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300114
115/* ctrl_dis helper macros */
Hans de Goede26984b02010-02-01 13:18:37 -0300116#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
117 (1 << AUTOGAIN_IDX))
Hans de Goedef45f06b2008-09-03 17:12:21 -0300118#define NO_FREQ (1 << FREQ_IDX)
119#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300120
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121#define COMP 0xc7 /* 0x87 //0x07 */
122#define COMP1 0xc9 /* 0x89 //0x09 */
123
124#define MCK_INIT 0x63
125#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
126
127#define SYS_CLK 0x04
128
Hans de Goede0a76cb82011-01-05 13:55:43 -0300129#define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300130{ \
Hans de Goede0a76cb82011-01-05 13:55:43 -0300131 .bridge_init = bridge, \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300132 .sensor_init = sensor, \
133 .sensor_init_size = sizeof(sensor), \
Hans de Goedef45f06b2008-09-03 17:12:21 -0300134 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
135}
136
Hans de Goededcef3232008-07-10 10:40:53 -0300137/* We calculate the autogain at the end of the transfer of a frame, at this
Hans de Goede26984b02010-02-01 13:18:37 -0300138 moment a frame with the old settings is being captured and transmitted. So
139 if we adjust the gain or exposure we must ignore atleast the next frame for
140 the new settings to come into effect before doing any other adjustments. */
141#define AUTOGAIN_IGNORE_FRAMES 1
Hans de Goededcef3232008-07-10 10:40:53 -0300142
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300143/* V4L2 controls supported by the driver */
144static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
145static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300146static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
147static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
148static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
149static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
150static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
151static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300152static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
153static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300155static const struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300156#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157 {
158 {
159 .id = V4L2_CID_BRIGHTNESS,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Brightness",
162 .minimum = 0,
163 .maximum = 255,
164 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300165#define BRIGHTNESS_DEF 127
166 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167 },
168 .set = sd_setbrightness,
169 .get = sd_getbrightness,
170 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300171#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 {
173 {
Hans de Goededcef3232008-07-10 10:40:53 -0300174 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300176 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300178 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300180#define GAIN_DEF 127
Hans de Goede82e839c2010-02-03 14:37:30 -0300181#define GAIN_KNEE 230
Hans de Goededcef3232008-07-10 10:40:53 -0300182 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300183 },
Hans de Goededcef3232008-07-10 10:40:53 -0300184 .set = sd_setgain,
185 .get = sd_getgain,
186 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300187#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300188 {
189 {
190 .id = V4L2_CID_EXPOSURE,
191 .type = V4L2_CTRL_TYPE_INTEGER,
192 .name = "Exposure",
Hans de Goede421763e2010-02-10 18:57:40 -0300193#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
194#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
Hans de Goededcef3232008-07-10 10:40:53 -0300195 .minimum = 0,
Hans de Goede82e839c2010-02-03 14:37:30 -0300196 .maximum = 1023,
Hans de Goededcef3232008-07-10 10:40:53 -0300197 .step = 1,
198 .default_value = EXPOSURE_DEF,
199 .flags = 0,
200 },
201 .set = sd_setexposure,
202 .get = sd_getexposure,
203 },
Hans de Goede26984b02010-02-01 13:18:37 -0300204#define COARSE_EXPOSURE_IDX 3
205 {
206 {
207 .id = V4L2_CID_EXPOSURE,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209 .name = "Exposure",
210#define COARSE_EXPOSURE_DEF 2 /* 30 fps */
211 .minimum = 2,
212 .maximum = 15,
213 .step = 1,
214 .default_value = COARSE_EXPOSURE_DEF,
215 .flags = 0,
216 },
217 .set = sd_setexposure,
218 .get = sd_getexposure,
219 },
220#define AUTOGAIN_IDX 4
Hans de Goededcef3232008-07-10 10:40:53 -0300221 {
222 {
223 .id = V4L2_CID_AUTOGAIN,
224 .type = V4L2_CTRL_TYPE_BOOLEAN,
225 .name = "Automatic Gain (and Exposure)",
226 .minimum = 0,
227 .maximum = 1,
228 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300229#define AUTOGAIN_DEF 1
230 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300231 .flags = 0,
232 },
233 .set = sd_setautogain,
234 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235 },
Hans de Goede26984b02010-02-01 13:18:37 -0300236#define FREQ_IDX 5
Hans de Goede66f35822008-07-16 10:16:28 -0300237 {
238 {
239 .id = V4L2_CID_POWER_LINE_FREQUENCY,
240 .type = V4L2_CTRL_TYPE_MENU,
241 .name = "Light frequency filter",
242 .minimum = 0,
243 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
244 .step = 1,
Hans de Goede606f8422010-02-10 06:49:23 -0300245#define FREQ_DEF 0
Hans de Goede66f35822008-07-16 10:16:28 -0300246 .default_value = FREQ_DEF,
247 },
248 .set = sd_setfreq,
249 .get = sd_getfreq,
250 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251};
252
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300253static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300254 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
255 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300256 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300259 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
260 .bytesperline = 160,
Hans de Goede5c515182008-09-03 17:12:22 -0300261 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300262 .colorspace = V4L2_COLORSPACE_SRGB,
263 .priv = 2},
264 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
265 .bytesperline = 320,
Hans de Goede5c515182008-09-03 17:12:22 -0300266 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 1},
269 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
270 .bytesperline = 640,
Hans de Goede5c515182008-09-03 17:12:22 -0300271 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300272 .colorspace = V4L2_COLORSPACE_SRGB,
273 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300274};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300275static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300276 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
277 .bytesperline = 160,
278 .sizeimage = 160 * 120,
279 .colorspace = V4L2_COLORSPACE_SRGB,
280 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
281 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
282 .bytesperline = 160,
283 .sizeimage = 160 * 120 * 5 / 4,
284 .colorspace = V4L2_COLORSPACE_SRGB,
285 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300286 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
287 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300288 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300289 .colorspace = V4L2_COLORSPACE_SRGB,
290 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300291 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
292 .bytesperline = 176,
Hans de Goede5c515182008-09-03 17:12:22 -0300293 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300294 .colorspace = V4L2_COLORSPACE_SRGB,
295 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300296 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
297 .bytesperline = 320,
298 .sizeimage = 320 * 240 * 5 / 4,
299 .colorspace = V4L2_COLORSPACE_SRGB,
300 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300301 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
302 .bytesperline = 352,
Hans de Goede5c515182008-09-03 17:12:22 -0300303 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300304 .colorspace = V4L2_COLORSPACE_SRGB,
305 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300306};
307
Hans de Goede00765f12010-12-12 15:55:03 -0300308static const __u8 initHv7131d[] = {
309 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
310 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
312 0x28, 0x1e, 0x60, 0x8e, 0x42,
Hans de Goede00765f12010-12-12 15:55:03 -0300313};
314static const __u8 hv7131d_sensor_init[][8] = {
315 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
316 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
317 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
318 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
319 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
320};
321
322static const __u8 initHv7131r[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300323 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
324 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300325 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300326 0x28, 0x1e, 0x60, 0x8a, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300327};
Hans de Goede00765f12010-12-12 15:55:03 -0300328static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300329 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
330 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
331 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
332 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
333 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
334};
335static const __u8 initOv6650[] = {
336 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
337 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300338 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede0a76cb82011-01-05 13:55:43 -0300339 0x10,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340};
Jean-François Moine780e3122010-10-19 04:29:10 -0300341static const __u8 ov6650_sensor_init[][8] = {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200342 /* Bright, contrast, etc are set through SCBB interface.
Jean-François Moine780e3122010-10-19 04:29:10 -0300343 * AVCAP on win2 do not send any data on this controls. */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300345
346 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300347 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300348 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300349 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300350 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300351 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
352/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
353 * THIS SET GREEN SCREEN
354 * (pixels could be innverted in decode kind of "brg",
355 * but blue wont be there. Avoid this data ... */
356 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
357 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300358 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300359 /* Enable rgb brightness control */
360 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
361 /* HDG: Note windows uses the line below, which sets both register 0x60
362 and 0x61 I believe these registers of the ov6650 are identical as
363 those of the ov7630, because if this is true the windows settings
364 add a bit additional red gain and a lot additional blue gain, which
365 matches my findings that the windows settings make blue much too
366 blue and red a little too red.
367 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300368 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300369 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
370 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371};
Hans de Goededcef3232008-07-10 10:40:53 -0300372
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300373static const __u8 initOv7630[] = {
374 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
375 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300376 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300378 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300379};
Hans de Goede6af492e2008-07-22 07:09:33 -0300380static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300381 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
382 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
383/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300384 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300385 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
386 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
387 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
388 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
389 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
390 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
391 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300392 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
393/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300394 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
395 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
396 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
397 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
398 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
399 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
400};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300401
402static const __u8 initPas106[] = {
403 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
404 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300405 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300406 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300407};
408/* compression 0x86 mckinit1 0x2b */
Hans de Goede421763e2010-02-10 18:57:40 -0300409
410/* "Known" PAS106B registers:
411 0x02 clock divider
412 0x03 Variable framerate bits 4-11
413 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
414 The variable framerate control must never be set lower then 300,
415 which sets the framerate at 90 / reg02, otherwise vsync is lost.
416 0x05 Shutter Time Line Offset, this can be used as an exposure control:
417 0 = use full frame time, 255 = no exposure at all
418 Note this may never be larger then "var-framerate control" / 2 - 2.
419 When var-framerate control is < 514, no exposure is reached at the max
420 allowed value for the framerate control value, rather then at 255.
421 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
422 only a very little bit, leave at 0xcd
423 0x07 offset sign bit (bit0 1 > negative offset)
424 0x08 offset
425 0x09 Blue Gain
426 0x0a Green1 Gain
427 0x0b Green2 Gain
428 0x0c Red Gain
429 0x0e Global gain
430 0x13 Write 1 to commit settings to sensor
431*/
432
Hans de Goedef45f06b2008-09-03 17:12:21 -0300433static const __u8 pas106_sensor_init[][8] = {
434 /* Pixel Clock Divider 6 */
435 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
436 /* Frame Time MSB (also seen as 0x12) */
437 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
438 /* Frame Time LSB (also seen as 0x05) */
439 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
440 /* Shutter Time Line Offset (also seen as 0x6d) */
441 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
442 /* Shutter Time Pixel Offset (also seen as 0xb1) */
443 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
444 /* Black Level Subtract Sign (also seen 0x00) */
445 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
446 /* Black Level Subtract Level (also seen 0x01) */
447 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
448 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
449 /* Color Gain B Pixel 5 a */
450 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
451 /* Color Gain G1 Pixel 1 5 */
452 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
453 /* Color Gain G2 Pixel 1 0 5 */
454 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
455 /* Color Gain R Pixel 3 1 */
456 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
457 /* Color GainH Pixel */
458 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
459 /* Global Gain */
460 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
461 /* Contrast */
462 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
463 /* H&V synchro polarity */
464 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
465 /* ?default */
466 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
467 /* DAC scale */
468 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
469 /* ?default */
470 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
471 /* Validate Settings */
472 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300473};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300474
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300475static const __u8 initPas202[] = {
476 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
477 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300478 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goede82e839c2010-02-03 14:37:30 -0300479 0x28, 0x1e, 0x20, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480};
Hans de Goede82e839c2010-02-03 14:37:30 -0300481
482/* "Known" PAS202BCB registers:
483 0x02 clock divider
484 0x04 Variable framerate bits 6-11 (*)
485 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
486 0x07 Blue Gain
487 0x08 Green Gain
488 0x09 Red Gain
489 0x0b offset sign bit (bit0 1 > negative offset)
490 0x0c offset
491 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
492 leave at 1 otherwise we get a jump in our exposure control
493 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
494 0x10 Master gain 0 - 31
495 0x11 write 1 to apply changes
496 (*) The variable framerate control must never be set lower then 500
497 which sets the framerate at 30 / reg02, otherwise vsync is lost.
498*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499static const __u8 pas202_sensor_init[][8] = {
Hans de Goede82e839c2010-02-03 14:37:30 -0300500 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
501 to set it lower, but for some reason the bridge starts missing
502 vsync's then */
503 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300504 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
505 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
Jean-François Moine1d00d6c2010-10-29 13:58:22 -0300506 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300507 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
508 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
509 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
510 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
511 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
512 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513};
514
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300515static const __u8 initTas5110c[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
517 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300518 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 0x16, 0x12, 0x60, 0x86, 0x2b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520};
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300521/* Same as above, except a different hstart */
522static const __u8 initTas5110d[] = {
523 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
524 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300525 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300526 0x16, 0x12, 0x60, 0x86, 0x2b,
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300527};
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300528/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
529static const __u8 tas5110c_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
531 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300532};
533/* Known TAS5110D registers
534 * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
535 * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
536 * Note: writing reg03 seems to only work when written together with 02
537 */
538static const __u8 tas5110d_sensor_init[][8] = {
539 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540};
541
542static const __u8 initTas5130[] = {
543 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
544 0x00, 0x00,
Hans de Goede4efcfa02010-02-01 07:48:17 -0300545 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546 0x28, 0x1e, 0x60, COMP, MCK_INIT,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300547};
548static const __u8 tas5130_sensor_init[][8] = {
Jean-François Moine780e3122010-10-19 04:29:10 -0300549/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550 * shutter 0x47 short exposure? */
551 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
552 /* shutter 0x01 long exposure */
553 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
554};
555
Hans Verkuild45b9b82008-09-04 03:33:43 -0300556static struct sensor_data sensor_data[] = {
Hans de Goede0a76cb82011-01-05 13:55:43 -0300557SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
558SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
559SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60),
560SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21),
561SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0),
562SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0),
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300563SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
Hans de Goede0a76cb82011-01-05 13:55:43 -0300564 NO_BRIGHTNESS|NO_FREQ, 0),
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300565SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
Hans de Goede0a76cb82011-01-05 13:55:43 -0300566 NO_BRIGHTNESS|NO_FREQ, 0),
567SENS(initTas5130, tas5130_sensor_init, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300568};
569
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300570/* get one byte in gspca_dev->usb_buf */
571static void reg_r(struct gspca_dev *gspca_dev,
572 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300573{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300574 usb_control_msg(gspca_dev->dev,
575 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300576 0, /* request */
577 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
578 value,
579 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300580 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 500);
582}
583
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300584static void reg_w(struct gspca_dev *gspca_dev,
585 __u16 value,
586 const __u8 *buffer,
587 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300589#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300590 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300591 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
592 return;
593 }
594#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300595 memcpy(gspca_dev->usb_buf, buffer, len);
596 usb_control_msg(gspca_dev->dev,
597 usb_sndctrlpipe(gspca_dev->dev, 0),
598 0x08, /* request */
599 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
600 value,
601 0, /* index */
602 gspca_dev->usb_buf, len,
603 500);
604}
605
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300606static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607{
608 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300609
610 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300611 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612 while (retry--) {
613 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300614 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf2008-07-16 08:40:30 -0300615 if (gspca_dev->usb_buf[0] & 0x04) {
616 if (gspca_dev->usb_buf[0] & 0x08)
617 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 return 0;
Andoni Zubimendib7474cf2008-07-16 08:40:30 -0300619 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620 }
621 return -1;
622}
623
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300624static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 const __u8 buffer[][8], int len)
626{
627 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629 len -= 8;
630 if (len <= 0)
631 break;
632 buffer++;
633 }
634}
635
636static void setbrightness(struct gspca_dev *gspca_dev)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 __u8 value;
640
641 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300642 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 case SENSOR_OV7630: {
644 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300645 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646
647 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300648 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300650 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 goto err;
652 break;
653 }
Hans de Goede421763e2010-02-10 18:57:40 -0300654 case SENSOR_PAS106:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655 case SENSOR_PAS202: {
Hans de Goede82e839c2010-02-03 14:37:30 -0300656 __u8 i2cpbright[] =
657 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
Hans de Goede421763e2010-02-10 18:57:40 -0300658 __u8 i2cpdoit[] =
Hans de Goede82e839c2010-02-03 14:37:30 -0300659 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660
Hans de Goede421763e2010-02-10 18:57:40 -0300661 /* PAS106 uses reg 7 and 8 instead of b and c */
662 if (sd->sensor == SENSOR_PAS106) {
663 i2cpbright[2] = 7;
664 i2cpdoit[2] = 0x13;
665 }
666
Hans de Goede82e839c2010-02-03 14:37:30 -0300667 if (sd->brightness < 127) {
668 /* change reg 0x0b, signreg */
669 i2cpbright[3] = 0x01;
670 /* set reg 0x0c, offset */
671 i2cpbright[4] = 127 - sd->brightness;
672 } else
673 i2cpbright[4] = sd->brightness - 127;
674
675 if (i2c_w(gspca_dev, i2cpbright) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300676 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300677 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678 goto err;
679 break;
680 }
Hans de Goededcef3232008-07-10 10:40:53 -0300681 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 __u8 i2c[] =
683 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
684
685 value = 0xff - sd->brightness;
686 i2c[4] = value;
687 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300688 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300689 goto err;
690 break;
691 }
692 }
693 return;
694err:
695 PDEBUG(D_ERR, "i2c error brightness");
696}
Hans de Goededcef3232008-07-10 10:40:53 -0300697
698static void setsensorgain(struct gspca_dev *gspca_dev)
699{
700 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300701 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300702
703 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300704 case SENSOR_HV7131D: {
705 __u8 i2c[] =
706 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
Hans de Goededcef3232008-07-10 10:40:53 -0300707
Hans de Goede00765f12010-12-12 15:55:03 -0300708 i2c[3] = 0x3f - (sd->gain / 4);
709 i2c[4] = 0x3f - (sd->gain / 4);
710 i2c[5] = 0x3f - (sd->gain / 4);
711
712 if (i2c_w(gspca_dev, i2c) < 0)
713 goto err;
714 break;
715 }
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300716 case SENSOR_TAS5110C: {
Hans de Goededcef3232008-07-10 10:40:53 -0300717 __u8 i2c[] =
718 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
719
Hans de Goedea975a522008-07-16 15:29:11 -0300720 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300721 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300722 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300723 break;
724 }
Hans de Goede0d0d7ef2011-01-06 07:55:20 -0300725 case SENSOR_TAS5110D: {
726 __u8 i2c[] = {
727 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
728 gain = 255 - gain;
729 /* The bits in the register are the wrong way around!! */
730 i2c[3] |= (gain & 0x80) >> 7;
731 i2c[3] |= (gain & 0x40) >> 5;
732 i2c[3] |= (gain & 0x20) >> 3;
733 i2c[3] |= (gain & 0x10) >> 1;
734 i2c[3] |= (gain & 0x08) << 1;
735 i2c[3] |= (gain & 0x04) << 3;
736 i2c[3] |= (gain & 0x02) << 5;
737 i2c[3] |= (gain & 0x01) << 7;
738 if (i2c_w(gspca_dev, i2c) < 0)
739 goto err;
740 break;
741 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300742
Hans de Goedea975a522008-07-16 15:29:11 -0300743 case SENSOR_OV6650:
744 gain >>= 1;
745 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300746 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300747 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300748
Hans de Goedef45f06b2008-09-03 17:12:21 -0300749 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300750 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300751 if (i2c_w(gspca_dev, i2c) < 0)
752 goto err;
753 break;
754 }
Hans de Goede421763e2010-02-10 18:57:40 -0300755 case SENSOR_PAS106:
Hans de Goede82e839c2010-02-03 14:37:30 -0300756 case SENSOR_PAS202: {
757 __u8 i2cpgain[] =
Hans de Goede421763e2010-02-10 18:57:40 -0300758 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede82e839c2010-02-03 14:37:30 -0300759 __u8 i2cpcolorgain[] =
760 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
Hans de Goede421763e2010-02-10 18:57:40 -0300761 __u8 i2cpdoit[] =
762 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
763
764 /* PAS106 uses different regs (and has split green gains) */
765 if (sd->sensor == SENSOR_PAS106) {
766 i2cpgain[2] = 0x0e;
767 i2cpcolorgain[0] = 0xd0;
768 i2cpcolorgain[2] = 0x09;
769 i2cpdoit[2] = 0x13;
770 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300771
772 i2cpgain[3] = sd->gain >> 3;
773 i2cpcolorgain[3] = sd->gain >> 4;
774 i2cpcolorgain[4] = sd->gain >> 4;
775 i2cpcolorgain[5] = sd->gain >> 4;
Hans de Goede421763e2010-02-10 18:57:40 -0300776 i2cpcolorgain[6] = sd->gain >> 4;
Hans de Goede82e839c2010-02-03 14:37:30 -0300777
778 if (i2c_w(gspca_dev, i2cpgain) < 0)
779 goto err;
780 if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
781 goto err;
782 if (i2c_w(gspca_dev, i2cpdoit) < 0)
783 goto err;
784 break;
785 }
Hans de Goededcef3232008-07-10 10:40:53 -0300786 }
787 return;
788err:
789 PDEBUG(D_ERR, "i2c error gain");
790}
791
792static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300793{
794 struct sd *sd = (struct sd *) gspca_dev;
795 __u8 gain;
Hans de Goede0a76cb82011-01-05 13:55:43 -0300796 __u8 buf[3] = { 0, 0, 0 };
Hans de Goede4efcfa02010-02-01 07:48:17 -0300797
798 if (sensor_data[sd->sensor].flags & F_GAIN) {
799 /* Use the sensor gain to do the actual gain */
800 setsensorgain(gspca_dev);
801 return;
802 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803
Hans de Goede0a76cb82011-01-05 13:55:43 -0300804 if (sd->bridge == BRIDGE_103) {
805 gain = sd->gain >> 1;
806 buf[0] = gain; /* Red */
807 buf[1] = gain; /* Green */
808 buf[2] = gain; /* Blue */
809 reg_w(gspca_dev, 0x05, buf, 3);
810 } else {
811 gain = sd->gain >> 4;
812 buf[0] = gain << 4 | gain; /* Red and blue */
813 buf[1] = gain; /* Green */
814 reg_w(gspca_dev, 0x10, buf, 2);
815 }
Hans de Goededcef3232008-07-10 10:40:53 -0300816}
817
818static void setexposure(struct gspca_dev *gspca_dev)
819{
820 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300821
822 switch (sd->sensor) {
Hans de Goede00765f12010-12-12 15:55:03 -0300823 case SENSOR_HV7131D: {
824 /* Note the datasheet wrongly says line mode exposure uses reg
825 0x26 and 0x27, testing has shown 0x25 + 0x26 */
826 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
827 /* The HV7131D's exposure goes from 0 - 65535, we scale our
828 exposure of 0-1023 to 0-6138. There are 2 reasons for this:
829 1) This puts our exposure knee of 200 at approx the point
830 where the framerate starts dropping
831 2) At 6138 the framerate has already dropped to 2 fps,
832 going any lower makes little sense */
833 __u16 reg = sd->exposure * 6;
834 i2c[3] = reg >> 8;
835 i2c[4] = reg & 0xff;
836 if (i2c_w(gspca_dev, i2c) != 0)
837 goto err;
838 break;
839 }
Hans de Goedeb10af3f2010-01-10 19:31:34 -0300840 case SENSOR_TAS5110C:
841 case SENSOR_TAS5110D: {
Hans de Goededcef3232008-07-10 10:40:53 -0300842 /* register 19's high nibble contains the sn9c10x clock divider
843 The high nibble configures the no fps according to the
844 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goede26984b02010-02-01 13:18:37 -0300845 __u8 reg = sd->exposure;
Hans de Goededcef3232008-07-10 10:40:53 -0300846 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300847 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300848 break;
849 }
Hans de Goedea975a522008-07-16 15:29:11 -0300850 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300851 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300852 /* The ov6650 / ov7630 have 2 registers which both influence
853 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300854 according to: fps = 30 / (low_nibble + 1)
855
856 The fps configures the maximum exposure setting, but it is
857 possible to use less exposure then what the fps maximum
858 allows by setting register 10. register 10 configures the
859 actual exposure as quotient of the full exposure, with 0
860 being no exposure at all (not very usefull) and reg10_max
861 being max exposure possible at that framerate.
862
863 The code maps our 0 - 510 ms exposure ctrl to these 2
864 registers, trying to keep fps as high as possible.
865 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300866 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
867 int reg10, reg11, reg10_max;
868
Hans de Goede66f35822008-07-16 10:16:28 -0300869 /* ov6645 datasheet says reg10_max is 9a, but that uses
870 tline * 2 * reg10 as formula for calculating texpo, the
871 ov6650 probably uses the same formula as the 7730 which uses
872 tline * 4 * reg10, which explains why the reg10max we've
873 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300874 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300875 if (sd->sensor == SENSOR_OV6650) {
876 reg10_max = 0x4d;
877 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
878 } else
879 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300880
Hans de Goede82e839c2010-02-03 14:37:30 -0300881 reg11 = (15 * sd->exposure + 999) / 1000;
Hans de Goedef4d52022008-07-15 09:36:42 -0300882 if (reg11 < 1)
883 reg11 = 1;
884 else if (reg11 > 16)
885 reg11 = 16;
886
Hans de Goede10bb7532010-02-04 06:10:55 -0300887 /* In 640x480, if the reg11 has less than 4, the image is
888 unstable (the bridge goes into a higher compression mode
889 which we have not reverse engineered yet). */
890 if (gspca_dev->width == 640 && reg11 < 4)
891 reg11 = 4;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300892
Hans de Goedef4d52022008-07-15 09:36:42 -0300893 /* frame exposure time in ms = 1000 * reg11 / 30 ->
Hans de Goede82e839c2010-02-03 14:37:30 -0300894 reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
895 reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300896
897 /* Don't allow this to get below 10 when using autogain, the
898 steps become very large (relatively) when below 10 causing
899 the image to oscilate from much too dark, to much too bright
900 and back again. */
901 if (sd->autogain && reg10 < 10)
902 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300903 else if (reg10 > reg10_max)
904 reg10 = reg10_max;
905
906 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300907 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300908 i2c[3] = reg10;
909 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300910
911 /* If register 11 didn't change, don't change it */
Jean-François Moine780e3122010-10-19 04:29:10 -0300912 if (sd->reg11 == reg11)
Hans de Goede6af492e2008-07-22 07:09:33 -0300913 i2c[0] = 0xa0;
914
915 if (i2c_w(gspca_dev, i2c) == 0)
916 sd->reg11 = reg11;
917 else
Hans de Goede82e839c2010-02-03 14:37:30 -0300918 goto err;
919 break;
920 }
921 case SENSOR_PAS202: {
922 __u8 i2cpframerate[] =
923 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
924 __u8 i2cpexpo[] =
925 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
926 const __u8 i2cpdoit[] =
927 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
928 int framerate_ctrl;
929
930 /* The exposure knee for the autogain algorithm is 200
931 (100 ms / 10 fps on other sensors), for values below this
932 use the control for setting the partial frame expose time,
933 above that use variable framerate. This way we run at max
934 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
935 is reached. Using the variable framerate control above 200
936 is better then playing around with both clockdiv + partial
937 frame exposure times (like we are doing with the ov chips),
938 as that sometimes leads to jumps in the exposure control,
939 which are bad for auto exposure. */
940 if (sd->exposure < 200) {
941 i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
942 framerate_ctrl = 500;
943 } else {
944 /* The PAS202's exposure control goes from 0 - 4095,
945 but anything below 500 causes vsync issues, so scale
946 our 200-1023 to 500-4095 */
947 framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
948 500;
949 }
950
951 i2cpframerate[3] = framerate_ctrl >> 6;
952 i2cpframerate[4] = framerate_ctrl & 0x3f;
953 if (i2c_w(gspca_dev, i2cpframerate) < 0)
954 goto err;
955 if (i2c_w(gspca_dev, i2cpexpo) < 0)
956 goto err;
957 if (i2c_w(gspca_dev, i2cpdoit) < 0)
958 goto err;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300959 break;
960 }
Hans de Goede421763e2010-02-10 18:57:40 -0300961 case SENSOR_PAS106: {
962 __u8 i2cpframerate[] =
963 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
964 __u8 i2cpexpo[] =
965 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
966 const __u8 i2cpdoit[] =
967 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
968 int framerate_ctrl;
969
970 /* For values below 150 use partial frame exposure, above
971 that use framerate ctrl */
972 if (sd->exposure < 150) {
973 i2cpexpo[3] = 150 - sd->exposure;
974 framerate_ctrl = 300;
975 } else {
976 /* The PAS106's exposure control goes from 0 - 4095,
977 but anything below 300 causes vsync issues, so scale
978 our 150-1023 to 300-4095 */
979 framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
980 300;
981 }
982
983 i2cpframerate[3] = framerate_ctrl >> 4;
984 i2cpframerate[4] = framerate_ctrl & 0x0f;
985 if (i2c_w(gspca_dev, i2cpframerate) < 0)
986 goto err;
987 if (i2c_w(gspca_dev, i2cpexpo) < 0)
988 goto err;
989 if (i2c_w(gspca_dev, i2cpdoit) < 0)
990 goto err;
991 break;
992 }
Hans de Goededcef3232008-07-10 10:40:53 -0300993 }
Hans de Goede82e839c2010-02-03 14:37:30 -0300994 return;
995err:
996 PDEBUG(D_ERR, "i2c error exposure");
Hans de Goededcef3232008-07-10 10:40:53 -0300997}
998
Hans de Goede66f35822008-07-16 10:16:28 -0300999static void setfreq(struct gspca_dev *gspca_dev)
1000{
1001 struct sd *sd = (struct sd *) gspca_dev;
1002
1003 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -03001004 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -03001005 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -03001006 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -03001007 compensation, for the ov6650 this is identical to ov6630
1008 0x2b register, see ov6630 datasheet.
1009 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -03001010 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -03001011 switch (sd->freq) {
1012 default:
1013/* case 0: * no filter*/
1014/* case 2: * 60 hz */
1015 i2c[3] = 0;
1016 break;
1017 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -03001018 i2c[3] = (sd->sensor == SENSOR_OV6650)
1019 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -03001020 break;
1021 }
Hans de Goedef45f06b2008-09-03 17:12:21 -03001022 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -03001023 if (i2c_w(gspca_dev, i2c) < 0)
1024 PDEBUG(D_ERR, "i2c error setfreq");
1025 break;
1026 }
1027 }
1028}
1029
Hans de Goede26984b02010-02-01 13:18:37 -03001030#include "coarse_expo_autogain.h"
1031
Hans de Goededcef3232008-07-10 10:40:53 -03001032static void do_autogain(struct gspca_dev *gspca_dev)
1033{
Hans de Goede26984b02010-02-01 13:18:37 -03001034 int deadzone, desired_avg_lum, result;
Hans de Goededcef3232008-07-10 10:40:53 -03001035 struct sd *sd = (struct sd *) gspca_dev;
1036 int avg_lum = atomic_read(&sd->avg_lum);
1037
Hans de Goede26984b02010-02-01 13:18:37 -03001038 if (avg_lum == -1 || !sd->autogain)
Hans de Goededcef3232008-07-10 10:40:53 -03001039 return;
1040
Hans de Goede26984b02010-02-01 13:18:37 -03001041 if (sd->autogain_ignore_frames > 0) {
1042 sd->autogain_ignore_frames--;
1043 return;
1044 }
1045
Hans de Goede5017c7b2008-10-22 04:59:29 -03001046 /* SIF / VGA sensors have a different autoexposure area and thus
1047 different avg_lum values for the same picture brightness */
1048 if (sensor_data[sd->sensor].flags & F_SIF) {
Hans de Goede26984b02010-02-01 13:18:37 -03001049 deadzone = 500;
1050 /* SIF sensors tend to overexpose, so keep this small */
1051 desired_avg_lum = 5000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001052 } else {
Hans de Goede26984b02010-02-01 13:18:37 -03001053 deadzone = 1500;
Hans de Goedef913c002011-01-05 16:01:16 -03001054 desired_avg_lum = 13000;
Hans de Goede5017c7b2008-10-22 04:59:29 -03001055 }
1056
Hans de Goede26984b02010-02-01 13:18:37 -03001057 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
1058 result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
1059 sd->brightness * desired_avg_lum / 127,
1060 deadzone);
1061 else
1062 result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
1063 sd->brightness * desired_avg_lum / 127,
1064 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1065
1066 if (result) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -03001067 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -03001068 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -03001069 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -03001070 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071}
1072
1073/* this function is called at probe time */
1074static int sd_config(struct gspca_dev *gspca_dev,
1075 const struct usb_device_id *id)
1076{
1077 struct sd *sd = (struct sd *) gspca_dev;
1078 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -03001079
1080 reg_r(gspca_dev, 0x00);
1081 if (gspca_dev->usb_buf[0] != 0x10)
1082 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001083
Jean-Francois Moine5da162e2008-07-26 14:17:23 -03001084 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001085 sd->sensor = id->driver_info >> 8;
1086 sd->bridge = id->driver_info & 0xff;
1087 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001088
1089 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001090 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001092 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001093 } else {
1094 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -03001095 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001096 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -03001097 cam->npkt = 36; /* 36 packets per ISOC message */
1098
Hans de Goededcef3232008-07-10 10:40:53 -03001099 sd->brightness = BRIGHTNESS_DEF;
1100 sd->gain = GAIN_DEF;
Hans de Goede26984b02010-02-01 13:18:37 -03001101 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
1102 sd->exposure = COARSE_EXPOSURE_DEF;
1103 gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
1104 } else {
1105 sd->exposure = EXPOSURE_DEF;
1106 gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
1107 }
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001108 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1109 sd->autogain = 0; /* Disable do_autogain callback */
1110 else
1111 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -03001112 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -03001113
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001114 return 0;
1115}
1116
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001117/* this function is called at probe and resume time */
1118static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119{
Hans de Goede271315a2008-09-03 17:12:19 -03001120 const __u8 stop = 0x09; /* Disable stream turn of LED */
1121
1122 reg_w(gspca_dev, 0x01, &stop, 1);
1123
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001124 return 0;
1125}
1126
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001127/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001128static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001129{
1130 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -03001131 struct cam *cam = &gspca_dev->cam;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001132 int i, mode;
1133 __u8 regs[0x31];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001134
Hans de Goede93627732008-09-04 16:20:12 -03001135 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001136 /* Copy registers 0x01 - 0x19 from the template */
1137 memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
1138 /* Set the mode */
1139 regs[0x18] |= mode << 4;
1140
1141 /* Set bridge gain to 1.0 */
1142 if (sd->bridge == BRIDGE_103) {
1143 regs[0x05] = 0x20; /* Red */
1144 regs[0x06] = 0x20; /* Green */
1145 regs[0x07] = 0x20; /* Blue */
1146 } else {
1147 regs[0x10] = 0x00; /* Red and blue */
1148 regs[0x11] = 0x00; /* Green */
1149 }
1150
1151 /* Setup pixel numbers and auto exposure window */
1152 if (sensor_data[sd->sensor].flags & F_SIF) {
1153 regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
1154 regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
1155 regs[0x1c] = 0x02; /* AE H-start 64 */
1156 regs[0x1d] = 0x02; /* AE V-start 64 */
1157 regs[0x1e] = 0x09; /* AE H-end 288 */
1158 regs[0x1f] = 0x07; /* AE V-end 224 */
1159 } else {
1160 regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
1161 regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
Hans de Goedef913c002011-01-05 16:01:16 -03001162 regs[0x1c] = 0x05; /* AE H-start 160 */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001163 regs[0x1d] = 0x03; /* AE V-start 96 */
1164 regs[0x1e] = 0x0f; /* AE H-end 480 */
1165 regs[0x1f] = 0x0c; /* AE V-end 384 */
1166 }
1167
1168 /* Setup the gamma table (only used with the sn9c103 bridge) */
1169 for (i = 0; i < 16; i++)
1170 regs[0x20 + i] = i * 16;
1171 regs[0x20 + i] = 255;
1172
1173 /* Special cases where some regs depend on mode or bridge */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001174 switch (sd->sensor) {
Hans de Goedef45f06b2008-09-03 17:12:21 -03001175 case SENSOR_TAS5130CXX:
Hans de Goede0a76cb82011-01-05 13:55:43 -03001176 /* FIXME / TESTME
1177 probably not mode specific at all most likely the upper
Hans de Goedef45f06b2008-09-03 17:12:21 -03001178 nibble of 0x19 is exposure (clock divider) just as with
1179 the tas5110, we need someone to test this. */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001180 regs[0x19] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 break;
Hans de Goede0a76cb82011-01-05 13:55:43 -03001182 case SENSOR_OV7630:
1183 /* FIXME / TESTME for some reason with the 101/102 bridge the
1184 clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
1185 Also the hstart needs to go from 1 to 2 when using a 103,
1186 which is likely related. This does not seem right. */
1187 if (sd->bridge == BRIDGE_103) {
1188 regs[0x01] = 0x44; /* Select 24 Mhz clock */
1189 regs[0x12] = 0x02; /* Set hstart to 2 */
1190 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 }
Hans de Goedec437d652008-09-03 17:12:22 -03001192 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -03001193 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
Hans de Goede0a76cb82011-01-05 13:55:43 -03001194 regs[0x18] &= ~0x80;
Hans de Goede93627732008-09-04 16:20:12 -03001195
1196 /* Vga mode emulation on SIF sensor? */
1197 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
Hans de Goede0a76cb82011-01-05 13:55:43 -03001198 regs[0x12] += 16; /* hstart adjust */
1199 regs[0x13] += 24; /* vstart adjust */
1200 regs[0x15] = 320 / 16; /* hsize */
1201 regs[0x16] = 240 / 16; /* vsize */
Hans de Goede93627732008-09-04 16:20:12 -03001202 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001203
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001204 /* reg 0x01 bit 2 video transfert on */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001205 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001206 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001207 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208 /* Set the registers from the template */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001209 reg_w(gspca_dev, 0x01, &regs[0x01],
1210 (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001211
1212 /* Init the sensor */
1213 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1214 sensor_data[sd->sensor].sensor_init_size);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001215
Hans de Goede0a76cb82011-01-05 13:55:43 -03001216 /* Mode / bridge specific sensor setup */
Hans de Goede82e839c2010-02-03 14:37:30 -03001217 switch (sd->sensor) {
1218 case SENSOR_PAS202: {
1219 const __u8 i2cpclockdiv[] =
1220 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1221 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1222 if (mode)
1223 i2c_w(gspca_dev, i2cpclockdiv);
Hans de Goede0a76cb82011-01-05 13:55:43 -03001224 break;
Hans de Goede82e839c2010-02-03 14:37:30 -03001225 }
Hans de Goede0a76cb82011-01-05 13:55:43 -03001226 case SENSOR_OV7630:
1227 /* FIXME / TESTME We should be able to handle this identical
1228 for the 101/102 and the 103 case */
1229 if (sd->bridge == BRIDGE_103) {
1230 const __u8 i2c[] = { 0xa0, 0x21, 0x13,
1231 0x80, 0x00, 0x00, 0x00, 0x10 };
1232 i2c_w(gspca_dev, i2c);
1233 }
1234 break;
Hans de Goede82e839c2010-02-03 14:37:30 -03001235 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001236 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001237 reg_w(gspca_dev, 0x15, &regs[0x15], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001238 /* compression register */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001239 reg_w(gspca_dev, 0x18, &regs[0x18], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001240 /* H_start */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001241 reg_w(gspca_dev, 0x12, &regs[0x12], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -03001242 /* V_START */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001243 reg_w(gspca_dev, 0x13, &regs[0x13], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001244 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1245 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede0a76cb82011-01-05 13:55:43 -03001246 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001247 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede0a76cb82011-01-05 13:55:43 -03001248 reg_w(gspca_dev, 0x19, &regs[0x19], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001249 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001250 reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001251 /* Enable video transfert */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001252 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 /* Compression */
Hans de Goede0a76cb82011-01-05 13:55:43 -03001254 reg_w(gspca_dev, 0x18, &regs[0x18], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001255 msleep(20);
1256
Hans de Goede6af492e2008-07-22 07:09:33 -03001257 sd->reg11 = -1;
1258
Hans de Goededcef3232008-07-10 10:40:53 -03001259 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001260 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001261 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -03001262 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -03001263
Hans de Goede6af492e2008-07-22 07:09:33 -03001264 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001265 sd->autogain_ignore_frames = 0;
Hans de Goede26984b02010-02-01 13:18:37 -03001266 sd->exp_too_high_cnt = 0;
1267 sd->exp_too_low_cnt = 0;
Hans de Goededcef3232008-07-10 10:40:53 -03001268 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03001269 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001270}
1271
1272static void sd_stopN(struct gspca_dev *gspca_dev)
1273{
Hans de Goedef45f06b2008-09-03 17:12:21 -03001274 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001275}
1276
Hans de Goede2b3e2842010-12-12 08:55:04 -03001277static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001278{
Hans de Goededcef3232008-07-10 10:40:53 -03001279 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede2b3e2842010-12-12 08:55:04 -03001280 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001281
Hans de Goedec36260e2008-07-16 09:56:07 -03001282 /* frames start with:
1283 * ff ff 00 c4 c4 96 synchro
1284 * 00 (unknown)
1285 * xx (frame sequence / size / compression)
1286 * (xx) (idem - extra byte for sn9c103)
1287 * ll mm brightness sum inside auto exposure
1288 * ll mm brightness sum outside auto exposure
1289 * (xx xx xx xx xx) audio values for snc103
1290 */
Hans de Goede2b3e2842010-12-12 08:55:04 -03001291 for (i = 0; i < len; i++) {
1292 switch (sd->header_read) {
1293 case 0:
1294 if (data[i] == 0xff)
1295 sd->header_read++;
1296 break;
1297 case 1:
1298 if (data[i] == 0xff)
1299 sd->header_read++;
1300 else
1301 sd->header_read = 0;
1302 break;
1303 case 2:
1304 if (data[i] == 0x00)
1305 sd->header_read++;
1306 else if (data[i] != 0xff)
1307 sd->header_read = 0;
1308 break;
1309 case 3:
1310 if (data[i] == 0xc4)
1311 sd->header_read++;
1312 else if (data[i] == 0xff)
1313 sd->header_read = 1;
1314 else
1315 sd->header_read = 0;
1316 break;
1317 case 4:
1318 if (data[i] == 0xc4)
1319 sd->header_read++;
1320 else if (data[i] == 0xff)
1321 sd->header_read = 1;
1322 else
1323 sd->header_read = 0;
1324 break;
1325 case 5:
1326 if (data[i] == 0x96)
1327 sd->header_read++;
1328 else if (data[i] == 0xff)
1329 sd->header_read = 1;
1330 else
1331 sd->header_read = 0;
1332 break;
1333 default:
1334 sd->header[sd->header_read - 6] = data[i];
1335 sd->header_read++;
1336 if (sd->header_read == header_size) {
1337 sd->header_read = 0;
1338 return data + i + 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001339 }
1340 }
1341 }
Hans de Goede2b3e2842010-12-12 08:55:04 -03001342 return NULL;
1343}
1344
1345static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1346 u8 *data, /* isoc packet */
1347 int len) /* iso packet length */
1348{
1349 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1350 struct sd *sd = (struct sd *) gspca_dev;
1351 struct cam *cam = &gspca_dev->cam;
1352 u8 *sof;
1353
1354 sof = find_sof(gspca_dev, data, len);
1355 if (sof) {
1356 if (sd->bridge == BRIDGE_103) {
1357 fr_h_sz = 18;
1358 lum_offset = 3;
1359 } else {
1360 fr_h_sz = 12;
1361 lum_offset = 2;
1362 }
1363
1364 len_after_sof = len - (sof - data);
1365 len = (sof - data) - fr_h_sz;
1366 if (len < 0)
1367 len = 0;
1368 }
Hans de Goedec437d652008-09-03 17:12:22 -03001369
1370 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1371 /* In raw mode we sometimes get some garbage after the frame
1372 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001373 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001374 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1375
Jean-François Moineb192ca92010-06-27 03:08:19 -03001376 used = gspca_dev->image_len;
Hans de Goedec437d652008-09-03 17:12:22 -03001377 if (used + len > size)
1378 len = size - used;
1379 }
1380
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001381 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Hans de Goede2b3e2842010-12-12 08:55:04 -03001382
1383 if (sof) {
1384 int lum = sd->header[lum_offset] +
1385 (sd->header[lum_offset + 1] << 8);
1386
1387 /* When exposure changes midway a frame we
1388 get a lum of 0 in this case drop 2 frames
1389 as the frames directly after an exposure
1390 change have an unstable image. Sometimes lum
1391 *really* is 0 (cam used in low light with
1392 low exposure setting), so do not drop frames
1393 if the previous lum was 0 too. */
1394 if (lum == 0 && sd->prev_avg_lum != 0) {
1395 lum = -1;
1396 sd->frames_to_drop = 2;
1397 sd->prev_avg_lum = 0;
1398 } else
1399 sd->prev_avg_lum = lum;
1400 atomic_set(&sd->avg_lum, lum);
1401
1402 if (sd->frames_to_drop)
1403 sd->frames_to_drop--;
1404 else
1405 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1406
1407 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1408 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001409}
1410
1411static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1412{
1413 struct sd *sd = (struct sd *) gspca_dev;
1414
1415 sd->brightness = val;
1416 if (gspca_dev->streaming)
1417 setbrightness(gspca_dev);
1418 return 0;
1419}
1420
1421static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1422{
1423 struct sd *sd = (struct sd *) gspca_dev;
1424
1425 *val = sd->brightness;
1426 return 0;
1427}
1428
Hans de Goededcef3232008-07-10 10:40:53 -03001429static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001430{
1431 struct sd *sd = (struct sd *) gspca_dev;
1432
Hans de Goededcef3232008-07-10 10:40:53 -03001433 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001434 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001435 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001436 return 0;
1437}
1438
Hans de Goededcef3232008-07-10 10:40:53 -03001439static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001440{
1441 struct sd *sd = (struct sd *) gspca_dev;
1442
Hans de Goededcef3232008-07-10 10:40:53 -03001443 *val = sd->gain;
1444 return 0;
1445}
1446
1447static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1448{
1449 struct sd *sd = (struct sd *) gspca_dev;
1450
1451 sd->exposure = val;
1452 if (gspca_dev->streaming)
1453 setexposure(gspca_dev);
1454 return 0;
1455}
1456
1457static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1458{
1459 struct sd *sd = (struct sd *) gspca_dev;
1460
1461 *val = sd->exposure;
1462 return 0;
1463}
1464
1465static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1466{
1467 struct sd *sd = (struct sd *) gspca_dev;
1468
1469 sd->autogain = val;
Hans de Goede26984b02010-02-01 13:18:37 -03001470 sd->exp_too_high_cnt = 0;
1471 sd->exp_too_low_cnt = 0;
1472
Hans de Goededcef3232008-07-10 10:40:53 -03001473 /* when switching to autogain set defaults to make sure
1474 we are on a valid point of the autogain gain /
1475 exposure knee graph, and give this change time to
1476 take effect before doing autogain. */
Hans de Goede26984b02010-02-01 13:18:37 -03001477 if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
Hans de Goededcef3232008-07-10 10:40:53 -03001478 sd->exposure = EXPOSURE_DEF;
1479 sd->gain = GAIN_DEF;
1480 if (gspca_dev->streaming) {
1481 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1482 setexposure(gspca_dev);
1483 setgain(gspca_dev);
1484 }
1485 }
1486
1487 return 0;
1488}
1489
1490static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1491{
1492 struct sd *sd = (struct sd *) gspca_dev;
1493
1494 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001495 return 0;
1496}
1497
Hans de Goede66f35822008-07-16 10:16:28 -03001498static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1499{
1500 struct sd *sd = (struct sd *) gspca_dev;
1501
1502 sd->freq = val;
1503 if (gspca_dev->streaming)
1504 setfreq(gspca_dev);
1505 return 0;
1506}
1507
1508static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1509{
1510 struct sd *sd = (struct sd *) gspca_dev;
1511
1512 *val = sd->freq;
1513 return 0;
1514}
1515
1516static int sd_querymenu(struct gspca_dev *gspca_dev,
1517 struct v4l2_querymenu *menu)
1518{
1519 switch (menu->id) {
1520 case V4L2_CID_POWER_LINE_FREQUENCY:
1521 switch (menu->index) {
1522 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1523 strcpy((char *) menu->name, "NoFliker");
1524 return 0;
1525 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1526 strcpy((char *) menu->name, "50 Hz");
1527 return 0;
1528 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1529 strcpy((char *) menu->name, "60 Hz");
1530 return 0;
1531 }
1532 break;
1533 }
1534 return -EINVAL;
1535}
1536
Jean-François Moine28566432010-10-01 07:33:26 -03001537#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001538static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1539 u8 *data, /* interrupt packet data */
1540 int len) /* interrupt packet length */
1541{
1542 int ret = -EINVAL;
1543
1544 if (len == 1 && data[0] == 1) {
1545 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1546 input_sync(gspca_dev->input_dev);
1547 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1548 input_sync(gspca_dev->input_dev);
1549 ret = 0;
1550 }
1551
1552 return ret;
1553}
1554#endif
1555
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001556/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001557static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001558 .name = MODULE_NAME,
1559 .ctrls = sd_ctrls,
1560 .nctrls = ARRAY_SIZE(sd_ctrls),
1561 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001562 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001563 .start = sd_start,
1564 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001565 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001566 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001567 .dq_callback = do_autogain,
Jean-François Moine28566432010-10-01 07:33:26 -03001568#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Hans de Goedef65e93d2010-01-31 10:35:15 -03001569 .int_pkt_scan = sd_int_pkt_scan,
1570#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001571};
1572
1573/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001574#define SB(sensor, bridge) \
1575 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1576
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001577
Márton Németh37b372e2009-12-10 11:31:09 -03001578static const struct usb_device_id device_table[] __devinitconst = {
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001579 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1580 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
Hans de Goedeb10af3f2010-01-10 19:31:34 -03001581 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001582 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1583 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001584 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001585#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001586 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1587 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1588 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
Hans de Goede0e4b91c2010-02-10 20:29:43 -03001589#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001590 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1591 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001592 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1593 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001594 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001595 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001596 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Hans de Goede00765f12010-12-12 15:55:03 -03001597 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
Hans de Goede4cce1652008-09-04 16:22:57 -03001598 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1599#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1600 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1601#endif
1602 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001603 {}
1604};
1605MODULE_DEVICE_TABLE(usb, device_table);
1606
1607/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001608static int __devinit sd_probe(struct usb_interface *intf,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001609 const struct usb_device_id *id)
1610{
1611 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1612 THIS_MODULE);
1613}
1614
1615static struct usb_driver sd_driver = {
1616 .name = MODULE_NAME,
1617 .id_table = device_table,
1618 .probe = sd_probe,
1619 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001620#ifdef CONFIG_PM
1621 .suspend = gspca_suspend,
1622 .resume = gspca_resume,
1623#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001624};
1625
1626/* -- module insert / remove -- */
1627static int __init sd_mod_init(void)
1628{
Jean-François Moine54826432010-09-13 04:53:03 -03001629 return usb_register(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001630}
1631static void __exit sd_mod_exit(void)
1632{
1633 usb_deregister(&sd_driver);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001634}
1635
1636module_init(sd_mod_init);
1637module_exit(sd_mod_exit);