blob: 33a3df1f69150f6200635839ddc2ff92e5e81c46 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030027MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
35 int avg_lum;
36 unsigned int exposure;
37
38 unsigned short brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 signed char ag_cnt;
44#define AG_CNT_START 13
45
46 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030047 unsigned char bridge;
48#define BRIDGE_SN9C102P 0
49#define BRIDGE_SN9C105 1
50#define BRIDGE_SN9C110 2
51#define BRIDGE_SN9C120 3
52#define BRIDGE_SN9C325 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030053 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_MI0360 1
56#define SENSOR_MO4000 2
57#define SENSOR_OV7648 3
58#define SENSOR_OV7660 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030059 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030060};
61
62/* V4L2 controls supported by the driver */
63static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030073 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 0xffff,
80 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030081#define BRIGHTNESS_DEF 0x7fff
82 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030083 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030087 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 127,
94 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030095#define CONTRAST_DEF 63
96 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030097 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 255,
108 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300109#define COLOR_DEF 127
110 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 {
116 {
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300123#define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 },
126 .set = sd_setautogain,
127 .get = sd_getautogain,
128 },
129};
130
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300131static struct v4l2_pix_format vga_mode[] = {
132 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 160,
134 .sizeimage = 160 * 120 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 320,
139 .sizeimage = 320 * 240 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
142 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 640,
144 .sizeimage = 640 * 480 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300147};
148
149/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300150static const __u8 sn_hv7131[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300151/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300152 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300153/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300154 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300156 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300157/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300159};
160
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300161static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300163 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300164/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300165 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300166/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300167 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300168/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300170};
171
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300172static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300174 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300175/* reg9 rega regb regc regd rege regf reg10 reg11*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300176 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300177/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300178 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300180 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
182 0xd3, 0xdf, 0xea, 0xf5
183};
184
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300185static const __u8 sn_ov7648[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300186 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
187 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
188 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
189};
190
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300191static const __u8 sn_ov7660[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
193 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
194/* reg9 rega regb regc regd rege regf reg10 reg11*/
195 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
196/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300197 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300198/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
200};
201
202/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300203static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 sn_hv7131,
205 sn_mi0360,
206 sn_mo4000,
207 sn_ov7648,
208 sn_ov7660
209};
210
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300211static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300212 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
213 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
214};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300215static const __u8 regsn20_sn9c120[] = {
216 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
217 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
218};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300219static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300220 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
221 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
222};
223
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300224static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300225 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
226 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
227/* 0x00, 0x00, 0x00, 0x00, 0x00 */
228 0xf7, 0x0f, 0x0a, 0x00, 0x00
229};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300230static const __u8 reg84_sn9c120_1[] = {
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x0c, 0x00, 0x00
234};
235static const __u8 reg84_sn9c120_2[] = {
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x0c, 0x02, 0x3b
239};
240static const __u8 reg84_sn9c120_3[] = {
241 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
242 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
243 0xf5, 0x0f, 0x0c, 0x02, 0x3b
244};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300245static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300246 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
247 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
248 0xf8, 0x0f, 0x00, 0x00, 0x00
249};
250
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300251static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
253 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
254 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
255 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
256 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
258 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
259
260 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
262 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
263 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
264 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
267 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
268
269 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
270 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
271 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
272 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
274
275 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
278 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300280 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300281};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300282static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300283 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
285 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
287 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
288 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
289 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
290 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
292 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
305 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
306 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
308 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
309 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
310 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
311 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
312 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
313 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
315 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
316
317 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
318 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
319 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
320 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
321 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
322
323 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
324 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
325 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
326 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
327
328 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
329 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
330/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
331/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
332 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
333 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300334 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300335};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300336static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300357 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300359static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300360 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300361/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300362 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
363 /* Outformat ?? rawRGB */
364 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300365 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
366/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367 /* GAIN BLUE RED VREF */
368 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
369 /* COM 1 BAVE GEAVE AECHH */
370 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
371 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300372 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
373/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374 /* AECH CLKRC COM7 COM8 */
375 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
376 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
377 /* HSTART HSTOP VSTRT VSTOP */
378 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
379 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
380 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
381 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300382 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
383/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384 /* AEW AEB VPT BBIAS */
385 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
386 /* GbBIAS RSVD EXHCH EXHCL */
387 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
388 /* RBIAS ADVFL ASDVFH YAVE */
389 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
390 /* HSYST HSYEN HREF */
391 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
392 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
393 /* ADC ACOM OFON TSLB */
394 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
395 /* COM11 COM12 COM13 COM14 */
396 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
397 /* EDGE COM15 COM16 COM17 */
398 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
399 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
400 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
402 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
403 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
404 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
405 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
406 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
408 /* LCC1 LCC2 LCC3 LCC4 */
409 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
410 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
411 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
412 /* band gap reference [0..3] DBLV */
413 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
414 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
415 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
420 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
421 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
422 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
423/****** (some exchanges in the win trace) ******/
424 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
425 /* bits[3..0]reserved */
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
428 /* VREF vertical frame ctrl */
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
431 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300433/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
434 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
435 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300436/****** (some exchanges in the win trace) ******/
437 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
438 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
439 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
440 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300441 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300442/****** (some exchanges in the win trace) ******/
443/**********startsensor KO if changed !!****/
444 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
448/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300449 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300450};
451/* reg0x04 reg0x07 reg 0x10 */
452/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
453
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300454static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300455 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
456 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
459 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
460 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
461 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
462 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
464 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
465 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
466 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
467 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
468 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
469 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
471 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
472 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
473 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
474 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
475 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
476 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
477 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
478 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
479 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
480 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
481 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
482 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
483 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
484 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
486 * This is currently setting a
487 * blue tint, and some things more , i leave it here for future test if
488 * somene is having problems with color on this sensor
489 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
490 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
491 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
492 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
493 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
497 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
502 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
503 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
504 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
505 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
506/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300507 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508};
509
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300510static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
512 0x06, 0x08, 0x0A, 0x11,
513 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
514 0x19, 0x19, 0x17, 0x15,
515 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
516 0x21, 0x2E, 0x21, 0x23,
517 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
518 0x25, 0x29, 0x2C, 0x29,
519 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
520 0x17, 0x1B, 0x29, 0x29,
521 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
522 0x29, 0x29, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29
527};
528
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300529/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
530static void reg_r(struct gspca_dev *gspca_dev,
531 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300533 usb_control_msg(gspca_dev->dev,
534 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 0,
536 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
537 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300538 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300540 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541}
542
Jean-Francois Moine60017612008-07-18 08:46:19 -0300543static void reg_w1(struct gspca_dev *gspca_dev,
544 __u16 value,
545 __u8 data)
546{
547 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
548 gspca_dev->usb_buf[0] = data;
549 usb_control_msg(gspca_dev->dev,
550 usb_sndctrlpipe(gspca_dev->dev, 0),
551 0x08,
552 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
553 value,
554 0,
555 gspca_dev->usb_buf, 1,
556 500);
557}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300558static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300559 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300560 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300561 int len)
562{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300563 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
564 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300565 if (len <= sizeof gspca_dev->usb_buf) {
566 memcpy(gspca_dev->usb_buf, buffer, len);
567 usb_control_msg(gspca_dev->dev,
568 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569 0x08,
570 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
571 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300572 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300573 500);
574 } else {
575 __u8 *tmpbuf;
576
577 tmpbuf = kmalloc(len, GFP_KERNEL);
578 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300579 usb_control_msg(gspca_dev->dev,
580 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300581 0x08,
582 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
583 value, 0,
584 tmpbuf, len,
585 500);
586 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300587 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588}
589
Jean-Francois Moine60017612008-07-18 08:46:19 -0300590/* I2C write 1 byte */
591static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300592{
593 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300594
Jean-Francois Moine60017612008-07-18 08:46:19 -0300595 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
596 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
597 gspca_dev->usb_buf[1] = sd->i2c_base;
598 gspca_dev->usb_buf[2] = reg;
599 gspca_dev->usb_buf[3] = val;
600 gspca_dev->usb_buf[4] = 0;
601 gspca_dev->usb_buf[5] = 0;
602 gspca_dev->usb_buf[6] = 0;
603 gspca_dev->usb_buf[7] = 0x10;
604 usb_control_msg(gspca_dev->dev,
605 usb_sndctrlpipe(gspca_dev->dev, 0),
606 0x08,
607 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
608 0x08, /* value = i2c */
609 0,
610 gspca_dev->usb_buf, 8,
611 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300612}
613
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300614/* I2C write 8 bytes */
615static void i2c_w8(struct gspca_dev *gspca_dev,
616 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300618 memcpy(gspca_dev->usb_buf, buffer, 8);
619 usb_control_msg(gspca_dev->dev,
620 usb_sndctrlpipe(gspca_dev->dev, 0),
621 0x08,
622 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
623 0x08, 0, /* value, index */
624 gspca_dev->usb_buf, 8,
625 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300626}
627
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300628/* read 5 bytes in gspca_dev->usb_buf */
629static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300630{
631 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300632 __u8 mode[8];
633
Hans de Goede3647fea2008-07-15 05:36:30 -0300634 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 mode[1] = sd->i2c_base;
636 mode[2] = reg;
637 mode[3] = 0;
638 mode[4] = 0;
639 mode[5] = 0;
640 mode[6] = 0;
641 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300642 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300643 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300644 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300646 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300647 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300648 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300649}
650
651static int probesensor(struct gspca_dev *gspca_dev)
652{
653 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654
Jean-Francois Moine60017612008-07-18 08:46:19 -0300655 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300656 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300657 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300658 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300659 i2c_r5(gspca_dev, 0); /* read sensor id */
660 if (gspca_dev->usb_buf[0] == 0x02
661 && gspca_dev->usb_buf[1] == 0x09
662 && gspca_dev->usb_buf[2] == 0x01
663 && gspca_dev->usb_buf[3] == 0x00
664 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
666 sd->sensor = SENSOR_HV7131R;
667 return SENSOR_HV7131R;
668 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300669 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300670 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
671 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
673 return -ENODEV;
674}
675
676static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300677 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678{
679 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300680 const __u8 *reg9a;
681 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300683 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300685 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
687
Jean-Francois Moine60017612008-07-18 08:46:19 -0300688 reg_w1(gspca_dev, 0xf1, 0x00);
689 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690
691 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300692 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
693 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300694 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300695 switch (sd->bridge) {
696 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 reg9a = reg9a_sn9c325;
698 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300699 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700 reg9a = reg9a_sn9c120;
701 break;
702 default:
703 reg9a = reg9a_def;
704 break;
705 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707
Jean-Francois Moine60017612008-07-18 08:46:19 -0300708 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300709
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300710 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711
Hans de Goede3647fea2008-07-15 05:36:30 -0300712 switch (sd->bridge) {
713 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300714 reg_w1(gspca_dev, 0x01, 0x61);
715 reg_w1(gspca_dev, 0x17, 0x20);
716 reg_w1(gspca_dev, 0x01, 0x60);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300718 case BRIDGE_SN9C325:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300719 reg_w1(gspca_dev, 0x01, 0x43);
720 reg_w1(gspca_dev, 0x17, 0xae);
721 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722 break;
723 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300724 reg_w1(gspca_dev, 0x01, 0x43);
725 reg_w1(gspca_dev, 0x17, 0x61);
726 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727 }
728
729 if (sd->sensor == SENSOR_HV7131R) {
730 if (probesensor(gspca_dev) < 0)
731 return -ENODEV;
732 }
733 return 0;
734}
735
736static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
737{
738 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300739 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
741
742 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300743 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300744 i++;
745 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300746 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747}
748
749static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
750{
751 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752
753 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300754 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755 i++;
756 }
757}
758
759static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
760{
761 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300762
763 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300764 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765 i++;
766 }
767}
768
769static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
770{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300771 int i = 0;
772
773 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300774 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300775 i++;
776 }
777}
778
779static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
780{
781 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782
Jean-Francois Moine60017612008-07-18 08:46:19 -0300783 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
784 i++;
785 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300787 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300788 i++;
789 }
790}
791
792/* this function is called at probe time */
793static int sd_config(struct gspca_dev *gspca_dev,
794 const struct usb_device_id *id)
795{
796 struct sd *sd = (struct sd *) gspca_dev;
797 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798
799 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800 cam->epaddr = 0x01;
801 cam->cam_mode = vga_mode;
802 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300803
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -0300804 sd->bridge = id->driver_info >> 16;
805 sd->sensor = id->driver_info >> 8;
806 sd->i2c_base = id->driver_info;
807
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300809 sd->brightness = BRIGHTNESS_DEF;
810 sd->contrast = CONTRAST_DEF;
811 sd->colors = COLOR_DEF;
812 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813 return 0;
814}
815
816/* this function is called at open time */
817static int sd_open(struct gspca_dev *gspca_dev)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300820/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300821 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300822 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300823
Hans de Goede3647fea2008-07-15 05:36:30 -0300824 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300825 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300826 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300827 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300828 reg_r(gspca_dev, 0x00, 1);
829 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -0300830 switch (sd->bridge) {
831 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832 if (regF1 != 0x11)
833 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300834 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300835 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300836 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 if (regF1 != 0x11)
838 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300839 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300841 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 if (regF1 != 0x12)
843 return -ENODEV;
844 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300845 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300846 break;
847 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300848/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300849/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 if (regF1 != 0x12)
851 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300852 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 break;
854 }
855
Jean-Francois Moine60017612008-07-18 08:46:19 -0300856 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857
858 return 0;
859}
860
861static unsigned int setexposure(struct gspca_dev *gspca_dev,
862 unsigned int expo)
863{
864 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300865 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300866 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300867 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300869 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
871
872 switch (sd->sensor) {
873 case SENSOR_HV7131R: {
874 __u8 Expodoit[] =
875 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
876
877 Expodoit[3] = expo >> 16;
878 Expodoit[4] = expo >> 8;
879 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300880 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881 break;
882 }
883 case SENSOR_MI0360: {
884 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
885 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
886
887 if (expo > 0x0635)
888 expo = 0x0635;
889 else if (expo < 0x0001)
890 expo = 0x0001;
891 expoMi[3] = expo >> 8;
892 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300893 i2c_w8(gspca_dev, expoMi);
894 i2c_w8(gspca_dev, doit);
895 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300896 break;
897 }
898 case SENSOR_MO4000: {
899 __u8 expoMof[] =
900 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
901 __u8 expoMo10[] =
902 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
903
904 if (expo > 0x1fff)
905 expo = 0x1fff;
906 else if (expo < 0x0001)
907 expo = 0x0001;
908 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300909 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 expoMo10[3] = ((expo & 0x1c00) >> 10)
911 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300912 i2c_w8(gspca_dev, expoMo10);
913 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300914 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 ((expoMo10[3] & 0x07) << 10)
916 | (expoMof[3] << 2)
917 | ((expoMo10[3] & 0x30) >> 4));
918 break;
919 }
920 }
921 return expo;
922}
923
924static void setbrightness(struct gspca_dev *gspca_dev)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927 unsigned int expo;
928 __u8 k2;
929
930 switch (sd->sensor) {
931 case SENSOR_HV7131R:
932 expo = sd->brightness << 4;
933 if (expo > 0x002dc6c0)
934 expo = 0x002dc6c0;
935 else if (expo < 0x02a0)
936 expo = 0x02a0;
937 sd->exposure = setexposure(gspca_dev, expo);
938 break;
939 case SENSOR_MI0360:
940 expo = sd->brightness >> 4;
941 sd->exposure = setexposure(gspca_dev, expo);
942 break;
943 case SENSOR_MO4000:
944 expo = sd->brightness >> 4;
945 sd->exposure = setexposure(gspca_dev, expo);
946 break;
947 case SENSOR_OV7660:
948 return; /*jfm??*/
949 }
950
951 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300952 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300953}
954
955static void setcontrast(struct gspca_dev *gspca_dev)
956{
957 struct sd *sd = (struct sd *) gspca_dev;
958 __u8 k2;
959 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
960
961 if (sd->sensor == SENSOR_OV7660)
962 return; /*jfm??*/
963 k2 = sd->contrast;
964 contrast[2] = k2;
965 contrast[0] = (k2 + 1) >> 1;
966 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300967 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300968}
969
970static void setcolors(struct gspca_dev *gspca_dev)
971{
972 struct sd *sd = (struct sd *) gspca_dev;
973 __u8 data;
974 int colour;
975
976 colour = sd->colors - 128;
977 if (colour > 0)
978 data = (colour + 32) & 0x7f; /* blue */
979 else
980 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300981 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982}
983
984/* -- start the camera -- */
985static void sd_start(struct gspca_dev *gspca_dev)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300988 int i;
989 __u8 data;
990 __u8 reg1;
991 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300992 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300994 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
995 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
996 static const __u8 CA_sn9c120[] =
997 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
998 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
999 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001000 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1001
1002 sn9c1xx = sn_tb[(int) sd->sensor];
1003 configure_gpio(gspca_dev, sn9c1xx);
1004
1005/*fixme:jfm this sequence should appear at end of sd_start */
1006/* with
Jean-Francois Moine60017612008-07-18 08:46:19 -03001007 reg_w1(gspca_dev, 0x01, 0x44); */
1008 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1009 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1010 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1011 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1012 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1013 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1014 reg_w1(gspca_dev, 0xd3, 0x50);
1015 reg_w1(gspca_dev, 0xc6, 0x00);
1016 reg_w1(gspca_dev, 0xc7, 0x00);
1017 reg_w1(gspca_dev, 0xc8, 0x50);
1018 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019/*fixme:jfm end of ending sequence */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001020 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001021 switch (sd->bridge) {
1022 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001024 break;
1025 case BRIDGE_SN9C120:
1026 data = 0xa0;
1027 break;
1028 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001029 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001030 break;
1031 }
Jean-Francois Moine60017612008-07-18 08:46:19 -03001032 reg_w1(gspca_dev, 0x17, data);
1033 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1034 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1035 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1036 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001037 switch (sd->bridge) {
1038 case BRIDGE_SN9C325:
1039 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1040 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001041 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001042 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1043 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001044 reg_w1(gspca_dev, 0x9a, 0x0a);
1045 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001046 break;
1047 case BRIDGE_SN9C120:
1048 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1049 sizeof regsn20_sn9c120);
1050 for (i = 0; i < 2; i++)
1051 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1052 sizeof reg84_sn9c120_1);
1053 for (i = 0; i < 6; i++)
1054 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1055 sizeof reg84_sn9c120_2);
1056 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1057 sizeof reg84_sn9c120_3);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001058 reg_w1(gspca_dev, 0x9a, 0x05);
1059 reg_w1(gspca_dev, 0x99, 0x5b);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001060 break;
1061 default:
1062 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001063 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001064 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001065 reg_w1(gspca_dev, 0x9a, 0x08);
1066 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001067 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068 }
1069
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001070 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001071 if (mode)
1072 reg1 = 0x46; /* 320 clk 48Mhz */
1073 else
1074 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 reg17 = 0x61;
1076 switch (sd->sensor) {
1077 case SENSOR_HV7131R:
1078 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001079 break;
1080 case SENSOR_MI0360:
1081 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001082 break;
1083 case SENSOR_MO4000:
1084 mo4000_InitSensor(gspca_dev);
1085 if (mode) {
1086/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1087 reg1 = 0x06; /* clk 24Mz */
1088 } else {
1089 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001090/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 }
1092 break;
1093 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001094 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001095 reg17 = 0xa2;
1096 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001097/* if (mode)
1098 ; * 320x2...
1099 else
1100 ; * 640x... */
1101 break;
1102 default:
1103/* case SENSOR_OV7660: */
1104 ov7660_InitSensor(gspca_dev);
1105 if (mode) {
1106/* reg17 = 0x21; * 320 */
1107/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001108/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001109 } else {
1110 reg17 = 0xa2; /* 640 */
1111 reg1 = 0x40;
1112 }
1113 break;
1114 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001115 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001116 switch (sd->bridge) {
1117 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001118 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001119 break;
1120 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001121 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001122 break;
1123 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001124 switch (sd->bridge) {
1125 case BRIDGE_SN9C120: /*jfm ?? */
1126 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001127 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001128 break;
1129 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001130 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001131 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1132 break;
1133 }
1134
1135 /* here change size mode 0 -> VGA; 1 -> CIF */
1136 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001137 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001138
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001139 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1140 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001141
1142 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001143 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144
Jean-Francois Moine60017612008-07-18 08:46:19 -03001145 reg_w1(gspca_dev, 0x17, reg17);
1146 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001147 setbrightness(gspca_dev);
1148 setcontrast(gspca_dev);
1149}
1150
1151static void sd_stopN(struct gspca_dev *gspca_dev)
1152{
1153 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001154 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001155 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001156 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001157 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001159 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160
1161 data = 0x0b;
1162 switch (sd->sensor) {
1163 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001164 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001165 data = 0x2b;
1166 break;
1167 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001168 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001169 data = 0x29;
1170 break;
1171 case SENSOR_MO4000:
1172 break;
1173 case SENSOR_OV7648:
1174 data = 0x29;
1175 break;
1176 default:
1177/* case SENSOR_OV7660: */
1178 break;
1179 }
1180 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001181 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1182 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1183 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1184 reg_w1(gspca_dev, 0x01, data);
1185 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001186}
1187
1188static void sd_stop0(struct gspca_dev *gspca_dev)
1189{
1190}
1191
1192static void sd_close(struct gspca_dev *gspca_dev)
1193{
1194}
1195
1196static void setautogain(struct gspca_dev *gspca_dev)
1197{
1198 struct sd *sd = (struct sd *) gspca_dev;
1199 /* Thanks S., without your advice, autobright should not work :) */
1200 int delta;
1201 int expotimes = 0;
1202 __u8 luma_mean = 130;
1203 __u8 luma_delta = 20;
1204
1205 delta = sd->avg_lum;
1206 if (delta < luma_mean - luma_delta ||
1207 delta > luma_mean + luma_delta) {
1208 switch (sd->sensor) {
1209 case SENSOR_HV7131R:
1210 expotimes = sd->exposure >> 8;
1211 expotimes += (luma_mean - delta) >> 4;
1212 if (expotimes < 0)
1213 expotimes = 0;
1214 sd->exposure = setexposure(gspca_dev,
1215 (unsigned int) (expotimes << 8));
1216 break;
1217 case SENSOR_MO4000:
1218 case SENSOR_MI0360:
1219 expotimes = sd->exposure;
1220 expotimes += (luma_mean - delta) >> 6;
1221 if (expotimes < 0)
1222 expotimes = 0;
1223 sd->exposure = setexposure(gspca_dev,
1224 (unsigned int) expotimes);
1225 setcolors(gspca_dev);
1226 break;
1227 }
1228 }
1229}
1230
1231static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1232 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001233 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001234 int len) /* iso packet length */
1235{
1236 struct sd *sd = (struct sd *) gspca_dev;
1237 int sof, avg_lum;
1238
1239 sof = len - 64;
1240 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1241
1242 /* end of frame */
1243 gspca_frame_add(gspca_dev, LAST_PACKET,
1244 frame, data, sof + 2);
1245 if (sd->ag_cnt < 0)
1246 return;
1247 if (--sd->ag_cnt >= 0)
1248 return;
1249 sd->ag_cnt = AG_CNT_START;
1250/* w1 w2 w3 */
1251/* w4 w5 w6 */
1252/* w7 w8 */
1253/* w4 */
1254 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1255/* w6 */
1256 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1257/* w2 */
1258 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1259/* w8 */
1260 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1261/* w5 */
1262 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1263 avg_lum >>= 4;
1264 sd->avg_lum = avg_lum;
1265 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1266 setautogain(gspca_dev);
1267 return;
1268 }
1269 if (gspca_dev->last_packet_type == LAST_PACKET) {
1270
1271 /* put the JPEG 422 header */
1272 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1273 }
1274 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1275}
1276
1277static unsigned int getexposure(struct gspca_dev *gspca_dev)
1278{
1279 struct sd *sd = (struct sd *) gspca_dev;
1280 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001281
1282 switch (sd->sensor) {
1283 case SENSOR_HV7131R:
1284 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001285 i2c_r5(gspca_dev, 0x25);
1286 return (gspca_dev->usb_buf[0] << 16)
1287 | (gspca_dev->usb_buf[1] << 8)
1288 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289 case SENSOR_MI0360:
1290 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 i2c_r5(gspca_dev, 0x09);
1292 return (gspca_dev->usb_buf[0] << 8)
1293 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001294 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001295 i2c_r5(gspca_dev, 0x0e);
1296 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1297 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1298 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001299 PDEBUG(D_CONF, "exposure %d",
1300 (hexpo << 10) | (mexpo << 2) | lexpo);
1301 return (hexpo << 10) | (mexpo << 2) | lexpo;
1302 default:
1303/* case SENSOR_OV7660: */
1304 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001305 i2c_r5(gspca_dev, 0x04);
1306 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1307 lexpo = gspca_dev->usb_buf[0] & 0x02;
1308 i2c_r5(gspca_dev, 0x08);
1309 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001310 return (hexpo << 10) | (mexpo << 2) | lexpo;
1311 }
1312}
1313
1314static void getbrightness(struct gspca_dev *gspca_dev)
1315{
1316 struct sd *sd = (struct sd *) gspca_dev;
1317
1318 /* hardcoded registers seem not readable */
1319 switch (sd->sensor) {
1320 case SENSOR_HV7131R:
1321/* sd->brightness = 0x7fff; */
1322 sd->brightness = getexposure(gspca_dev) >> 4;
1323 break;
1324 case SENSOR_MI0360:
1325 sd->brightness = getexposure(gspca_dev) << 4;
1326 break;
1327 case SENSOR_MO4000:
1328/* sd->brightness = 0x1fff; */
1329 sd->brightness = getexposure(gspca_dev) << 4;
1330 break;
1331 }
1332}
1333
1334static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1335{
1336 struct sd *sd = (struct sd *) gspca_dev;
1337
1338 sd->brightness = val;
1339 if (gspca_dev->streaming)
1340 setbrightness(gspca_dev);
1341 return 0;
1342}
1343
1344static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1345{
1346 struct sd *sd = (struct sd *) gspca_dev;
1347
1348 getbrightness(gspca_dev);
1349 *val = sd->brightness;
1350 return 0;
1351}
1352
1353static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1354{
1355 struct sd *sd = (struct sd *) gspca_dev;
1356
1357 sd->contrast = val;
1358 if (gspca_dev->streaming)
1359 setcontrast(gspca_dev);
1360 return 0;
1361}
1362
1363static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1364{
1365 struct sd *sd = (struct sd *) gspca_dev;
1366
1367 *val = sd->contrast;
1368 return 0;
1369}
1370
1371static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1372{
1373 struct sd *sd = (struct sd *) gspca_dev;
1374
1375 sd->colors = val;
1376 if (gspca_dev->streaming)
1377 setcolors(gspca_dev);
1378 return 0;
1379}
1380
1381static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1382{
1383 struct sd *sd = (struct sd *) gspca_dev;
1384
1385 *val = sd->colors;
1386 return 0;
1387}
1388
1389static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1390{
1391 struct sd *sd = (struct sd *) gspca_dev;
1392
1393 sd->autogain = val;
1394 if (val)
1395 sd->ag_cnt = AG_CNT_START;
1396 else
1397 sd->ag_cnt = -1;
1398 return 0;
1399}
1400
1401static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1402{
1403 struct sd *sd = (struct sd *) gspca_dev;
1404
1405 *val = sd->autogain;
1406 return 0;
1407}
1408
1409/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001410static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001411 .name = MODULE_NAME,
1412 .ctrls = sd_ctrls,
1413 .nctrls = ARRAY_SIZE(sd_ctrls),
1414 .config = sd_config,
1415 .open = sd_open,
1416 .start = sd_start,
1417 .stopN = sd_stopN,
1418 .stop0 = sd_stop0,
1419 .close = sd_close,
1420 .pkt_scan = sd_pkt_scan,
1421};
1422
1423/* -- module initialisation -- */
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001424#define BSI(bridge, sensor, i2c_addr) \
1425 .driver_info = (BRIDGE_ ## bridge << 16) \
1426 | (SENSOR_ ## sensor << 8) \
1427 | (i2c_addr)
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001428static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001429#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001430 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1431 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1432 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1433 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1434 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001435#endif
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001436 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1437 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1438/* bw600.inf:
1439 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1440/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1441/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1442 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1443/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1444 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1445/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1446/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1447 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1448/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1449/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1450 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1451 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1452/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
1453/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1454/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1455/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1456 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
1457/* bw600.inf:
1458 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
1459 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1460/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
1461/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001462#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001463 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1464 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1465/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
1466 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1467 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1468/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001469#endif
Jean-Francois Moinee546f4b2008-07-26 03:43:59 -03001470 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001471 {}
1472};
1473MODULE_DEVICE_TABLE(usb, device_table);
1474
1475/* -- device connect -- */
1476static int sd_probe(struct usb_interface *intf,
1477 const struct usb_device_id *id)
1478{
1479 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1480 THIS_MODULE);
1481}
1482
1483static struct usb_driver sd_driver = {
1484 .name = MODULE_NAME,
1485 .id_table = device_table,
1486 .probe = sd_probe,
1487 .disconnect = gspca_disconnect,
1488};
1489
1490/* -- module insert / remove -- */
1491static int __init sd_mod_init(void)
1492{
1493 if (usb_register(&sd_driver) < 0)
1494 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001495 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001496 return 0;
1497}
1498static void __exit sd_mod_exit(void)
1499{
1500 usb_deregister(&sd_driver);
1501 info("deregistered");
1502}
1503
1504module_init(sd_mod_init);
1505module_exit(sd_mod_exit);