blob: a9f061063b49e04f5179eb19e2a469b53edbe2d3 [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
45#include "gspca.h"
46
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030047MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
48MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
49MODULE_LICENSE("GPL");
50
51/* specific webcam descriptor */
52struct sd {
53 struct gspca_dev gspca_dev; /* !! must be the first item */
Hans de Goededcef3232008-07-10 10:40:53 -030054 atomic_t avg_lum;
Hans de Goedebf2a2202008-09-04 16:22:56 -030055 int prev_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -030056
Hans de Goedead5ef80d2008-07-14 10:11:42 -030057 unsigned char gain;
58 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030060 unsigned char autogain;
61 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030062 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030063 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030064
Hans de Goedef45f06b2008-09-03 17:12:21 -030065 __u8 bridge; /* Type of bridge */
66#define BRIDGE_101 0
67#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
68#define BRIDGE_103 1
69
70 __u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030071#define SENSOR_HV7131R 0
72#define SENSOR_OV6650 1
73#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030074#define SENSOR_PAS106 3
75#define SENSOR_PAS202 4
76#define SENSOR_TAS5110 5
77#define SENSOR_TAS5130CXX 6
Hans de Goede6af492e2008-07-22 07:09:33 -030078 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030079};
80
Hans de Goedef45f06b2008-09-03 17:12:21 -030081typedef const __u8 sensor_init_t[8];
82
83struct sensor_data {
84 const __u8 *bridge_init[2];
85 int bridge_init_size[2];
86 sensor_init_t *sensor_init;
87 int sensor_init_size;
88 sensor_init_t *sensor_bridge_init[2];
89 int sensor_bridge_init_size[2];
90 int flags;
91 unsigned ctrl_dis;
92 __u8 sensor_addr;
93};
94
95/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030096#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030097#define F_SIF 0x02 /* sif or vga */
Hans de Goedec437d652008-09-03 17:12:22 -030098
99/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
100#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300101#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300102
103/* ctrl_dis helper macros */
104#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
105#define NO_FREQ (1 << FREQ_IDX)
106#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300107
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300108#define COMP2 0x8f
109#define COMP 0xc7 /* 0x87 //0x07 */
110#define COMP1 0xc9 /* 0x89 //0x09 */
111
112#define MCK_INIT 0x63
113#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
114
115#define SYS_CLK 0x04
116
Hans de Goedef45f06b2008-09-03 17:12:21 -0300117#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
118 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
119{ \
120 .bridge_init = { bridge_1, bridge_3 }, \
121 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
122 .sensor_init = sensor, \
123 .sensor_init_size = sizeof(sensor), \
124 .sensor_bridge_init = { sensor_1, sensor_3,}, \
125 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
126 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
127}
128
Hans de Goededcef3232008-07-10 10:40:53 -0300129/* We calculate the autogain at the end of the transfer of a frame, at this
130 moment a frame with the old settings is being transmitted, and a frame is
131 being captured with the old settings. So if we adjust the autogain we must
132 ignore atleast the 2 next frames for the new settings to come into effect
133 before doing any other adjustments */
134#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goededcef3232008-07-10 10:40:53 -0300135
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300136/* V4L2 controls supported by the driver */
137static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
138static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300139static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
140static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
141static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
142static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
143static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
144static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300145static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
146static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147
148static struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300149#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150 {
151 {
152 .id = V4L2_CID_BRIGHTNESS,
153 .type = V4L2_CTRL_TYPE_INTEGER,
154 .name = "Brightness",
155 .minimum = 0,
156 .maximum = 255,
157 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300158#define BRIGHTNESS_DEF 127
159 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160 },
161 .set = sd_setbrightness,
162 .get = sd_getbrightness,
163 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300164#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 {
166 {
Hans de Goededcef3232008-07-10 10:40:53 -0300167 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300169 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300171 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300172 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300173#define GAIN_DEF 127
174#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300175 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176 },
Hans de Goededcef3232008-07-10 10:40:53 -0300177 .set = sd_setgain,
178 .get = sd_getgain,
179 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300180#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300181 {
182 {
183 .id = V4L2_CID_EXPOSURE,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300186#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
187#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300188 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300189 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300190 .step = 1,
191 .default_value = EXPOSURE_DEF,
192 .flags = 0,
193 },
194 .set = sd_setexposure,
195 .get = sd_getexposure,
196 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300197#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300198 {
199 {
200 .id = V4L2_CID_AUTOGAIN,
201 .type = V4L2_CTRL_TYPE_BOOLEAN,
202 .name = "Automatic Gain (and Exposure)",
203 .minimum = 0,
204 .maximum = 1,
205 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300206#define AUTOGAIN_DEF 1
207 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300208 .flags = 0,
209 },
210 .set = sd_setautogain,
211 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300213#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300214 {
215 {
216 .id = V4L2_CID_POWER_LINE_FREQUENCY,
217 .type = V4L2_CTRL_TYPE_MENU,
218 .name = "Light frequency filter",
219 .minimum = 0,
220 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
221 .step = 1,
222#define FREQ_DEF 1
223 .default_value = FREQ_DEF,
224 },
225 .set = sd_setfreq,
226 .get = sd_getfreq,
227 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228};
229
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300230static const struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300231 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
232 .bytesperline = 160,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300233 .sizeimage = 160 * 120,
Hans de Goedec437d652008-09-03 17:12:22 -0300234 .colorspace = V4L2_COLORSPACE_SRGB,
235 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300236 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
237 .bytesperline = 160,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300238 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300239 .colorspace = V4L2_COLORSPACE_SRGB,
240 .priv = 2},
241 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
242 .bytesperline = 320,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300243 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300244 .colorspace = V4L2_COLORSPACE_SRGB,
245 .priv = 1},
246 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
247 .bytesperline = 640,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300248 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300249 .colorspace = V4L2_COLORSPACE_SRGB,
250 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300251};
Jean-Francois Moinecc611b82008-12-29 07:49:41 -0300252static const struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300253 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
254 .bytesperline = 160,
255 .sizeimage = 160 * 120,
256 .colorspace = V4L2_COLORSPACE_SRGB,
257 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
258 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
259 .bytesperline = 160,
260 .sizeimage = 160 * 120 * 5 / 4,
261 .colorspace = V4L2_COLORSPACE_SRGB,
262 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300263 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
264 .bytesperline = 176,
Mauro Carvalho Chehab2389b362008-08-06 20:13:46 -0300265 .sizeimage = 176 * 144,
Hans de Goedec437d652008-09-03 17:12:22 -0300266 .colorspace = V4L2_COLORSPACE_SRGB,
267 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300268 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
269 .bytesperline = 176,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300270 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300271 .colorspace = V4L2_COLORSPACE_SRGB,
272 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300273 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
274 .bytesperline = 320,
275 .sizeimage = 320 * 240 * 5 / 4,
276 .colorspace = V4L2_COLORSPACE_SRGB,
277 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300278 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
279 .bytesperline = 352,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300280 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300281 .colorspace = V4L2_COLORSPACE_SRGB,
282 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283};
284
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300285static const __u8 initHv7131[] = {
286 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
287 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300288 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300289 0x28, 0x1e, 0x60, 0x8a, 0x20,
290 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
291};
292static const __u8 hv7131_sensor_init[][8] = {
293 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
294 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
295 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
296 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
297 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
298};
299static const __u8 initOv6650[] = {
300 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
301 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300302 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300303 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300304};
305static const __u8 ov6650_sensor_init[][8] =
306{
307 /* Bright, contrast, etc are set througth SCBB interface.
308 * AVCAP on win2 do not send any data on this controls. */
309 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300310
311 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300312 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300313 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300314 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300315 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300316 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
317/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
318 * THIS SET GREEN SCREEN
319 * (pixels could be innverted in decode kind of "brg",
320 * but blue wont be there. Avoid this data ... */
321 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
322 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
323 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300324 /* Enable rgb brightness control */
325 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
326 /* HDG: Note windows uses the line below, which sets both register 0x60
327 and 0x61 I believe these registers of the ov6650 are identical as
328 those of the ov7630, because if this is true the windows settings
329 add a bit additional red gain and a lot additional blue gain, which
330 matches my findings that the windows settings make blue much too
331 blue and red a little too red.
332 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300333 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300334 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
335 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300336};
Hans de Goededcef3232008-07-10 10:40:53 -0300337
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338static const __u8 initOv7630[] = {
339 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
340 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300341 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300343 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
345};
346static const __u8 initOv7630_3[] = {
347 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
348 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Hans de Goede4cce1652008-09-04 16:22:57 -0300349 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300350 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300351 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
352 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
353 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
354 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300355};
Hans de Goede6af492e2008-07-22 07:09:33 -0300356static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300357 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
358 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
359/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300360 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
362 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
363 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
364 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
365 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
366 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
367 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300368 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
369/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
371 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
372 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
373 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
374 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
375 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
376};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377
Hans de Goedef45f06b2008-09-03 17:12:21 -0300378static const __u8 ov7630_sensor_init_3[][8] = {
379 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
380};
381
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382static const __u8 initPas106[] = {
383 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
384 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300385 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300386 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300387 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300388};
389/* compression 0x86 mckinit1 0x2b */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300390static const __u8 pas106_sensor_init[][8] = {
391 /* Pixel Clock Divider 6 */
392 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
393 /* Frame Time MSB (also seen as 0x12) */
394 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
395 /* Frame Time LSB (also seen as 0x05) */
396 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
397 /* Shutter Time Line Offset (also seen as 0x6d) */
398 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
399 /* Shutter Time Pixel Offset (also seen as 0xb1) */
400 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
401 /* Black Level Subtract Sign (also seen 0x00) */
402 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
403 /* Black Level Subtract Level (also seen 0x01) */
404 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
405 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
406 /* Color Gain B Pixel 5 a */
407 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
408 /* Color Gain G1 Pixel 1 5 */
409 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
410 /* Color Gain G2 Pixel 1 0 5 */
411 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
412 /* Color Gain R Pixel 3 1 */
413 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
414 /* Color GainH Pixel */
415 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
416 /* Global Gain */
417 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
418 /* Contrast */
419 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
420 /* H&V synchro polarity */
421 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
422 /* ?default */
423 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
424 /* DAC scale */
425 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 /* ?default */
427 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
428 /* Validate Settings */
429 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300430};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300431
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300432static const __u8 initPas202[] = {
433 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
434 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300435 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300436 0x28, 0x1e, 0x28, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300437 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
438};
439static const __u8 pas202_sensor_init[][8] = {
440 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
441 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
442 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
443 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
444 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
445 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
446 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
450 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
451 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
452
453 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
454 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
455 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
456 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
457 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
458 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
459 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
460 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
461};
462
463static const __u8 initTas5110[] = {
464 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
465 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300466 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 0x16, 0x12, 0x60, 0x86, 0x2b,
468 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
469};
470static const __u8 tas5110_sensor_init[][8] = {
471 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
472 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
473 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
474};
475
476static const __u8 initTas5130[] = {
477 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
478 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300479 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 0x28, 0x1e, 0x60, COMP, MCK_INIT,
481 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
482};
483static const __u8 tas5130_sensor_init[][8] = {
484/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
485 * shutter 0x47 short exposure? */
486 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
487 /* shutter 0x01 long exposure */
488 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
489};
490
Hans Verkuild45b9b82008-09-04 03:33:43 -0300491static struct sensor_data sensor_data[] = {
Hans de Goedef45f06b2008-09-03 17:12:21 -0300492SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300493SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300494SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
495 F_GAIN, 0, 0x21),
496SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
497 0),
Hans de Goede93627732008-09-04 16:20:12 -0300498SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300499 NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300500SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300501 NO_BRIGHTNESS|NO_FREQ, 0),
502SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
503 0),
504};
505
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300506/* get one byte in gspca_dev->usb_buf */
507static void reg_r(struct gspca_dev *gspca_dev,
508 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300509{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300510 usb_control_msg(gspca_dev->dev,
511 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300512 0, /* request */
513 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
514 value,
515 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300516 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 500);
518}
519
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300520static void reg_w(struct gspca_dev *gspca_dev,
521 __u16 value,
522 const __u8 *buffer,
523 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300525#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300526 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300527 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
528 return;
529 }
530#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300531 memcpy(gspca_dev->usb_buf, buffer, len);
532 usb_control_msg(gspca_dev->dev,
533 usb_sndctrlpipe(gspca_dev->dev, 0),
534 0x08, /* request */
535 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
536 value,
537 0, /* index */
538 gspca_dev->usb_buf, len,
539 500);
540}
541
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300542static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300543{
544 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545
546 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300547 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548 while (retry--) {
549 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300551 if (gspca_dev->usb_buf[0] & 0x04) {
552 if (gspca_dev->usb_buf[0] & 0x08)
553 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300555 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300556 }
557 return -1;
558}
559
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300560static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 const __u8 buffer[][8], int len)
562{
563 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300564 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300565 len -= 8;
566 if (len <= 0)
567 break;
568 buffer++;
569 }
570}
571
572static void setbrightness(struct gspca_dev *gspca_dev)
573{
574 struct sd *sd = (struct sd *) gspca_dev;
575 __u8 value;
576
577 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300578 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 case SENSOR_OV7630: {
580 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300581 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300582
583 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300584 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300585 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300586 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300587 goto err;
588 break;
589 }
590 case SENSOR_PAS106: {
591 __u8 i2c1[] =
592 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
593
594 i2c1[3] = sd->brightness >> 3;
595 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300596 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 goto err;
598 i2c1[3] = 0x01;
599 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 goto err;
602 break;
603 }
604 case SENSOR_PAS202: {
605 /* __u8 i2cpexpo1[] =
606 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
607 __u8 i2cpexpo[] =
608 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
609 __u8 i2cp202[] =
610 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
611 static __u8 i2cpdoit[] =
612 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
613
614 /* change reg 0x10 */
615 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300618/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300620 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300621 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300623 goto err;
624 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300625 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300627 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300628 goto err;
629 break;
630 }
Hans de Goededcef3232008-07-10 10:40:53 -0300631 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 __u8 i2c[] =
633 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
634
635 value = 0xff - sd->brightness;
636 i2c[4] = value;
637 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300638 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 goto err;
640 break;
641 }
642 }
643 return;
644err:
645 PDEBUG(D_ERR, "i2c error brightness");
646}
Hans de Goededcef3232008-07-10 10:40:53 -0300647
648static void setsensorgain(struct gspca_dev *gspca_dev)
649{
650 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300651 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300652
653 switch (sd->sensor) {
654
655 case SENSOR_TAS5110: {
656 __u8 i2c[] =
657 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
658
Hans de Goedea975a522008-07-16 15:29:11 -0300659 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300660 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300661 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300662 break;
663 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300664
Hans de Goedea975a522008-07-16 15:29:11 -0300665 case SENSOR_OV6650:
666 gain >>= 1;
667 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300668 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300669 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300670
Hans de Goedef45f06b2008-09-03 17:12:21 -0300671 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300672 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300673 if (i2c_w(gspca_dev, i2c) < 0)
674 goto err;
675 break;
676 }
Hans de Goededcef3232008-07-10 10:40:53 -0300677 }
678 return;
679err:
680 PDEBUG(D_ERR, "i2c error gain");
681}
682
683static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684{
685 struct sd *sd = (struct sd *) gspca_dev;
686 __u8 gain;
687 __u8 rgb_value;
688
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300689 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300690
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 /* red and blue gain */
692 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300693 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 /* green gain */
695 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300696 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300697
Hans de Goedef45f06b2008-09-03 17:12:21 -0300698 if (sensor_data[sd->sensor].flags & F_GAIN)
Hans de Goededcef3232008-07-10 10:40:53 -0300699 setsensorgain(gspca_dev);
700}
701
702static void setexposure(struct gspca_dev *gspca_dev)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300705
706 switch (sd->sensor) {
707 case SENSOR_TAS5110: {
708 __u8 reg;
709
710 /* register 19's high nibble contains the sn9c10x clock divider
711 The high nibble configures the no fps according to the
712 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300713 reg = 120 * sd->exposure / 1000;
714 if (reg < 2)
715 reg = 2;
716 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300717 reg = 15;
718 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300719 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300720 break;
721 }
Hans de Goedea975a522008-07-16 15:29:11 -0300722 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300723 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300724 /* The ov6650 / ov7630 have 2 registers which both influence
725 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300726 according to: fps = 30 / (low_nibble + 1)
727
728 The fps configures the maximum exposure setting, but it is
729 possible to use less exposure then what the fps maximum
730 allows by setting register 10. register 10 configures the
731 actual exposure as quotient of the full exposure, with 0
732 being no exposure at all (not very usefull) and reg10_max
733 being max exposure possible at that framerate.
734
735 The code maps our 0 - 510 ms exposure ctrl to these 2
736 registers, trying to keep fps as high as possible.
737 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300738 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
739 int reg10, reg11, reg10_max;
740
Hans de Goede66f35822008-07-16 10:16:28 -0300741 /* ov6645 datasheet says reg10_max is 9a, but that uses
742 tline * 2 * reg10 as formula for calculating texpo, the
743 ov6650 probably uses the same formula as the 7730 which uses
744 tline * 4 * reg10, which explains why the reg10max we've
745 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300746 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300747 if (sd->sensor == SENSOR_OV6650) {
748 reg10_max = 0x4d;
749 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
750 } else
751 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300752
753 reg11 = (60 * sd->exposure + 999) / 1000;
754 if (reg11 < 1)
755 reg11 = 1;
756 else if (reg11 > 16)
757 reg11 = 16;
758
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300759 /* In 640x480, if the reg11 has less than 3, the image is
760 unstable (not enough bandwidth). */
761 if (gspca_dev->width == 640 && reg11 < 3)
762 reg11 = 3;
763
Hans de Goedef4d52022008-07-15 09:36:42 -0300764 /* frame exposure time in ms = 1000 * reg11 / 30 ->
765 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
766 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300767
768 /* Don't allow this to get below 10 when using autogain, the
769 steps become very large (relatively) when below 10 causing
770 the image to oscilate from much too dark, to much too bright
771 and back again. */
772 if (sd->autogain && reg10 < 10)
773 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300774 else if (reg10 > reg10_max)
775 reg10 = reg10_max;
776
777 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300778 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300779 i2c[3] = reg10;
780 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300781
782 /* If register 11 didn't change, don't change it */
783 if (sd->reg11 == reg11 )
784 i2c[0] = 0xa0;
785
786 if (i2c_w(gspca_dev, i2c) == 0)
787 sd->reg11 = reg11;
788 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300789 PDEBUG(D_ERR, "i2c error exposure");
790 break;
791 }
Hans de Goededcef3232008-07-10 10:40:53 -0300792 }
793}
794
Hans de Goede66f35822008-07-16 10:16:28 -0300795static void setfreq(struct gspca_dev *gspca_dev)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798
799 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300800 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300801 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300802 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300803 compensation, for the ov6650 this is identical to ov6630
804 0x2b register, see ov6630 datasheet.
805 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300806 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300807 switch (sd->freq) {
808 default:
809/* case 0: * no filter*/
810/* case 2: * 60 hz */
811 i2c[3] = 0;
812 break;
813 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300814 i2c[3] = (sd->sensor == SENSOR_OV6650)
815 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300816 break;
817 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300818 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300819 if (i2c_w(gspca_dev, i2c) < 0)
820 PDEBUG(D_ERR, "i2c error setfreq");
821 break;
822 }
823 }
824}
825
Hans de Goededcef3232008-07-10 10:40:53 -0300826static void do_autogain(struct gspca_dev *gspca_dev)
827{
Hans de Goede5017c7b2008-10-22 04:59:29 -0300828 int deadzone, desired_avg_lum;
Hans de Goededcef3232008-07-10 10:40:53 -0300829 struct sd *sd = (struct sd *) gspca_dev;
830 int avg_lum = atomic_read(&sd->avg_lum);
831
832 if (avg_lum == -1)
833 return;
834
Hans de Goede5017c7b2008-10-22 04:59:29 -0300835 /* SIF / VGA sensors have a different autoexposure area and thus
836 different avg_lum values for the same picture brightness */
837 if (sensor_data[sd->sensor].flags & F_SIF) {
838 deadzone = 1000;
839 desired_avg_lum = 7000;
840 } else {
841 deadzone = 3000;
842 desired_avg_lum = 23000;
843 }
844
Hans de Goededcef3232008-07-10 10:40:53 -0300845 if (sd->autogain_ignore_frames > 0)
846 sd->autogain_ignore_frames--;
847 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
Hans de Goede5017c7b2008-10-22 04:59:29 -0300848 sd->brightness * desired_avg_lum / 127,
849 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
Jean-Francois Moine1c44d812008-11-10 05:56:55 -0300850 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
Hans de Goedea975a522008-07-16 15:29:11 -0300851 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300852 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300853 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854}
855
856/* this function is called at probe time */
857static int sd_config(struct gspca_dev *gspca_dev,
858 const struct usb_device_id *id)
859{
860 struct sd *sd = (struct sd *) gspca_dev;
861 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -0300862
863 reg_r(gspca_dev, 0x00);
864 if (gspca_dev->usb_buf[0] != 0x10)
865 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300867 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300868 sd->sensor = id->driver_info >> 8;
869 sd->bridge = id->driver_info & 0xff;
870 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300871
872 cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300873 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300875 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300876 } else {
877 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300878 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 }
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -0300880 cam->npkt = 36; /* 36 packets per ISOC message */
881
Hans de Goededcef3232008-07-10 10:40:53 -0300882 sd->brightness = BRIGHTNESS_DEF;
883 sd->gain = GAIN_DEF;
884 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300885 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
886 sd->autogain = 0; /* Disable do_autogain callback */
887 else
888 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300889 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300890
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300891 return 0;
892}
893
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300894/* this function is called at probe and resume time */
895static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896{
Hans de Goede271315a2008-09-03 17:12:19 -0300897 const __u8 stop = 0x09; /* Disable stream turn of LED */
898
899 reg_w(gspca_dev, 0x01, &stop, 1);
900
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901 return 0;
902}
903
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300905static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300906{
907 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -0300908 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300909 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -0300911 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912
Hans de Goede93627732008-09-04 16:20:12 -0300913 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300914 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
915 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -0300916 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
917 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300918 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919 switch (sd->sensor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300920 case SENSOR_PAS202:
Hans de Goede93627732008-09-04 16:20:12 -0300921 reg12_19[5] = mode ? 0x24 : 0x20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 break;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300923 case SENSOR_TAS5130CXX:
924 /* probably not mode specific at all most likely the upper
925 nibble of 0x19 is exposure (clock divider) just as with
926 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -0300927 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 break;
929 }
Hans de Goedec437d652008-09-03 17:12:22 -0300930 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -0300931 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
932 reg12_19[6] &= ~0x80;
933
934 /* Vga mode emulation on SIF sensor? */
935 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
936 reg12_19[0] += 16; /* 0x12: hstart adjust */
937 reg12_19[1] += 24; /* 0x13: vstart adjust */
938 reg12_19[3] = 320 / 16; /* 0x15: hsize */
939 reg12_19[4] = 240 / 16; /* 0x16: vsize */
940 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300941
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300943 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300945 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300947 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300948
949 /* Init the sensor */
950 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
951 sensor_data[sd->sensor].sensor_init_size);
952 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
953 i2c_w_vector(gspca_dev,
954 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
955 sensor_data[sd->sensor].sensor_bridge_init_size[
956 sd->bridge]);
957
Hans de Goede3647fea2008-07-15 05:36:30 -0300958 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -0300959 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -0300961 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300962 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -0300963 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300964 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -0300965 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 /* reset 0x17 SensorClk enable inv Clk 0x60 */
967 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -0300968 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -0300970 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300971 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300972 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300974 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -0300976 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300977 msleep(20);
978
Hans de Goede6af492e2008-07-22 07:09:33 -0300979 sd->reg11 = -1;
980
Hans de Goededcef3232008-07-10 10:40:53 -0300981 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300983 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300984 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300985
Hans de Goede6af492e2008-07-22 07:09:33 -0300986 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300987 sd->autogain_ignore_frames = 0;
988 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300989 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990}
991
992static void sd_stopN(struct gspca_dev *gspca_dev)
993{
Hans de Goedef45f06b2008-09-03 17:12:21 -0300994 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995}
996
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300998 u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999 int len) /* iso packet length */
1000{
Hans de Goede0d2a7222008-07-03 08:15:22 -03001001 int i;
Hans de Goededcef3232008-07-10 10:40:53 -03001002 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedec437d652008-09-03 17:12:22 -03001003 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001004
Hans de Goedec36260ee2008-07-16 09:56:07 -03001005 /* frames start with:
1006 * ff ff 00 c4 c4 96 synchro
1007 * 00 (unknown)
1008 * xx (frame sequence / size / compression)
1009 * (xx) (idem - extra byte for sn9c103)
1010 * ll mm brightness sum inside auto exposure
1011 * ll mm brightness sum outside auto exposure
1012 * (xx xx xx xx xx) audio values for snc103
1013 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -03001015 for (i = 0; i < len - 6; i++) {
1016 if (data[0 + i] == 0xff
1017 && data[1 + i] == 0xff
1018 && data[2 + i] == 0x00
1019 && data[3 + i] == 0xc4
1020 && data[4 + i] == 0xc4
1021 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -03001022 int lum = -1;
1023 int pkt_type = LAST_PACKET;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001024 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1025 18 : 12;
Hans de Goede6af492e2008-07-22 07:09:33 -03001026
Hans de Goedef45f06b2008-09-03 17:12:21 -03001027 if (len - i < fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -03001028 PDEBUG(D_STREAM, "packet too short to"
1029 " get avg brightness");
Hans de Goedef45f06b2008-09-03 17:12:21 -03001030 } else if (sd->bridge == BRIDGE_103) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001031 lum = data[i + 9] +
1032 (data[i + 10] << 8);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001033 } else {
1034 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001035 }
Hans de Goedebf2a2202008-09-04 16:22:56 -03001036 /* When exposure changes midway a frame we
1037 get a lum of 0 in this case drop 2 frames
1038 as the frames directly after an exposure
1039 change have an unstable image. Sometimes lum
1040 *really* is 0 (cam used in low light with
1041 low exposure setting), so do not drop frames
1042 if the previous lum was 0 too. */
1043 if (lum == 0 && sd->prev_avg_lum != 0) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001044 lum = -1;
1045 sd->frames_to_drop = 2;
Hans de Goedebf2a2202008-09-04 16:22:56 -03001046 sd->prev_avg_lum = 0;
1047 } else
1048 sd->prev_avg_lum = lum;
Hans de Goede6af492e2008-07-22 07:09:33 -03001049 atomic_set(&sd->avg_lum, lum);
1050
1051 if (sd->frames_to_drop) {
1052 sd->frames_to_drop--;
1053 pkt_type = DISCARD_PACKET;
1054 }
1055
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001056 gspca_frame_add(gspca_dev, pkt_type,
1057 NULL, 0);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001058 data += i + fr_h_sz;
1059 len -= i + fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001060 gspca_frame_add(gspca_dev, FIRST_PACKET,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001061 data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001062 return;
1063 }
1064 }
1065 }
Hans de Goedec437d652008-09-03 17:12:22 -03001066
1067 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1068 /* In raw mode we sometimes get some garbage after the frame
1069 ignore this */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001070 struct gspca_frame *frame;
1071 int used;
Hans de Goedec437d652008-09-03 17:12:22 -03001072 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1073
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001074 frame = gspca_get_i_frame(gspca_dev);
1075 if (frame == NULL) {
1076 gspca_dev->last_packet_type = DISCARD_PACKET;
1077 return;
1078 }
1079 used = frame->data_end - frame->data;
Hans de Goedec437d652008-09-03 17:12:22 -03001080 if (used + len > size)
1081 len = size - used;
1082 }
1083
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03001084 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001085}
1086
1087static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1088{
1089 struct sd *sd = (struct sd *) gspca_dev;
1090
1091 sd->brightness = val;
1092 if (gspca_dev->streaming)
1093 setbrightness(gspca_dev);
1094 return 0;
1095}
1096
1097static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1098{
1099 struct sd *sd = (struct sd *) gspca_dev;
1100
1101 *val = sd->brightness;
1102 return 0;
1103}
1104
Hans de Goededcef3232008-07-10 10:40:53 -03001105static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001106{
1107 struct sd *sd = (struct sd *) gspca_dev;
1108
Hans de Goededcef3232008-07-10 10:40:53 -03001109 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001111 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001112 return 0;
1113}
1114
Hans de Goededcef3232008-07-10 10:40:53 -03001115static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001116{
1117 struct sd *sd = (struct sd *) gspca_dev;
1118
Hans de Goededcef3232008-07-10 10:40:53 -03001119 *val = sd->gain;
1120 return 0;
1121}
1122
1123static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1124{
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
1127 sd->exposure = val;
1128 if (gspca_dev->streaming)
1129 setexposure(gspca_dev);
1130 return 0;
1131}
1132
1133static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136
1137 *val = sd->exposure;
1138 return 0;
1139}
1140
1141static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
1145 sd->autogain = val;
1146 /* when switching to autogain set defaults to make sure
1147 we are on a valid point of the autogain gain /
1148 exposure knee graph, and give this change time to
1149 take effect before doing autogain. */
1150 if (sd->autogain) {
1151 sd->exposure = EXPOSURE_DEF;
1152 sd->gain = GAIN_DEF;
1153 if (gspca_dev->streaming) {
1154 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1155 setexposure(gspca_dev);
1156 setgain(gspca_dev);
1157 }
1158 }
1159
1160 return 0;
1161}
1162
1163static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1164{
1165 struct sd *sd = (struct sd *) gspca_dev;
1166
1167 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001168 return 0;
1169}
1170
Hans de Goede66f35822008-07-16 10:16:28 -03001171static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1172{
1173 struct sd *sd = (struct sd *) gspca_dev;
1174
1175 sd->freq = val;
1176 if (gspca_dev->streaming)
1177 setfreq(gspca_dev);
1178 return 0;
1179}
1180
1181static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1182{
1183 struct sd *sd = (struct sd *) gspca_dev;
1184
1185 *val = sd->freq;
1186 return 0;
1187}
1188
1189static int sd_querymenu(struct gspca_dev *gspca_dev,
1190 struct v4l2_querymenu *menu)
1191{
1192 switch (menu->id) {
1193 case V4L2_CID_POWER_LINE_FREQUENCY:
1194 switch (menu->index) {
1195 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1196 strcpy((char *) menu->name, "NoFliker");
1197 return 0;
1198 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1199 strcpy((char *) menu->name, "50 Hz");
1200 return 0;
1201 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1202 strcpy((char *) menu->name, "60 Hz");
1203 return 0;
1204 }
1205 break;
1206 }
1207 return -EINVAL;
1208}
1209
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001210/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001211static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001212 .name = MODULE_NAME,
1213 .ctrls = sd_ctrls,
1214 .nctrls = ARRAY_SIZE(sd_ctrls),
1215 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001216 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 .start = sd_start,
1218 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001220 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001221 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001222};
1223
1224/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001225#define SB(sensor, bridge) \
1226 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1227
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001228
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001229static __devinitdata struct usb_device_id device_table[] = {
Hans de Goedea94a5082008-09-04 16:22:55 -03001230 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
1231 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
Hans de Goede222a07f2008-09-03 17:12:20 -03001232#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedea94a5082008-09-04 16:22:55 -03001233 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001234 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1235 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001236#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001237 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001238#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001239 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1240 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1241 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1242 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1243 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001244#endif
Jean-Francois Moine29fbdf32008-11-07 04:53:28 -03001245 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goedef45f06b2008-09-03 17:12:21 -03001246 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001247#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001248 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001249#endif
Hans de Goede4cce1652008-09-04 16:22:57 -03001250 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1251#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1252 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1253#endif
1254 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001255 {}
1256};
1257MODULE_DEVICE_TABLE(usb, device_table);
1258
1259/* -- device connect -- */
1260static int sd_probe(struct usb_interface *intf,
1261 const struct usb_device_id *id)
1262{
1263 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1264 THIS_MODULE);
1265}
1266
1267static struct usb_driver sd_driver = {
1268 .name = MODULE_NAME,
1269 .id_table = device_table,
1270 .probe = sd_probe,
1271 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001272#ifdef CONFIG_PM
1273 .suspend = gspca_suspend,
1274 .resume = gspca_resume,
1275#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001276};
1277
1278/* -- module insert / remove -- */
1279static int __init sd_mod_init(void)
1280{
Alexey Klimovf69e9522009-01-01 13:02:07 -03001281 int ret;
1282 ret = usb_register(&sd_driver);
1283 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03001284 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001285 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001286 return 0;
1287}
1288static void __exit sd_mod_exit(void)
1289{
1290 usb_deregister(&sd_driver);
1291 PDEBUG(D_PROBE, "deregistered");
1292}
1293
1294module_init(sd_mod_init);
1295module_exit(sd_mod_exit);