blob: 93d4746ff95ac7c8e77d85b3a6c0cfdca74e8a57 [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 Moine739570b2008-07-14 09:38:29 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 int avg_lum;
39 unsigned int exposure;
40
41 unsigned short brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 signed char ag_cnt;
47#define AG_CNT_START 13
48
49 char qindex;
Hans de Goede3647fea2008-07-15 05:36:30 -030050 unsigned char bridge;
51#define BRIDGE_SN9C102P 0
52#define BRIDGE_SN9C105 1
53#define BRIDGE_SN9C110 2
54#define BRIDGE_SN9C120 3
55#define BRIDGE_SN9C325 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030056 char sensor; /* Type of image sensor chip */
57#define SENSOR_HV7131R 0
58#define SENSOR_MI0360 1
59#define SENSOR_MO4000 2
60#define SENSOR_OV7648 3
61#define SENSOR_OV7660 4
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030062 unsigned char i2c_base;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030063};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
74
75static struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076 {
77 {
78 .id = V4L2_CID_BRIGHTNESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Brightness",
81 .minimum = 0,
82 .maximum = 0xffff,
83 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030084#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030086 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030090 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
96 .maximum = 127,
97 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030098#define CONTRAST_DEF 63
99 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300100 },
101 .set = sd_setcontrast,
102 .get = sd_getcontrast,
103 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300104 {
105 {
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Color",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300112#define COLOR_DEF 127
113 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300114 },
115 .set = sd_setcolors,
116 .get = sd_getcolors,
117 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300118 {
119 {
120 .id = V4L2_CID_AUTOGAIN,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
122 .name = "Auto Gain",
123 .minimum = 0,
124 .maximum = 1,
125 .step = 1,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300126#define AUTOGAIN_DEF 1
127 .default_value = AUTOGAIN_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300128 },
129 .set = sd_setautogain,
130 .get = sd_getautogain,
131 },
132};
133
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300134static struct v4l2_pix_format vga_mode[] = {
135 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 160,
137 .sizeimage = 160 * 120 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 2},
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 .bytesperline = 320,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
144 .priv = 1},
145 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 640,
147 .sizeimage = 640 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150};
151
152/*Data from sn9c102p+hv71331r */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300153static const __u8 sn_hv7131[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
155/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
156 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
157/* rega regb regc regd rege regf reg10 reg11 */
158 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
159/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
162};
163
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300164static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
166/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
167 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
168/* rega regb regc regd rege regf reg10 reg11 */
169 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
170/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
172/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
173};
174
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300175static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
177/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
178 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
179/* reg9 rega regb regc regd rege regf reg10 reg11*/
180 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
181/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
183/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
184 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
185 0xd3, 0xdf, 0xea, 0xf5
186};
187
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300188static const __u8 sn_ov7648[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300189 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
190 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
192};
193
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300194static const __u8 sn_ov7660[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
197/* reg9 rega regb regc regd rege regf reg10 reg11*/
198 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
199/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
200 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, 0x07, 0x00, 0x00,
201/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203};
204
205/* sequence specific to the sensors - !! index = SENSOR_xxx */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300206static const __u8 *sn_tb[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300207 sn_hv7131,
208 sn_mi0360,
209 sn_mo4000,
210 sn_ov7648,
211 sn_ov7660
212};
213
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300214static const __u8 regsn20[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
217};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300218static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300219 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
220 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
221};
222
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300223static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300224 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
225 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
226/* 0x00, 0x00, 0x00, 0x00, 0x00 */
227 0xf7, 0x0f, 0x0a, 0x00, 0x00
228};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300229static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300230 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
231 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
232 0xf8, 0x0f, 0x00, 0x00, 0x00
233};
234
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300235static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300236 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
237 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
238 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
239 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
240 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
241 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
242 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
243
244 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
245 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
246 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
247 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
248 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
249 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
250 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
251 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
252
253 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
254 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
255 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
256 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
257 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
258
259 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
260 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
261 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
262 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
263 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300264 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300265};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300266static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300267 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
268 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
269 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
270 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
271 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
272 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
273 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
274 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
275 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
277 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
278 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
279 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
281 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
283 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
284 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
285 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
286 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
287 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
288 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
289 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
290 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
291 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
292 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
294 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
296 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
299 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
300
301 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
302 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
305 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
306
307 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
308 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
309 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
310 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
311
312 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
313 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
314/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
315/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
316 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
317 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300318 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300319};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300320static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300321 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
322 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
323 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
324 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
325 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
327 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
328 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
329 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
330 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
331 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
332 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
333 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
334 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
335 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
336 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
337 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
338 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
339 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300341 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300343static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300344 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
345 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
346 /* Outformat ?? rawRGB */
347 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
348/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
349 * GAIN BLUE RED VREF */
350 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
351 /* GAIN BLUE RED VREF */
352 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
353 /* COM 1 BAVE GEAVE AECHH */
354 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
355 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
356/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
357 * AECH CLKRC COM7 COM8 */
358 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
359 /* AECH CLKRC COM7 COM8 */
360 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
361 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
362 /* HSTART HSTOP VSTRT VSTOP */
363 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
364 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
365 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
366 /* BOS GBOS GROS ROS (BGGR offset) */
367/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
368 * AEW AEB VPT BBIAS */
369 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
370 /* AEW AEB VPT BBIAS */
371 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
372 /* GbBIAS RSVD EXHCH EXHCL */
373 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
374 /* RBIAS ADVFL ASDVFH YAVE */
375 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
376 /* HSYST HSYEN HREF */
377 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
378 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
379 /* ADC ACOM OFON TSLB */
380 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
381 /* COM11 COM12 COM13 COM14 */
382 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
383 /* EDGE COM15 COM16 COM17 */
384 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
385 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
386 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
387 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
388 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
389 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
390 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
391 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
392 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
393 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
394 /* LCC1 LCC2 LCC3 LCC4 */
395 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
396 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
397 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
398 /* band gap reference [0..3] DBLV */
399 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
400 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
401 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
402 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
403 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
404 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
405 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
406 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
407 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
408 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
409/****** (some exchanges in the win trace) ******/
410 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
411 /* bits[3..0]reserved */
412 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
413 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
414 /* VREF vertical frame ctrl */
415 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
416 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
417 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
418 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10},
420/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, */
421/****** (some exchanges in the win trace) ******/
422 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
423 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
424 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
425 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
426/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, */
427/****** (some exchanges in the win trace) ******/
428/**********startsensor KO if changed !!****/
429 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
431 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
433/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300434 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300435};
436/* reg0x04 reg0x07 reg 0x10 */
437/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
438
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300439static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300440 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
441 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
442 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
443 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
444 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
445 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
446 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
447 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
448 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
449 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
450 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
451 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
452 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
453 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
454 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
455 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
456 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
457 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
458 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
459 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
460 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
461 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
462 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
463 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
464 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
465 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
466 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
467 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
468 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
469 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
471 * This is currently setting a
472 * blue tint, and some things more , i leave it here for future test if
473 * somene is having problems with color on this sensor
474 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
475 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
476 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
477 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
478 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
479 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
480 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
481 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
482 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
483 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
484 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
485 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
486 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
487 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
488 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
489 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
490 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
491/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300492 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493};
494
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300495static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300496 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
497 0x06, 0x08, 0x0A, 0x11,
498 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
499 0x19, 0x19, 0x17, 0x15,
500 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
501 0x21, 0x2E, 0x21, 0x23,
502 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
503 0x25, 0x29, 0x2C, 0x29,
504 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
505 0x17, 0x1B, 0x29, 0x29,
506 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
507 0x29, 0x29, 0x29, 0x29,
508 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
509 0x29, 0x29, 0x29, 0x29,
510 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
511 0x29, 0x29, 0x29, 0x29
512};
513
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300514/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
515static void reg_r(struct gspca_dev *gspca_dev,
516 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300518 usb_control_msg(gspca_dev->dev,
519 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520 0,
521 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
522 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300523 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 500);
525}
526
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300529 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 int len)
531{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532 if (len <= sizeof gspca_dev->usb_buf) {
533 memcpy(gspca_dev->usb_buf, buffer, len);
534 usb_control_msg(gspca_dev->dev,
535 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300536 0x08,
537 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
538 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300539 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300540 500);
541 } else {
542 __u8 *tmpbuf;
543
544 tmpbuf = kmalloc(len, GFP_KERNEL);
545 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300546 usb_control_msg(gspca_dev->dev,
547 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300548 0x08,
549 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
550 value, 0,
551 tmpbuf, len,
552 500);
553 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300554 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555}
556
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300557/* I2C write 2 bytes */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300558static void i2c_w2(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300559 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300560{
561 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562 __u8 mode[8];
563
564 /* is i2c ready */
Hans de Goede3647fea2008-07-15 05:36:30 -0300565 mode[0] = 0x81 | (2 << 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566 mode[1] = sd->i2c_base;
567 mode[2] = buffer[0];
568 mode[3] = buffer[1];
569 mode[4] = 0;
570 mode[5] = 0;
571 mode[6] = 0;
572 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300573 reg_w(gspca_dev, 0x08, mode, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574}
575
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576/* I2C write 8 bytes */
577static void i2c_w8(struct gspca_dev *gspca_dev,
578 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300580 reg_w(gspca_dev, 0x08, buffer, 8);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 msleep(1);
582}
583
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300584/* read 5 bytes in gspca_dev->usb_buf */
585static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586{
587 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588 __u8 mode[8];
589
Hans de Goede3647fea2008-07-15 05:36:30 -0300590 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591 mode[1] = sd->i2c_base;
592 mode[2] = reg;
593 mode[3] = 0;
594 mode[4] = 0;
595 mode[5] = 0;
596 mode[6] = 0;
597 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300598 i2c_w8(gspca_dev, mode);
Hans de Goede3647fea2008-07-15 05:36:30 -0300599 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300600 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300601 i2c_w8(gspca_dev, mode);
602 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603}
604
605static int probesensor(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608 __u8 reg02;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300609 static const __u8 datasend[] = { 2, 0 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610 /* reg val1 val2 val3 val4 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300611
612 i2c_w2(gspca_dev, datasend);
613/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
614 msleep(10);
615 reg02 = 0x66;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300616 reg_w(gspca_dev, 0x02, &reg02, 1); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300618 i2c_r5(gspca_dev, 0); /* read sensor id */
619 if (gspca_dev->usb_buf[0] == 0x02
620 && gspca_dev->usb_buf[1] == 0x09
621 && gspca_dev->usb_buf[2] == 0x01
622 && gspca_dev->usb_buf[3] == 0x00
623 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
625 sd->sensor = SENSOR_HV7131R;
626 return SENSOR_HV7131R;
627 }
628 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300629 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
630 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
632 return -ENODEV;
633}
634
635static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300636 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637{
638 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 __u8 data;
640 __u8 regF1;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300641 const __u8 *reg9a;
642 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300644 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300646 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300647 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
648
649
650 regF1 = 0x00;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300653 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1);
654 /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655
656 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300657 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
658 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
659 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 3);
Hans de Goede3647fea2008-07-15 05:36:30 -0300660 switch (sd->bridge) {
661 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 reg9a = reg9a_sn9c325;
663 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300664 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300665 reg9a = reg9a_sn9c120;
666 break;
667 default:
668 reg9a = reg9a_def;
669 break;
670 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300671 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672
673 data = 0x60; /*fixme:jfm 60 00 00 (3) */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300674 reg_w(gspca_dev, 0xd4, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300676 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677
Hans de Goede3647fea2008-07-15 05:36:30 -0300678 switch (sd->bridge) {
679 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300681 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300682 data = 0x20;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300683 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300684 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300685 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300687 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300688 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 data = 0xae;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300691 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300693 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300694 break;
695 default:
696 data = 0x43;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300697 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300698 data = 0x61;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300699 reg_w(gspca_dev, 0x17, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700 data = 0x42;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300701 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702 }
703
704 if (sd->sensor == SENSOR_HV7131R) {
705 if (probesensor(gspca_dev) < 0)
706 return -ENODEV;
707 }
708 return 0;
709}
710
711static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
712{
713 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300714 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300715 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
716
717 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300718 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 i++;
720 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300721 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300722}
723
724static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
725{
726 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300727
728 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300729 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730 i++;
731 }
732}
733
734static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
735{
736 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737
738 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300739 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300740 i++;
741 }
742}
743
744static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
745{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300746 int i = 0;
747
748 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300749 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750 i++;
751 }
752}
753
754static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
755{
756 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300757
758 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300759 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300760 i++;
761 }
762}
763
764/* this function is called at probe time */
765static int sd_config(struct gspca_dev *gspca_dev,
766 const struct usb_device_id *id)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct cam *cam;
770 __u16 vendor;
771 __u16 product;
772
773 vendor = id->idVendor;
774 product = id->idProduct;
775 sd->sensor = -1;
776 switch (vendor) {
777 case 0x0458: /* Genius */
778/* switch (product) {
779 case 0x7025: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300780 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300781 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300782 sd->i2c_base = 0x5d;
783/* break;
784 } */
785 break;
786 case 0x045e:
787/* switch (product) {
788 case 0x00f5:
789 case 0x00f7: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300790 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300792 sd->i2c_base = 0x21;
793/* break;
794 } */
795 break;
796 case 0x0471: /* Philips */
797/* switch (product) {
798 case 0x0327:
799 case 0x0328:
800 case 0x0330: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300801 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300802 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 sd->i2c_base = 0x5d;
804/* break;
805 } */
806 break;
807 case 0x0c45: /* Sonix */
808 switch (product) {
809 case 0x6040:
Hans de Goede3647fea2008-07-15 05:36:30 -0300810 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 sd->sensor = SENSOR_MI0360; /* from BW600.inf */
812/* sd->sensor = SENSOR_HV7131R; * gspcav1 value */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300813 sd->i2c_base = 0x11;
814 break;
815/* case 0x607a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300816 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 sd->i2c_base = 0x??;
819 break; */
820 case 0x607c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300821 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300823 sd->i2c_base = 0x11;
824 break;
825/* case 0x607e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300826 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300827 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828 sd->i2c_base = 0x??;
829 break; */
830 case 0x60c0:
Hans de Goede3647fea2008-07-15 05:36:30 -0300831 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300833 sd->i2c_base = 0x5d;
834 break;
835/* case 0x60c8: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300836 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 sd->i2c_base = 0x??;
839 break; */
840/* case 0x60cc: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300841 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300842 sd->sensor = SENSOR_HV7131GP;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 sd->i2c_base = 0x??;
844 break; */
845 case 0x60ec:
Hans de Goede3647fea2008-07-15 05:36:30 -0300846 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 sd->i2c_base = 0x21;
849 break;
850/* case 0x60ef: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300851 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 sd->i2c_base = 0x??;
854 break; */
855/* case 0x60fa: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300856 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858 sd->i2c_base = 0x??;
859 break; */
860 case 0x60fb:
Hans de Goede3647fea2008-07-15 05:36:30 -0300861 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300862 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 sd->i2c_base = 0x21;
864 break;
865 case 0x60fc:
Hans de Goede3647fea2008-07-15 05:36:30 -0300866 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300867 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 sd->i2c_base = 0x11;
869 break;
870/* case 0x60fe: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300871 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300872 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 sd->i2c_base = 0x??;
874 break; */
875/* case 0x6108: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300876 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878 sd->i2c_base = 0x??;
879 break; */
880/* case 0x6122: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300881 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300882 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300883 sd->i2c_base = 0x??;
884 break; */
885 case 0x612a:
Hans de Goede3647fea2008-07-15 05:36:30 -0300886/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
887 sd->bridge = BRIDGE_SN9C325;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 sd->i2c_base = 0x21;
890 break;
891/* case 0x6123: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300892 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 sd->sensor = SENSOR_SanyoCCD;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 sd->i2c_base = 0x??;
895 break; */
896 case 0x612c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300897 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 sd->i2c_base = 0x21;
900 break;
901/* case 0x612e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300902 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 sd->i2c_base = 0x??;
905 break; */
906/* case 0x612f: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300907 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909 sd->i2c_base = 0x??;
910 break; */
911 case 0x6130:
Hans de Goede3647fea2008-07-15 05:36:30 -0300912 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300914 sd->i2c_base = 0x5d;
915 break;
916 case 0x6138:
Hans de Goede3647fea2008-07-15 05:36:30 -0300917 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919 sd->i2c_base = 0x21;
920 break;
921/* case 0x613a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300922 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300923 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924 sd->i2c_base = 0x??;
925 break; */
926 case 0x613b:
Hans de Goede3647fea2008-07-15 05:36:30 -0300927 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300928 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929 sd->i2c_base = 0x21;
930 break;
931 case 0x613c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300932 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300933 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934 sd->i2c_base = 0x11;
935 break;
936/* case 0x613e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300937 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300938 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939 sd->i2c_base = 0x??;
940 break; */
941 }
942 break;
943 }
944 if (sd->sensor < 0) {
945 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
946 vendor, product);
947 return -EINVAL;
948 }
949
950 cam = &gspca_dev->cam;
951 cam->dev_name = (char *) id->driver_info;
952 cam->epaddr = 0x01;
953 cam->cam_mode = vga_mode;
954 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300955
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300957 sd->brightness = BRIGHTNESS_DEF;
958 sd->contrast = CONTRAST_DEF;
959 sd->colors = COLOR_DEF;
960 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 return 0;
962}
963
964/* this function is called at open time */
965static int sd_open(struct gspca_dev *gspca_dev)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300968/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 __u8 regF1;
970 __u8 regGpio[] = { 0x29, 0x74 };
971
Hans de Goede3647fea2008-07-15 05:36:30 -0300972 /* setup a selector by bridge */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300973 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300974 reg_w(gspca_dev, 0xf1, &regF1, 1);
975 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
976 regF1 = gspca_dev->usb_buf[0];
977 reg_w(gspca_dev, 0xf1, &regF1, 1);
978 reg_r(gspca_dev, 0x00, 1);
979 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -0300980 switch (sd->bridge) {
981 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300982 if (regF1 != 0x11)
983 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300984 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300985 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300986 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 if (regF1 != 0x11)
988 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300989 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300991 case BRIDGE_SN9C110:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300992 if (regF1 != 0x12)
993 return -ENODEV;
994 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300995 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300997 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300998 if (regF1 != 0x12)
999 return -ENODEV;
1000 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001001 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001002 break;
1003 default:
Hans de Goede3647fea2008-07-15 05:36:30 -03001004/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001005 if (regF1 != 0x12)
1006 return -ENODEV;
1007 regGpio[1] = 0x62;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001008 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 break;
1010 }
1011
1012 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001013 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014
1015 return 0;
1016}
1017
1018static unsigned int setexposure(struct gspca_dev *gspca_dev,
1019 unsigned int expo)
1020{
1021 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001022 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001024 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001026 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1028
1029 switch (sd->sensor) {
1030 case SENSOR_HV7131R: {
1031 __u8 Expodoit[] =
1032 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1033
1034 Expodoit[3] = expo >> 16;
1035 Expodoit[4] = expo >> 8;
1036 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001037 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038 break;
1039 }
1040 case SENSOR_MI0360: {
1041 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1042 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1043
1044 if (expo > 0x0635)
1045 expo = 0x0635;
1046 else if (expo < 0x0001)
1047 expo = 0x0001;
1048 expoMi[3] = expo >> 8;
1049 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001050 i2c_w8(gspca_dev, expoMi);
1051 i2c_w8(gspca_dev, doit);
1052 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001053 break;
1054 }
1055 case SENSOR_MO4000: {
1056 __u8 expoMof[] =
1057 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1058 __u8 expoMo10[] =
1059 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1060
1061 if (expo > 0x1fff)
1062 expo = 0x1fff;
1063 else if (expo < 0x0001)
1064 expo = 0x0001;
1065 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001066 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001067 expoMo10[3] = ((expo & 0x1c00) >> 10)
1068 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001069 i2c_w8(gspca_dev, expoMo10);
1070 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001071 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072 ((expoMo10[3] & 0x07) << 10)
1073 | (expoMof[3] << 2)
1074 | ((expoMo10[3] & 0x30) >> 4));
1075 break;
1076 }
1077 }
1078 return expo;
1079}
1080
1081static void setbrightness(struct gspca_dev *gspca_dev)
1082{
1083 struct sd *sd = (struct sd *) gspca_dev;
1084 unsigned int expo;
1085 __u8 k2;
1086
1087 switch (sd->sensor) {
1088 case SENSOR_HV7131R:
1089 expo = sd->brightness << 4;
1090 if (expo > 0x002dc6c0)
1091 expo = 0x002dc6c0;
1092 else if (expo < 0x02a0)
1093 expo = 0x02a0;
1094 sd->exposure = setexposure(gspca_dev, expo);
1095 break;
1096 case SENSOR_MI0360:
1097 expo = sd->brightness >> 4;
1098 sd->exposure = setexposure(gspca_dev, expo);
1099 break;
1100 case SENSOR_MO4000:
1101 expo = sd->brightness >> 4;
1102 sd->exposure = setexposure(gspca_dev, expo);
1103 break;
1104 case SENSOR_OV7660:
1105 return; /*jfm??*/
1106 }
1107
1108 k2 = sd->brightness >> 10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001109 reg_w(gspca_dev, 0x96, &k2, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001110}
1111
1112static void setcontrast(struct gspca_dev *gspca_dev)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115 __u8 k2;
1116 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1117
1118 if (sd->sensor == SENSOR_OV7660)
1119 return; /*jfm??*/
1120 k2 = sd->contrast;
1121 contrast[2] = k2;
1122 contrast[0] = (k2 + 1) >> 1;
1123 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001124 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001125}
1126
1127static void setcolors(struct gspca_dev *gspca_dev)
1128{
1129 struct sd *sd = (struct sd *) gspca_dev;
1130 __u8 data;
1131 int colour;
1132
1133 colour = sd->colors - 128;
1134 if (colour > 0)
1135 data = (colour + 32) & 0x7f; /* blue */
1136 else
1137 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001138 reg_w(gspca_dev, 0x05, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001139}
1140
1141/* -- start the camera -- */
1142static void sd_start(struct gspca_dev *gspca_dev)
1143{
1144 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001145 int i;
1146 __u8 data;
1147 __u8 reg1;
1148 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001149 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001150 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001151 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1152 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1153 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1154 static const __u8 CA_sn9c120[] =
1155 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1156 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1157 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1159
1160 sn9c1xx = sn_tb[(int) sd->sensor];
1161 configure_gpio(gspca_dev, sn9c1xx);
1162
1163/*fixme:jfm this sequence should appear at end of sd_start */
1164/* with
1165 data = 0x44;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001166 reg_w(gspca_dev, 0x01, &data, 1); */
1167 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1168 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1169 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1170 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1171 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1172 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1173 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1174 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1175 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1176 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1177 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001178/*fixme:jfm end of ending sequence */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001179 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
Hans de Goede3647fea2008-07-15 05:36:30 -03001180 if (sd->bridge == BRIDGE_SN9C325)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001181 data = 0xae;
1182 else
1183 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001184 reg_w(gspca_dev, 0x17, &data, 1);
1185 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1186 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1187 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1188 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
Hans de Goede3647fea2008-07-15 05:36:30 -03001189 if (sd->bridge == BRIDGE_SN9C325) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001190 reg_w(gspca_dev, 0x20, regsn20_sn9c325, 0x11);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001191 for (i = 0; i < 8; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001192 reg_w(gspca_dev, 0x84, reg84_sn9c325, 0x15);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001193 data = 0x0a;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001194 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195 data = 0x60;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001196 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001197 } else {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001198 reg_w(gspca_dev, 0x20, regsn20, 0x11);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 for (i = 0; i < 8; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001200 reg_w(gspca_dev, 0x84, reg84, 0x15);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001201 data = 0x08;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001202 reg_w(gspca_dev, 0x9a, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001203 data = 0x59;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001204 reg_w(gspca_dev, 0x99, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 }
1206
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001207 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208 reg1 = 0x02;
1209 reg17 = 0x61;
1210 switch (sd->sensor) {
1211 case SENSOR_HV7131R:
1212 hv7131R_InitSensor(gspca_dev);
1213 if (mode)
1214 reg1 = 0x46; /* 320 clk 48Mhz */
1215 else
1216 reg1 = 0x06; /* 640 clk 24Mz */
1217 break;
1218 case SENSOR_MI0360:
1219 mi0360_InitSensor(gspca_dev);
1220 if (mode)
1221 reg1 = 0x46; /* 320 clk 48Mhz */
1222 else
1223 reg1 = 0x06; /* 640 clk 24Mz */
1224 break;
1225 case SENSOR_MO4000:
1226 mo4000_InitSensor(gspca_dev);
1227 if (mode) {
1228/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1229 reg1 = 0x06; /* clk 24Mz */
1230 } else {
1231 reg17 = 0x22; /* 640 MCKSIZE */
1232 reg1 = 0x06; /* 640 clk 24Mz */
1233 }
1234 break;
1235 case SENSOR_OV7648:
1236 reg17 = 0xa2;
1237 reg1 = 0x44;
1238 ov7648_InitSensor(gspca_dev);
1239/* if (mode)
1240 ; * 320x2...
1241 else
1242 ; * 640x... */
1243 break;
1244 default:
1245/* case SENSOR_OV7660: */
1246 ov7660_InitSensor(gspca_dev);
1247 if (mode) {
1248/* reg17 = 0x21; * 320 */
1249/* reg1 = 0x44; */
1250 reg1 = 0x46;
1251 } else {
1252 reg17 = 0xa2; /* 640 */
1253 reg1 = 0x40;
1254 }
1255 break;
1256 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001257 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001258 switch (sd->bridge) {
1259 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001260 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001261 break;
1262 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001263 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001264 break;
1265 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001266 switch (sd->bridge) {
1267 case BRIDGE_SN9C120: /*jfm ?? */
1268 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001269 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001270 break;
1271 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001272 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001273 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1274 break;
1275 }
1276
1277 /* here change size mode 0 -> VGA; 1 -> CIF */
1278 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001279 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001280
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001281 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1282 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001283
1284 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001285 reg_w(gspca_dev, 0x18, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001286
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001287 reg_w(gspca_dev, 0x17, &reg17, 1);
1288 reg_w(gspca_dev, 0x01, &reg1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001289 setbrightness(gspca_dev);
1290 setcontrast(gspca_dev);
1291}
1292
1293static void sd_stopN(struct gspca_dev *gspca_dev)
1294{
1295 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001296 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001297 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001298 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001299 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1300 __u8 regF1;
1301 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001302 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001303
1304 data = 0x0b;
1305 switch (sd->sensor) {
1306 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001307 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001308 data = 0x2b;
1309 break;
1310 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001311 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001312 data = 0x29;
1313 break;
1314 case SENSOR_MO4000:
1315 break;
1316 case SENSOR_OV7648:
1317 data = 0x29;
1318 break;
1319 default:
1320/* case SENSOR_OV7660: */
1321 break;
1322 }
1323 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001324 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1325 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1326 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1327 reg_w(gspca_dev, 0x01, &data, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001328 regF1 = 0x01;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001329 reg_w(gspca_dev, 0xf1, &regF1, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001330}
1331
1332static void sd_stop0(struct gspca_dev *gspca_dev)
1333{
1334}
1335
1336static void sd_close(struct gspca_dev *gspca_dev)
1337{
1338}
1339
1340static void setautogain(struct gspca_dev *gspca_dev)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343 /* Thanks S., without your advice, autobright should not work :) */
1344 int delta;
1345 int expotimes = 0;
1346 __u8 luma_mean = 130;
1347 __u8 luma_delta = 20;
1348
1349 delta = sd->avg_lum;
1350 if (delta < luma_mean - luma_delta ||
1351 delta > luma_mean + luma_delta) {
1352 switch (sd->sensor) {
1353 case SENSOR_HV7131R:
1354 expotimes = sd->exposure >> 8;
1355 expotimes += (luma_mean - delta) >> 4;
1356 if (expotimes < 0)
1357 expotimes = 0;
1358 sd->exposure = setexposure(gspca_dev,
1359 (unsigned int) (expotimes << 8));
1360 break;
1361 case SENSOR_MO4000:
1362 case SENSOR_MI0360:
1363 expotimes = sd->exposure;
1364 expotimes += (luma_mean - delta) >> 6;
1365 if (expotimes < 0)
1366 expotimes = 0;
1367 sd->exposure = setexposure(gspca_dev,
1368 (unsigned int) expotimes);
1369 setcolors(gspca_dev);
1370 break;
1371 }
1372 }
1373}
1374
1375static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1376 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001377 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001378 int len) /* iso packet length */
1379{
1380 struct sd *sd = (struct sd *) gspca_dev;
1381 int sof, avg_lum;
1382
1383 sof = len - 64;
1384 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1385
1386 /* end of frame */
1387 gspca_frame_add(gspca_dev, LAST_PACKET,
1388 frame, data, sof + 2);
1389 if (sd->ag_cnt < 0)
1390 return;
1391 if (--sd->ag_cnt >= 0)
1392 return;
1393 sd->ag_cnt = AG_CNT_START;
1394/* w1 w2 w3 */
1395/* w4 w5 w6 */
1396/* w7 w8 */
1397/* w4 */
1398 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1399/* w6 */
1400 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1401/* w2 */
1402 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1403/* w8 */
1404 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1405/* w5 */
1406 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1407 avg_lum >>= 4;
1408 sd->avg_lum = avg_lum;
1409 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1410 setautogain(gspca_dev);
1411 return;
1412 }
1413 if (gspca_dev->last_packet_type == LAST_PACKET) {
1414
1415 /* put the JPEG 422 header */
1416 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1417 }
1418 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1419}
1420
1421static unsigned int getexposure(struct gspca_dev *gspca_dev)
1422{
1423 struct sd *sd = (struct sd *) gspca_dev;
1424 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001425
1426 switch (sd->sensor) {
1427 case SENSOR_HV7131R:
1428 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001429 i2c_r5(gspca_dev, 0x25);
1430 return (gspca_dev->usb_buf[0] << 16)
1431 | (gspca_dev->usb_buf[1] << 8)
1432 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001433 case SENSOR_MI0360:
1434 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001435 i2c_r5(gspca_dev, 0x09);
1436 return (gspca_dev->usb_buf[0] << 8)
1437 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001438 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001439 i2c_r5(gspca_dev, 0x0e);
1440 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1441 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1442 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001443 PDEBUG(D_CONF, "exposure %d",
1444 (hexpo << 10) | (mexpo << 2) | lexpo);
1445 return (hexpo << 10) | (mexpo << 2) | lexpo;
1446 default:
1447/* case SENSOR_OV7660: */
1448 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001449 i2c_r5(gspca_dev, 0x04);
1450 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1451 lexpo = gspca_dev->usb_buf[0] & 0x02;
1452 i2c_r5(gspca_dev, 0x08);
1453 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001454 return (hexpo << 10) | (mexpo << 2) | lexpo;
1455 }
1456}
1457
1458static void getbrightness(struct gspca_dev *gspca_dev)
1459{
1460 struct sd *sd = (struct sd *) gspca_dev;
1461
1462 /* hardcoded registers seem not readable */
1463 switch (sd->sensor) {
1464 case SENSOR_HV7131R:
1465/* sd->brightness = 0x7fff; */
1466 sd->brightness = getexposure(gspca_dev) >> 4;
1467 break;
1468 case SENSOR_MI0360:
1469 sd->brightness = getexposure(gspca_dev) << 4;
1470 break;
1471 case SENSOR_MO4000:
1472/* sd->brightness = 0x1fff; */
1473 sd->brightness = getexposure(gspca_dev) << 4;
1474 break;
1475 }
1476}
1477
1478static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1479{
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 sd->brightness = val;
1483 if (gspca_dev->streaming)
1484 setbrightness(gspca_dev);
1485 return 0;
1486}
1487
1488static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1489{
1490 struct sd *sd = (struct sd *) gspca_dev;
1491
1492 getbrightness(gspca_dev);
1493 *val = sd->brightness;
1494 return 0;
1495}
1496
1497static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1498{
1499 struct sd *sd = (struct sd *) gspca_dev;
1500
1501 sd->contrast = val;
1502 if (gspca_dev->streaming)
1503 setcontrast(gspca_dev);
1504 return 0;
1505}
1506
1507static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1508{
1509 struct sd *sd = (struct sd *) gspca_dev;
1510
1511 *val = sd->contrast;
1512 return 0;
1513}
1514
1515static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 sd->colors = val;
1520 if (gspca_dev->streaming)
1521 setcolors(gspca_dev);
1522 return 0;
1523}
1524
1525static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528
1529 *val = sd->colors;
1530 return 0;
1531}
1532
1533static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 sd->autogain = val;
1538 if (val)
1539 sd->ag_cnt = AG_CNT_START;
1540 else
1541 sd->ag_cnt = -1;
1542 return 0;
1543}
1544
1545static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1546{
1547 struct sd *sd = (struct sd *) gspca_dev;
1548
1549 *val = sd->autogain;
1550 return 0;
1551}
1552
1553/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001554static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001555 .name = MODULE_NAME,
1556 .ctrls = sd_ctrls,
1557 .nctrls = ARRAY_SIZE(sd_ctrls),
1558 .config = sd_config,
1559 .open = sd_open,
1560 .start = sd_start,
1561 .stopN = sd_stopN,
1562 .stop0 = sd_stop0,
1563 .close = sd_close,
1564 .pkt_scan = sd_pkt_scan,
1565};
1566
1567/* -- module initialisation -- */
1568#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001569static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001570#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001571 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1572 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1573 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1574 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1575 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001576#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001577 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1578 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1579 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1580 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1581 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1582 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1583 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1584 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1585 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001586#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001587 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1588 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1589 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1590 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001591#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001592 {}
1593};
1594MODULE_DEVICE_TABLE(usb, device_table);
1595
1596/* -- device connect -- */
1597static int sd_probe(struct usb_interface *intf,
1598 const struct usb_device_id *id)
1599{
1600 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1601 THIS_MODULE);
1602}
1603
1604static struct usb_driver sd_driver = {
1605 .name = MODULE_NAME,
1606 .id_table = device_table,
1607 .probe = sd_probe,
1608 .disconnect = gspca_disconnect,
1609};
1610
1611/* -- module insert / remove -- */
1612static int __init sd_mod_init(void)
1613{
1614 if (usb_register(&sd_driver) < 0)
1615 return -1;
1616 info("v%s registered", version);
1617 return 0;
1618}
1619static void __exit sd_mod_exit(void)
1620{
1621 usb_deregister(&sd_driver);
1622 info("deregistered");
1623}
1624
1625module_init(sd_mod_init);
1626module_exit(sd_mod_exit);