blob: 7f67148a52304d87716277c697e8491969fde009 [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;
55
Hans de Goedead5ef80d2008-07-14 10:11:42 -030056 unsigned char gain;
57 unsigned char exposure;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030058 unsigned char brightness;
Hans de Goededcef3232008-07-10 10:40:53 -030059 unsigned char autogain;
60 unsigned char autogain_ignore_frames;
Hans de Goede6af492e2008-07-22 07:09:33 -030061 unsigned char frames_to_drop;
Hans de Goede66f35822008-07-16 10:16:28 -030062 unsigned char freq; /* light freq filter setting */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063
Hans de Goedef45f06b2008-09-03 17:12:21 -030064 __u8 bridge; /* Type of bridge */
65#define BRIDGE_101 0
66#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
67#define BRIDGE_103 1
68
69 __u8 sensor; /* Type of image sensor chip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030070#define SENSOR_HV7131R 0
71#define SENSOR_OV6650 1
72#define SENSOR_OV7630 2
Hans de Goede6af492e2008-07-22 07:09:33 -030073#define SENSOR_PAS106 3
74#define SENSOR_PAS202 4
75#define SENSOR_TAS5110 5
76#define SENSOR_TAS5130CXX 6
Hans de Goede6af492e2008-07-22 07:09:33 -030077 __u8 reg11;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030078};
79
Hans de Goedef45f06b2008-09-03 17:12:21 -030080typedef const __u8 sensor_init_t[8];
81
82struct sensor_data {
83 const __u8 *bridge_init[2];
84 int bridge_init_size[2];
85 sensor_init_t *sensor_init;
86 int sensor_init_size;
87 sensor_init_t *sensor_bridge_init[2];
88 int sensor_bridge_init_size[2];
89 int flags;
90 unsigned ctrl_dis;
91 __u8 sensor_addr;
92};
93
94/* sensor_data flags */
Jean-Francois Moine5da162e2008-07-26 14:17:23 -030095#define F_GAIN 0x01 /* has gain */
Hans de Goedee2ad2a52008-09-03 17:12:15 -030096#define F_SIF 0x02 /* sif or vga */
Hans de Goedec437d652008-09-03 17:12:22 -030097
98/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
99#define MODE_RAW 0x10 /* raw bayer mode */
Hans de Goede93627732008-09-04 16:20:12 -0300100#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300101
102/* ctrl_dis helper macros */
103#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
104#define NO_FREQ (1 << FREQ_IDX)
105#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300106
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300107#define COMP2 0x8f
108#define COMP 0xc7 /* 0x87 //0x07 */
109#define COMP1 0xc9 /* 0x89 //0x09 */
110
111#define MCK_INIT 0x63
112#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
113
114#define SYS_CLK 0x04
115
Hans de Goedef45f06b2008-09-03 17:12:21 -0300116#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
117 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
118{ \
119 .bridge_init = { bridge_1, bridge_3 }, \
120 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
121 .sensor_init = sensor, \
122 .sensor_init_size = sizeof(sensor), \
123 .sensor_bridge_init = { sensor_1, sensor_3,}, \
124 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
125 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
126}
127
Hans de Goededcef3232008-07-10 10:40:53 -0300128/* We calculate the autogain at the end of the transfer of a frame, at this
129 moment a frame with the old settings is being transmitted, and a frame is
130 being captured with the old settings. So if we adjust the autogain we must
131 ignore atleast the 2 next frames for the new settings to come into effect
132 before doing any other adjustments */
133#define AUTOGAIN_IGNORE_FRAMES 3
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300134#define AUTOGAIN_DEADZONE 1000
Hans de Goededcef3232008-07-10 10:40:53 -0300135#define DESIRED_AVG_LUM 7000
136
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300137/* V4L2 controls supported by the driver */
138static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
139static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goededcef3232008-07-10 10:40:53 -0300140static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
141static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
142static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
143static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
144static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
145static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede66f35822008-07-16 10:16:28 -0300146static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
147static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300148
149static struct ctrl sd_ctrls[] = {
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300150#define BRIGHTNESS_IDX 0
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151 {
152 {
153 .id = V4L2_CID_BRIGHTNESS,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Brightness",
156 .minimum = 0,
157 .maximum = 255,
158 .step = 1,
Hans de Goededcef3232008-07-10 10:40:53 -0300159#define BRIGHTNESS_DEF 127
160 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300161 },
162 .set = sd_setbrightness,
163 .get = sd_getbrightness,
164 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300165#define GAIN_IDX 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166 {
167 {
Hans de Goededcef3232008-07-10 10:40:53 -0300168 .id = V4L2_CID_GAIN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169 .type = V4L2_CTRL_TYPE_INTEGER,
Hans de Goededcef3232008-07-10 10:40:53 -0300170 .name = "Gain",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300172 .maximum = 255,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173 .step = 1,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300174#define GAIN_DEF 127
175#define GAIN_KNEE 200
Hans de Goededcef3232008-07-10 10:40:53 -0300176 .default_value = GAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177 },
Hans de Goededcef3232008-07-10 10:40:53 -0300178 .set = sd_setgain,
179 .get = sd_getgain,
180 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300181#define EXPOSURE_IDX 2
Hans de Goededcef3232008-07-10 10:40:53 -0300182 {
183 {
184 .id = V4L2_CID_EXPOSURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "Exposure",
Hans de Goedef4d52022008-07-15 09:36:42 -0300187#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
188#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
Hans de Goededcef3232008-07-10 10:40:53 -0300189 .minimum = 0,
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300190 .maximum = 255,
Hans de Goededcef3232008-07-10 10:40:53 -0300191 .step = 1,
192 .default_value = EXPOSURE_DEF,
193 .flags = 0,
194 },
195 .set = sd_setexposure,
196 .get = sd_getexposure,
197 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300198#define AUTOGAIN_IDX 3
Hans de Goededcef3232008-07-10 10:40:53 -0300199 {
200 {
201 .id = V4L2_CID_AUTOGAIN,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
203 .name = "Automatic Gain (and Exposure)",
204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300207#define AUTOGAIN_DEF 1
208 .default_value = AUTOGAIN_DEF,
Hans de Goededcef3232008-07-10 10:40:53 -0300209 .flags = 0,
210 },
211 .set = sd_setautogain,
212 .get = sd_getautogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300213 },
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300214#define FREQ_IDX 4
Hans de Goede66f35822008-07-16 10:16:28 -0300215 {
216 {
217 .id = V4L2_CID_POWER_LINE_FREQUENCY,
218 .type = V4L2_CTRL_TYPE_MENU,
219 .name = "Light frequency filter",
220 .minimum = 0,
221 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
222 .step = 1,
223#define FREQ_DEF 1
224 .default_value = FREQ_DEF,
225 },
226 .set = sd_setfreq,
227 .get = sd_getfreq,
228 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300229};
230
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300231static struct v4l2_pix_format vga_mode[] = {
Hans de Goedec437d652008-09-03 17:12:22 -0300232 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
233 .bytesperline = 160,
Hans de Goede93627732008-09-04 16:20:12 -0300234 .sizeimage = 160 * 120 * 5 / 4,
Hans de Goedec437d652008-09-03 17:12:22 -0300235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = 2 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300237 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
238 .bytesperline = 160,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300239 .sizeimage = 160 * 120 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300240 .colorspace = V4L2_COLORSPACE_SRGB,
241 .priv = 2},
242 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
243 .bytesperline = 320,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300244 .sizeimage = 320 * 240 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300245 .colorspace = V4L2_COLORSPACE_SRGB,
246 .priv = 1},
247 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
248 .bytesperline = 640,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300249 .sizeimage = 640 * 480 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300250 .colorspace = V4L2_COLORSPACE_SRGB,
251 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252};
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300253static struct v4l2_pix_format sif_mode[] = {
Hans de Goede93627732008-09-04 16:20:12 -0300254 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
255 .bytesperline = 160,
256 .sizeimage = 160 * 120,
257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
259 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
260 .bytesperline = 160,
261 .sizeimage = 160 * 120 * 5 / 4,
262 .colorspace = V4L2_COLORSPACE_SRGB,
263 .priv = 1 | MODE_REDUCED_SIF},
Hans de Goedec437d652008-09-03 17:12:22 -0300264 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
265 .bytesperline = 176,
Hans de Goede93627732008-09-04 16:20:12 -0300266 .sizeimage = 176 * 144 * 5 / 4,
Hans de Goedec437d652008-09-03 17:12:22 -0300267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 1 | MODE_RAW},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300269 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
270 .bytesperline = 176,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300271 .sizeimage = 176 * 144 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300272 .colorspace = V4L2_COLORSPACE_SRGB,
273 .priv = 1},
Hans de Goede93627732008-09-04 16:20:12 -0300274 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
275 .bytesperline = 320,
276 .sizeimage = 320 * 240 * 5 / 4,
277 .colorspace = V4L2_COLORSPACE_SRGB,
278 .priv = 0 | MODE_REDUCED_SIF},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300279 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
280 .bytesperline = 352,
Hans de Goede5c51518d2008-09-03 17:12:22 -0300281 .sizeimage = 352 * 288 * 5 / 4,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300282 .colorspace = V4L2_COLORSPACE_SRGB,
283 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300284};
285
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286static const __u8 initHv7131[] = {
287 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
288 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300289 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300290 0x28, 0x1e, 0x60, 0x8a, 0x20,
291 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
292};
293static const __u8 hv7131_sensor_init[][8] = {
294 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
295 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
296 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
297 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
298 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
299};
300static const __u8 initOv6650[] = {
301 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
302 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300303 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
Hans de Goede93627732008-09-04 16:20:12 -0300304 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300305};
306static const __u8 ov6650_sensor_init[][8] =
307{
308 /* Bright, contrast, etc are set througth SCBB interface.
309 * AVCAP on win2 do not send any data on this controls. */
310 /* Anyway, some registers appears to alter bright and constrat */
Hans de Goededcef3232008-07-10 10:40:53 -0300311
312 /* Reset sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300313 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300314 /* Set clock register 0x11 low nibble is clock divider */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300315 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
Hans de Goededcef3232008-07-10 10:40:53 -0300316 /* Next some unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
318/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
319 * THIS SET GREEN SCREEN
320 * (pixels could be innverted in decode kind of "brg",
321 * but blue wont be there. Avoid this data ... */
322 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
323 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
324 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
Hans de Goede722103e2008-07-17 10:24:47 -0300325 /* Enable rgb brightness control */
326 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
327 /* HDG: Note windows uses the line below, which sets both register 0x60
328 and 0x61 I believe these registers of the ov6650 are identical as
329 those of the ov7630, because if this is true the windows settings
330 add a bit additional red gain and a lot additional blue gain, which
331 matches my findings that the windows settings make blue much too
332 blue and red a little too red.
333 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
Hans de Goededcef3232008-07-10 10:40:53 -0300334 /* Some more unknown stuff */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300335 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
336 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337};
Hans de Goededcef3232008-07-10 10:40:53 -0300338
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300339static const __u8 initOv7630[] = {
340 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
341 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
Hans de Goedec437d652008-09-03 17:12:22 -0300342 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300343 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300344 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300345 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
346};
347static const __u8 initOv7630_3[] = {
348 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
349 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300350 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300351 0x28, 0x1e, /* H & V sizes r15 .. r16 */
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300352 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
353 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
354 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
355 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300356};
Hans de Goede6af492e2008-07-22 07:09:33 -0300357static const __u8 ov7630_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
359 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
360/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
Andoni Zubimendi794af522008-07-16 08:33:14 -0300361 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
363 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
365 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
366 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
368 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
Andoni Zubimendi794af522008-07-16 08:33:14 -0300369 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
370/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
372 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
373 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
374 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
375 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
376 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
377};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300378
Hans de Goedef45f06b2008-09-03 17:12:21 -0300379static const __u8 ov7630_sensor_init_3[][8] = {
380 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
381};
382
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383static const __u8 initPas106[] = {
384 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
385 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300386 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300387 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
Hans de Goede93627732008-09-04 16:20:12 -0300388 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300389};
390/* compression 0x86 mckinit1 0x2b */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300391static const __u8 pas106_sensor_init[][8] = {
392 /* Pixel Clock Divider 6 */
393 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
394 /* Frame Time MSB (also seen as 0x12) */
395 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
396 /* Frame Time LSB (also seen as 0x05) */
397 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
398 /* Shutter Time Line Offset (also seen as 0x6d) */
399 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
400 /* Shutter Time Pixel Offset (also seen as 0xb1) */
401 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
402 /* Black Level Subtract Sign (also seen 0x00) */
403 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
404 /* Black Level Subtract Level (also seen 0x01) */
405 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
406 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
407 /* Color Gain B Pixel 5 a */
408 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
409 /* Color Gain G1 Pixel 1 5 */
410 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
411 /* Color Gain G2 Pixel 1 0 5 */
412 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
413 /* Color Gain R Pixel 3 1 */
414 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
415 /* Color GainH Pixel */
416 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
417 /* Global Gain */
418 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
419 /* Contrast */
420 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
421 /* H&V synchro polarity */
422 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
423 /* ?default */
424 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
425 /* DAC scale */
426 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
427 /* ?default */
428 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
429 /* Validate Settings */
430 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300431};
Hans de Goedef45f06b2008-09-03 17:12:21 -0300432
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300433static const __u8 initPas202[] = {
434 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
435 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300436 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300437 0x28, 0x1e, 0x28, 0x89, 0x20,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300438 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
439};
440static const __u8 pas202_sensor_init[][8] = {
441 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
442 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
443 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
444 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
445 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
446 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
450 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
451 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
452 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
453
454 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
455 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
456 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
457 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
458 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
459 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
460 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
461 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
462};
463
464static const __u8 initTas5110[] = {
465 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
466 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300467 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300468 0x16, 0x12, 0x60, 0x86, 0x2b,
469 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
470};
471static const __u8 tas5110_sensor_init[][8] = {
472 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
473 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
474 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
475};
476
477static const __u8 initTas5130[] = {
478 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
479 0x00, 0x00,
Hans de Goedec437d652008-09-03 17:12:22 -0300480 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300481 0x28, 0x1e, 0x60, COMP, MCK_INIT,
482 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
483};
484static const __u8 tas5130_sensor_init[][8] = {
485/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
486 * shutter 0x47 short exposure? */
487 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
488 /* shutter 0x01 long exposure */
489 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
490};
491
Hans de Goedef45f06b2008-09-03 17:12:21 -0300492struct sensor_data sensor_data[] = {
493SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300494SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
Hans de Goedef45f06b2008-09-03 17:12:21 -0300495SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
496 F_GAIN, 0, 0x21),
497SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
498 0),
Hans de Goede93627732008-09-04 16:20:12 -0300499SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300500 NO_EXPO|NO_FREQ, 0),
Hans de Goede93627732008-09-04 16:20:12 -0300501SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
Hans de Goedef45f06b2008-09-03 17:12:21 -0300502 NO_BRIGHTNESS|NO_FREQ, 0),
503SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
504 0),
505};
506
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300507/* get one byte in gspca_dev->usb_buf */
508static void reg_r(struct gspca_dev *gspca_dev,
509 __u16 value)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300510{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300511 usb_control_msg(gspca_dev->dev,
512 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513 0, /* request */
514 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
515 value,
516 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300517 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300518 500);
519}
520
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300521static void reg_w(struct gspca_dev *gspca_dev,
522 __u16 value,
523 const __u8 *buffer,
524 int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525{
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300526#ifdef GSPCA_DEBUG
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300527 if (len > USB_BUF_SZ) {
Hans de Goede0d2a7222008-07-03 08:15:22 -0300528 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
529 return;
530 }
531#endif
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532 memcpy(gspca_dev->usb_buf, buffer, len);
533 usb_control_msg(gspca_dev->dev,
534 usb_sndctrlpipe(gspca_dev->dev, 0),
535 0x08, /* request */
536 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
537 value,
538 0, /* index */
539 gspca_dev->usb_buf, len,
540 500);
541}
542
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544{
545 int retry = 60;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300546
547 /* is i2c ready */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300548 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549 while (retry--) {
550 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300551 reg_r(gspca_dev, 0x08);
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300552 if (gspca_dev->usb_buf[0] & 0x04) {
553 if (gspca_dev->usb_buf[0] & 0x08)
554 return -1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 return 0;
Andoni Zubimendib7474cf92008-07-16 08:40:30 -0300556 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 }
558 return -1;
559}
560
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300561static void i2c_w_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562 const __u8 buffer[][8], int len)
563{
564 for (;;) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300565 reg_w(gspca_dev, 0x08, *buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566 len -= 8;
567 if (len <= 0)
568 break;
569 buffer++;
570 }
571}
572
573static void setbrightness(struct gspca_dev *gspca_dev)
574{
575 struct sd *sd = (struct sd *) gspca_dev;
576 __u8 value;
577
578 switch (sd->sensor) {
Hans de Goedea975a522008-07-16 15:29:11 -0300579 case SENSOR_OV6650:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300580 case SENSOR_OV7630: {
581 __u8 i2cOV[] =
Hans de Goedea975a522008-07-16 15:29:11 -0300582 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300583
584 /* change reg 0x06 */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300585 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586 i2cOV[3] = sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300587 if (i2c_w(gspca_dev, i2cOV) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588 goto err;
589 break;
590 }
591 case SENSOR_PAS106: {
592 __u8 i2c1[] =
593 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
594
595 i2c1[3] = sd->brightness >> 3;
596 i2c1[2] = 0x0e;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300597 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300598 goto err;
599 i2c1[3] = 0x01;
600 i2c1[2] = 0x13;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300601 if (i2c_w(gspca_dev, i2c1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300602 goto err;
603 break;
604 }
605 case SENSOR_PAS202: {
606 /* __u8 i2cpexpo1[] =
607 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
608 __u8 i2cpexpo[] =
609 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
610 __u8 i2cp202[] =
611 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
612 static __u8 i2cpdoit[] =
613 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
614
615 /* change reg 0x10 */
616 i2cpexpo[4] = 0xff - sd->brightness;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300619/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620 goto err; */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300621 if (i2c_w(gspca_dev, i2cpexpo) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300622 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300623 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624 goto err;
625 i2cp202[3] = sd->brightness >> 3;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300626 if (i2c_w(gspca_dev, i2cp202) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627 goto err;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628 if (i2c_w(gspca_dev, i2cpdoit) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629 goto err;
630 break;
631 }
Hans de Goededcef3232008-07-10 10:40:53 -0300632 case SENSOR_TAS5130CXX: {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633 __u8 i2c[] =
634 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
635
636 value = 0xff - sd->brightness;
637 i2c[4] = value;
638 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300639 if (i2c_w(gspca_dev, i2c) < 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 goto err;
641 break;
642 }
643 }
644 return;
645err:
646 PDEBUG(D_ERR, "i2c error brightness");
647}
Hans de Goededcef3232008-07-10 10:40:53 -0300648
649static void setsensorgain(struct gspca_dev *gspca_dev)
650{
651 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedea975a522008-07-16 15:29:11 -0300652 unsigned char gain = sd->gain;
Hans de Goededcef3232008-07-10 10:40:53 -0300653
654 switch (sd->sensor) {
655
656 case SENSOR_TAS5110: {
657 __u8 i2c[] =
658 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
659
Hans de Goedea975a522008-07-16 15:29:11 -0300660 i2c[4] = 255 - gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300661 if (i2c_w(gspca_dev, i2c) < 0)
Hans de Goededcef3232008-07-10 10:40:53 -0300662 goto err;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300663 break;
664 }
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300665
Hans de Goedea975a522008-07-16 15:29:11 -0300666 case SENSOR_OV6650:
667 gain >>= 1;
668 /* fall thru */
Hans de Goede6af492e2008-07-22 07:09:33 -0300669 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300670 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
Andoni Zubimendi794af522008-07-16 08:33:14 -0300671
Hans de Goedef45f06b2008-09-03 17:12:21 -0300672 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goedea975a522008-07-16 15:29:11 -0300673 i2c[3] = gain >> 2;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300674 if (i2c_w(gspca_dev, i2c) < 0)
675 goto err;
676 break;
677 }
Hans de Goededcef3232008-07-10 10:40:53 -0300678 }
679 return;
680err:
681 PDEBUG(D_ERR, "i2c error gain");
682}
683
684static void setgain(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685{
686 struct sd *sd = (struct sd *) gspca_dev;
687 __u8 gain;
688 __u8 rgb_value;
689
Hans de Goedead5ef80d2008-07-14 10:11:42 -0300690 gain = sd->gain >> 4;
Hans de Goededcef3232008-07-10 10:40:53 -0300691
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692 /* red and blue gain */
693 rgb_value = gain << 4 | gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300694 reg_w(gspca_dev, 0x10, &rgb_value, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 /* green gain */
696 rgb_value = gain;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300697 reg_w(gspca_dev, 0x11, &rgb_value, 1);
Hans de Goededcef3232008-07-10 10:40:53 -0300698
Hans de Goedef45f06b2008-09-03 17:12:21 -0300699 if (sensor_data[sd->sensor].flags & F_GAIN)
Hans de Goededcef3232008-07-10 10:40:53 -0300700 setsensorgain(gspca_dev);
701}
702
703static void setexposure(struct gspca_dev *gspca_dev)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goededcef3232008-07-10 10:40:53 -0300706
707 switch (sd->sensor) {
708 case SENSOR_TAS5110: {
709 __u8 reg;
710
711 /* register 19's high nibble contains the sn9c10x clock divider
712 The high nibble configures the no fps according to the
713 formula: 60 / high_nibble. With a maximum of 30 fps */
Hans de Goedef4d52022008-07-15 09:36:42 -0300714 reg = 120 * sd->exposure / 1000;
715 if (reg < 2)
716 reg = 2;
717 else if (reg > 15)
Hans de Goededcef3232008-07-10 10:40:53 -0300718 reg = 15;
719 reg = (reg << 4) | 0x0b;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300720 reg_w(gspca_dev, 0x19, &reg, 1);
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300721 break;
722 }
Hans de Goedea975a522008-07-16 15:29:11 -0300723 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300724 case SENSOR_OV7630: {
Hans de Goedea975a522008-07-16 15:29:11 -0300725 /* The ov6650 / ov7630 have 2 registers which both influence
726 exposure, register 11, whose low nibble sets the nr off fps
Hans de Goedef4d52022008-07-15 09:36:42 -0300727 according to: fps = 30 / (low_nibble + 1)
728
729 The fps configures the maximum exposure setting, but it is
730 possible to use less exposure then what the fps maximum
731 allows by setting register 10. register 10 configures the
732 actual exposure as quotient of the full exposure, with 0
733 being no exposure at all (not very usefull) and reg10_max
734 being max exposure possible at that framerate.
735
736 The code maps our 0 - 510 ms exposure ctrl to these 2
737 registers, trying to keep fps as high as possible.
738 */
Hans de Goede6af492e2008-07-22 07:09:33 -0300739 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
740 int reg10, reg11, reg10_max;
741
Hans de Goede66f35822008-07-16 10:16:28 -0300742 /* ov6645 datasheet says reg10_max is 9a, but that uses
743 tline * 2 * reg10 as formula for calculating texpo, the
744 ov6650 probably uses the same formula as the 7730 which uses
745 tline * 4 * reg10, which explains why the reg10max we've
746 found experimentally for the ov6650 is exactly half that of
Hans de Goedea975a522008-07-16 15:29:11 -0300747 the ov6645. The ov7630 datasheet says the max is 0x41. */
Hans de Goede6af492e2008-07-22 07:09:33 -0300748 if (sd->sensor == SENSOR_OV6650) {
749 reg10_max = 0x4d;
750 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
751 } else
752 reg10_max = 0x41;
Hans de Goedef4d52022008-07-15 09:36:42 -0300753
754 reg11 = (60 * sd->exposure + 999) / 1000;
755 if (reg11 < 1)
756 reg11 = 1;
757 else if (reg11 > 16)
758 reg11 = 16;
759
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300760 /* In 640x480, if the reg11 has less than 3, the image is
761 unstable (not enough bandwidth). */
762 if (gspca_dev->width == 640 && reg11 < 3)
763 reg11 = 3;
764
Hans de Goedef4d52022008-07-15 09:36:42 -0300765 /* frame exposure time in ms = 1000 * reg11 / 30 ->
766 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
767 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
Hans de Goedea975a522008-07-16 15:29:11 -0300768
769 /* Don't allow this to get below 10 when using autogain, the
770 steps become very large (relatively) when below 10 causing
771 the image to oscilate from much too dark, to much too bright
772 and back again. */
773 if (sd->autogain && reg10 < 10)
774 reg10 = 10;
Hans de Goedef4d52022008-07-15 09:36:42 -0300775 else if (reg10 > reg10_max)
776 reg10 = reg10_max;
777
778 /* Write reg 10 and reg11 low nibble */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300779 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Andoni Zubimendi794af522008-07-16 08:33:14 -0300780 i2c[3] = reg10;
781 i2c[4] |= reg11 - 1;
Hans de Goede6af492e2008-07-22 07:09:33 -0300782
783 /* If register 11 didn't change, don't change it */
784 if (sd->reg11 == reg11 )
785 i2c[0] = 0xa0;
786
787 if (i2c_w(gspca_dev, i2c) == 0)
788 sd->reg11 = reg11;
789 else
Andoni Zubimendi794af522008-07-16 08:33:14 -0300790 PDEBUG(D_ERR, "i2c error exposure");
791 break;
792 }
Hans de Goededcef3232008-07-10 10:40:53 -0300793 }
794}
795
Hans de Goede66f35822008-07-16 10:16:28 -0300796static void setfreq(struct gspca_dev *gspca_dev)
797{
798 struct sd *sd = (struct sd *) gspca_dev;
799
800 switch (sd->sensor) {
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300801 case SENSOR_OV6650:
Hans de Goede6af492e2008-07-22 07:09:33 -0300802 case SENSOR_OV7630: {
Hans de Goede66f35822008-07-16 10:16:28 -0300803 /* Framerate adjust register for artificial light 50 hz flicker
Hans de Goede6af492e2008-07-22 07:09:33 -0300804 compensation, for the ov6650 this is identical to ov6630
805 0x2b register, see ov6630 datasheet.
806 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
Andoni Zubimendid87616f2008-07-17 05:35:52 -0300807 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
Hans de Goede66f35822008-07-16 10:16:28 -0300808 switch (sd->freq) {
809 default:
810/* case 0: * no filter*/
811/* case 2: * 60 hz */
812 i2c[3] = 0;
813 break;
814 case 1: /* 50 hz */
Hans de Goede722103e2008-07-17 10:24:47 -0300815 i2c[3] = (sd->sensor == SENSOR_OV6650)
816 ? 0x4f : 0x8a;
Hans de Goede66f35822008-07-16 10:16:28 -0300817 break;
818 }
Hans de Goedef45f06b2008-09-03 17:12:21 -0300819 i2c[1] = sensor_data[sd->sensor].sensor_addr;
Hans de Goede66f35822008-07-16 10:16:28 -0300820 if (i2c_w(gspca_dev, i2c) < 0)
821 PDEBUG(D_ERR, "i2c error setfreq");
822 break;
823 }
824 }
825}
826
Hans de Goededcef3232008-07-10 10:40:53 -0300827static void do_autogain(struct gspca_dev *gspca_dev)
828{
829 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
835 if (sd->autogain_ignore_frames > 0)
836 sd->autogain_ignore_frames--;
837 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
838 sd->brightness * DESIRED_AVG_LUM / 127,
Hans de Goedea975a522008-07-16 15:29:11 -0300839 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
840 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
841 (int)sd->gain, (int)sd->exposure);
Hans de Goededcef3232008-07-10 10:40:53 -0300842 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
Hans de Goedea975a522008-07-16 15:29:11 -0300843 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844}
845
846/* this function is called at probe time */
847static int sd_config(struct gspca_dev *gspca_dev,
848 const struct usb_device_id *id)
849{
850 struct sd *sd = (struct sd *) gspca_dev;
851 struct cam *cam;
Hans de Goede65f33392008-09-03 17:12:15 -0300852
853 reg_r(gspca_dev, 0x00);
854 if (gspca_dev->usb_buf[0] != 0x10)
855 return -ENODEV;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300856
Jean-Francois Moine5da162e2008-07-26 14:17:23 -0300857 /* copy the webcam info from the device id */
Hans de Goedef45f06b2008-09-03 17:12:21 -0300858 sd->sensor = id->driver_info >> 8;
859 sd->bridge = id->driver_info & 0xff;
860 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300861
862 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 cam->epaddr = 0x01;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300864 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 cam->cam_mode = vga_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300866 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867 } else {
868 cam->cam_mode = sif_mode;
Andoni Zubimendi51fc8e32008-07-10 11:12:24 -0300869 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870 }
Hans de Goededcef3232008-07-10 10:40:53 -0300871 sd->brightness = BRIGHTNESS_DEF;
872 sd->gain = GAIN_DEF;
873 sd->exposure = EXPOSURE_DEF;
Hans de Goedee2ad2a52008-09-03 17:12:15 -0300874 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
875 sd->autogain = 0; /* Disable do_autogain callback */
876 else
877 sd->autogain = AUTOGAIN_DEF;
Hans de Goede12ff9122008-07-17 10:30:56 -0300878 sd->freq = FREQ_DEF;
Hans de Goede6af492e2008-07-22 07:09:33 -0300879
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880 return 0;
881}
882
Jean-Francois Moine012d6b02008-09-03 17:12:16 -0300883/* this function is called at probe and resume time */
884static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885{
Hans de Goede271315a2008-09-03 17:12:19 -0300886 const __u8 stop = 0x09; /* Disable stream turn of LED */
887
888 reg_w(gspca_dev, 0x01, &stop, 1);
889
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 return 0;
891}
892
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893/* -- start the camera -- */
894static void sd_start(struct gspca_dev *gspca_dev)
895{
896 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede93627732008-09-04 16:20:12 -0300897 struct cam *cam = &gspca_dev->cam;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300898 int mode, l;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 const __u8 *sn9c10x;
Hans de Goede93627732008-09-04 16:20:12 -0300900 __u8 reg12_19[8];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300901
Hans de Goede93627732008-09-04 16:20:12 -0300902 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300903 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
904 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
Hans de Goede93627732008-09-04 16:20:12 -0300905 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
906 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300907 /* Special cases where reg 17 and or 19 value depends on mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 switch (sd->sensor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909 case SENSOR_PAS202:
Hans de Goede93627732008-09-04 16:20:12 -0300910 reg12_19[5] = mode ? 0x24 : 0x20;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300911 break;
Hans de Goedef45f06b2008-09-03 17:12:21 -0300912 case SENSOR_TAS5130CXX:
913 /* probably not mode specific at all most likely the upper
914 nibble of 0x19 is exposure (clock divider) just as with
915 the tas5110, we need someone to test this. */
Hans de Goede93627732008-09-04 16:20:12 -0300916 reg12_19[7] = mode ? 0x23 : 0x43;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300917 break;
918 }
Hans de Goedec437d652008-09-03 17:12:22 -0300919 /* Disable compression when the raw bayer format has been selected */
Hans de Goede93627732008-09-04 16:20:12 -0300920 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
921 reg12_19[6] &= ~0x80;
922
923 /* Vga mode emulation on SIF sensor? */
924 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
925 reg12_19[0] += 16; /* 0x12: hstart adjust */
926 reg12_19[1] += 24; /* 0x13: vstart adjust */
927 reg12_19[3] = 320 / 16; /* 0x15: hsize */
928 reg12_19[4] = 240 / 16; /* 0x16: vsize */
929 }
Hans de Goede6af492e2008-07-22 07:09:33 -0300930
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 /* reg 0x01 bit 2 video transfert on */
Hans de Goedefff42052008-07-23 07:04:39 -0300932 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 /* reg 0x17 SensorClk enable inv Clk 0x60 */
Hans de Goedefff42052008-07-23 07:04:39 -0300934 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 /* Set the registers from the template */
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300936 reg_w(gspca_dev, 0x01, sn9c10x, l);
Hans de Goedef45f06b2008-09-03 17:12:21 -0300937
938 /* Init the sensor */
939 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
940 sensor_data[sd->sensor].sensor_init_size);
941 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
942 i2c_w_vector(gspca_dev,
943 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
944 sensor_data[sd->sensor].sensor_bridge_init_size[
945 sd->bridge]);
946
Hans de Goede3647fea2008-07-15 05:36:30 -0300947 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
Hans de Goede93627732008-09-04 16:20:12 -0300948 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300949 /* compression register */
Hans de Goede93627732008-09-04 16:20:12 -0300950 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300951 /* H_start */
Hans de Goede93627732008-09-04 16:20:12 -0300952 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
Andoni Zubimendi794af522008-07-16 08:33:14 -0300953 /* V_START */
Hans de Goede93627732008-09-04 16:20:12 -0300954 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 /* reset 0x17 SensorClk enable inv Clk 0x60 */
956 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
Hans de Goede93627732008-09-04 16:20:12 -0300957 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300958 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
Hans de Goede93627732008-09-04 16:20:12 -0300959 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300961 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 /* Enable video transfert */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300963 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964 /* Compression */
Hans de Goede93627732008-09-04 16:20:12 -0300965 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 msleep(20);
967
Hans de Goede6af492e2008-07-22 07:09:33 -0300968 sd->reg11 = -1;
969
Hans de Goededcef3232008-07-10 10:40:53 -0300970 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300971 setbrightness(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300972 setexposure(gspca_dev);
Hans de Goede66f35822008-07-16 10:16:28 -0300973 setfreq(gspca_dev);
Hans de Goededcef3232008-07-10 10:40:53 -0300974
Hans de Goede6af492e2008-07-22 07:09:33 -0300975 sd->frames_to_drop = 0;
Hans de Goededcef3232008-07-10 10:40:53 -0300976 sd->autogain_ignore_frames = 0;
977 atomic_set(&sd->avg_lum, -1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978}
979
980static void sd_stopN(struct gspca_dev *gspca_dev)
981{
Hans de Goedef45f06b2008-09-03 17:12:21 -0300982 sd_init(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300983}
984
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985static void sd_pkt_scan(struct gspca_dev *gspca_dev,
986 struct gspca_frame *frame, /* target */
987 unsigned char *data, /* isoc packet */
988 int len) /* iso packet length */
989{
Hans de Goede0d2a7222008-07-03 08:15:22 -0300990 int i;
Hans de Goededcef3232008-07-10 10:40:53 -0300991 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedec437d652008-09-03 17:12:22 -0300992 struct cam *cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993
Hans de Goedec36260ee2008-07-16 09:56:07 -0300994 /* frames start with:
995 * ff ff 00 c4 c4 96 synchro
996 * 00 (unknown)
997 * xx (frame sequence / size / compression)
998 * (xx) (idem - extra byte for sn9c103)
999 * ll mm brightness sum inside auto exposure
1000 * ll mm brightness sum outside auto exposure
1001 * (xx xx xx xx xx) audio values for snc103
1002 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001003 if (len > 6 && len < 24) {
Hans de Goede0d2a7222008-07-03 08:15:22 -03001004 for (i = 0; i < len - 6; i++) {
1005 if (data[0 + i] == 0xff
1006 && data[1 + i] == 0xff
1007 && data[2 + i] == 0x00
1008 && data[3 + i] == 0xc4
1009 && data[4 + i] == 0xc4
1010 && data[5 + i] == 0x96) { /* start of frame */
Hans de Goede6af492e2008-07-22 07:09:33 -03001011 int lum = -1;
1012 int pkt_type = LAST_PACKET;
Hans de Goedef45f06b2008-09-03 17:12:21 -03001013 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1014 18 : 12;
Hans de Goede6af492e2008-07-22 07:09:33 -03001015
Hans de Goedef45f06b2008-09-03 17:12:21 -03001016 if (len - i < fr_h_sz) {
Hans de Goedec36260ee2008-07-16 09:56:07 -03001017 PDEBUG(D_STREAM, "packet too short to"
1018 " get avg brightness");
Hans de Goedef45f06b2008-09-03 17:12:21 -03001019 } else if (sd->bridge == BRIDGE_103) {
Hans de Goede6af492e2008-07-22 07:09:33 -03001020 lum = data[i + 9] +
1021 (data[i + 10] << 8);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001022 } else {
1023 lum = data[i + 8] + (data[i + 9] << 8);
Hans de Goededcef3232008-07-10 10:40:53 -03001024 }
Hans de Goede6af492e2008-07-22 07:09:33 -03001025 if (lum == 0) {
1026 lum = -1;
1027 sd->frames_to_drop = 2;
1028 }
1029 atomic_set(&sd->avg_lum, lum);
1030
1031 if (sd->frames_to_drop) {
1032 sd->frames_to_drop--;
1033 pkt_type = DISCARD_PACKET;
1034 }
1035
1036 frame = gspca_frame_add(gspca_dev, pkt_type,
1037 frame, data, 0);
Hans de Goedef45f06b2008-09-03 17:12:21 -03001038 data += i + fr_h_sz;
1039 len -= i + fr_h_sz;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001040 gspca_frame_add(gspca_dev, FIRST_PACKET,
1041 frame, data, len);
1042 return;
1043 }
1044 }
1045 }
Hans de Goedec437d652008-09-03 17:12:22 -03001046
1047 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1048 /* In raw mode we sometimes get some garbage after the frame
1049 ignore this */
1050 int used = frame->data_end - frame->data;
1051 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1052
1053 if (used + len > size)
1054 len = size - used;
1055 }
1056
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057 gspca_frame_add(gspca_dev, INTER_PACKET,
1058 frame, data, len);
1059}
1060
1061static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1062{
1063 struct sd *sd = (struct sd *) gspca_dev;
1064
1065 sd->brightness = val;
1066 if (gspca_dev->streaming)
1067 setbrightness(gspca_dev);
1068 return 0;
1069}
1070
1071static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1072{
1073 struct sd *sd = (struct sd *) gspca_dev;
1074
1075 *val = sd->brightness;
1076 return 0;
1077}
1078
Hans de Goededcef3232008-07-10 10:40:53 -03001079static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001080{
1081 struct sd *sd = (struct sd *) gspca_dev;
1082
Hans de Goededcef3232008-07-10 10:40:53 -03001083 sd->gain = val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001084 if (gspca_dev->streaming)
Hans de Goededcef3232008-07-10 10:40:53 -03001085 setgain(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001086 return 0;
1087}
1088
Hans de Goededcef3232008-07-10 10:40:53 -03001089static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090{
1091 struct sd *sd = (struct sd *) gspca_dev;
1092
Hans de Goededcef3232008-07-10 10:40:53 -03001093 *val = sd->gain;
1094 return 0;
1095}
1096
1097static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1098{
1099 struct sd *sd = (struct sd *) gspca_dev;
1100
1101 sd->exposure = val;
1102 if (gspca_dev->streaming)
1103 setexposure(gspca_dev);
1104 return 0;
1105}
1106
1107static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110
1111 *val = sd->exposure;
1112 return 0;
1113}
1114
1115static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1116{
1117 struct sd *sd = (struct sd *) gspca_dev;
1118
1119 sd->autogain = val;
1120 /* when switching to autogain set defaults to make sure
1121 we are on a valid point of the autogain gain /
1122 exposure knee graph, and give this change time to
1123 take effect before doing autogain. */
1124 if (sd->autogain) {
1125 sd->exposure = EXPOSURE_DEF;
1126 sd->gain = GAIN_DEF;
1127 if (gspca_dev->streaming) {
1128 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1129 setexposure(gspca_dev);
1130 setgain(gspca_dev);
1131 }
1132 }
1133
1134 return 0;
1135}
1136
1137static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1138{
1139 struct sd *sd = (struct sd *) gspca_dev;
1140
1141 *val = sd->autogain;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142 return 0;
1143}
1144
Hans de Goede66f35822008-07-16 10:16:28 -03001145static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1146{
1147 struct sd *sd = (struct sd *) gspca_dev;
1148
1149 sd->freq = val;
1150 if (gspca_dev->streaming)
1151 setfreq(gspca_dev);
1152 return 0;
1153}
1154
1155static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1156{
1157 struct sd *sd = (struct sd *) gspca_dev;
1158
1159 *val = sd->freq;
1160 return 0;
1161}
1162
1163static int sd_querymenu(struct gspca_dev *gspca_dev,
1164 struct v4l2_querymenu *menu)
1165{
1166 switch (menu->id) {
1167 case V4L2_CID_POWER_LINE_FREQUENCY:
1168 switch (menu->index) {
1169 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1170 strcpy((char *) menu->name, "NoFliker");
1171 return 0;
1172 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1173 strcpy((char *) menu->name, "50 Hz");
1174 return 0;
1175 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1176 strcpy((char *) menu->name, "60 Hz");
1177 return 0;
1178 }
1179 break;
1180 }
1181 return -EINVAL;
1182}
1183
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184/* sub-driver description */
Hans de Goededcef3232008-07-10 10:40:53 -03001185static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186 .name = MODULE_NAME,
1187 .ctrls = sd_ctrls,
1188 .nctrls = ARRAY_SIZE(sd_ctrls),
1189 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001190 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 .start = sd_start,
1192 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001193 .pkt_scan = sd_pkt_scan,
Hans de Goede66f35822008-07-16 10:16:28 -03001194 .querymenu = sd_querymenu,
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001195 .dq_callback = do_autogain,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001196};
1197
1198/* -- module initialisation -- */
Hans de Goedef45f06b2008-09-03 17:12:21 -03001199#define SB(sensor, bridge) \
1200 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1201
Hans de Goedee2ad2a52008-09-03 17:12:15 -03001202
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001203static __devinitdata struct usb_device_id device_table[] = {
Hans de Goede222a07f2008-09-03 17:12:20 -03001204#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001205 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)},
1206 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)},
1207 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)},
1208 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1209 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
Hans de Goede5de39b22008-07-17 10:34:28 -03001210#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001211 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001212#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001213 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1214 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1215 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1216 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1217 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1218 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001219#endif
Hans de Goedef45f06b2008-09-03 17:12:21 -03001220 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
Hans de Goede222a07f2008-09-03 17:12:20 -03001221#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
Hans de Goedef45f06b2008-09-03 17:12:21 -03001222 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1223 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1224 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1225 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001226#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001227 {}
1228};
1229MODULE_DEVICE_TABLE(usb, device_table);
1230
1231/* -- device connect -- */
1232static int sd_probe(struct usb_interface *intf,
1233 const struct usb_device_id *id)
1234{
1235 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1236 THIS_MODULE);
1237}
1238
1239static struct usb_driver sd_driver = {
1240 .name = MODULE_NAME,
1241 .id_table = device_table,
1242 .probe = sd_probe,
1243 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001244#ifdef CONFIG_PM
1245 .suspend = gspca_suspend,
1246 .resume = gspca_resume,
1247#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001248};
1249
1250/* -- module insert / remove -- */
1251static int __init sd_mod_init(void)
1252{
1253 if (usb_register(&sd_driver) < 0)
1254 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001255 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001256 return 0;
1257}
1258static void __exit sd_mod_exit(void)
1259{
1260 usb_deregister(&sd_driver);
1261 PDEBUG(D_PROBE, "deregistered");
1262}
1263
1264module_init(sd_mod_init);
1265module_exit(sd_mod_exit);