blob: 35b1a3ee4c3f806634e4484f3562144b7495a0ed [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 __u16 product;
799
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300800 product = id->idProduct;
801 sd->sensor = -1;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300802 switch (id->idVendor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 case 0x0458: /* Genius */
804/* switch (product) {
805 case 0x7025: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300806 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300807 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300808 sd->i2c_base = 0x5d;
809/* break;
810 } */
811 break;
812 case 0x045e:
813/* switch (product) {
814 case 0x00f5:
815 case 0x00f7: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300816 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300817 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 sd->i2c_base = 0x21;
819/* break;
820 } */
821 break;
822 case 0x0471: /* Philips */
823/* switch (product) {
824 case 0x0327:
825 case 0x0328:
826 case 0x0330: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300827 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300828 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 sd->i2c_base = 0x5d;
830/* break;
831 } */
832 break;
833 case 0x0c45: /* Sonix */
834 switch (product) {
835 case 0x6040:
Hans de Goede3647fea2008-07-15 05:36:30 -0300836 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300837/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
838/*fixme: MI0360 base=5d ? */
839 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300840 sd->i2c_base = 0x11;
841 break;
842/* case 0x607a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300843 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300845 sd->i2c_base = 0x??;
846 break; */
847 case 0x607c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300848 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300849 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300850 sd->i2c_base = 0x11;
851 break;
852/* case 0x607e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300853 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300854 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 sd->i2c_base = 0x??;
856 break; */
857 case 0x60c0:
Hans de Goede3647fea2008-07-15 05:36:30 -0300858 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860 sd->i2c_base = 0x5d;
861 break;
862/* case 0x60c8: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300863 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300864 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300865 sd->i2c_base = 0x??;
866 break; */
867/* case 0x60cc: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300868 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300869 sd->sensor = SENSOR_HV7131GP;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300870 sd->i2c_base = 0x??;
871 break; */
872 case 0x60ec:
Hans de Goede3647fea2008-07-15 05:36:30 -0300873 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300874 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875 sd->i2c_base = 0x21;
876 break;
877/* case 0x60ef: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300878 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300879 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880 sd->i2c_base = 0x??;
881 break; */
882/* case 0x60fa: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300883 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300885 sd->i2c_base = 0x??;
886 break; */
887 case 0x60fb:
Hans de Goede3647fea2008-07-15 05:36:30 -0300888 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300889 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300890 sd->i2c_base = 0x21;
891 break;
892 case 0x60fc:
Hans de Goede3647fea2008-07-15 05:36:30 -0300893 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300894 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300895 sd->i2c_base = 0x11;
896 break;
897/* case 0x60fe: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300898 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300899 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300900 sd->i2c_base = 0x??;
901 break; */
902/* case 0x6108: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300903 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300904 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300905 sd->i2c_base = 0x??;
906 break; */
907/* case 0x6122: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300908 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300909 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300910 sd->i2c_base = 0x??;
911 break; */
912 case 0x612a:
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300913/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
Hans de Goede3647fea2008-07-15 05:36:30 -0300914 sd->bridge = BRIDGE_SN9C325;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300915 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300916 sd->i2c_base = 0x21;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300917/*fixme: sensor_init has base = 00 et 6e!*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 break;
919/* case 0x6123: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300920 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 sd->sensor = SENSOR_SanyoCCD;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300922 sd->i2c_base = 0x??;
923 break; */
924 case 0x612c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300925 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300926 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300927 sd->i2c_base = 0x21;
928 break;
929/* case 0x612e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300930 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300931 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300932 sd->i2c_base = 0x??;
933 break; */
934/* case 0x612f: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300935 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300936 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300937 sd->i2c_base = 0x??;
938 break; */
939 case 0x6130:
Hans de Goede3647fea2008-07-15 05:36:30 -0300940 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300941 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300942 sd->i2c_base = 0x5d;
943 break;
944 case 0x6138:
Hans de Goede3647fea2008-07-15 05:36:30 -0300945 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300947 sd->i2c_base = 0x21;
948 break;
949/* case 0x613a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300950 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300951 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300952 sd->i2c_base = 0x??;
953 break; */
954 case 0x613b:
Hans de Goede3647fea2008-07-15 05:36:30 -0300955 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300956 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300957 sd->i2c_base = 0x21;
958 break;
959 case 0x613c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300960 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300962 sd->i2c_base = 0x11;
963 break;
964/* case 0x613e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300965 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300967 sd->i2c_base = 0x??;
968 break; */
969 }
970 break;
971 }
972 if (sd->sensor < 0) {
973 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
Jean-Francois Moine60017612008-07-18 08:46:19 -0300974 id->idVendor, product);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300975 return -EINVAL;
976 }
977
978 cam = &gspca_dev->cam;
979 cam->dev_name = (char *) id->driver_info;
980 cam->epaddr = 0x01;
981 cam->cam_mode = vga_mode;
982 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300983
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300984 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300985 sd->brightness = BRIGHTNESS_DEF;
986 sd->contrast = CONTRAST_DEF;
987 sd->colors = COLOR_DEF;
988 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989 return 0;
990}
991
992/* this function is called at open time */
993static int sd_open(struct gspca_dev *gspca_dev)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300996/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300997 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -0300998 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300999
Hans de Goede3647fea2008-07-15 05:36:30 -03001000 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001001 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001002 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001003 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001004 reg_r(gspca_dev, 0x00, 1);
1005 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -03001006 switch (sd->bridge) {
1007 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001008 if (regF1 != 0x11)
1009 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001010 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001012 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 if (regF1 != 0x11)
1014 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001015 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001016 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001017 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001018 if (regF1 != 0x12)
1019 return -ENODEV;
1020 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001021 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022 break;
1023 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001024/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -03001025/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 if (regF1 != 0x12)
1027 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001028 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001029 break;
1030 }
1031
Jean-Francois Moine60017612008-07-18 08:46:19 -03001032 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001033
1034 return 0;
1035}
1036
1037static unsigned int setexposure(struct gspca_dev *gspca_dev,
1038 unsigned int expo)
1039{
1040 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001041 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001042 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001043 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001045 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1047
1048 switch (sd->sensor) {
1049 case SENSOR_HV7131R: {
1050 __u8 Expodoit[] =
1051 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1052
1053 Expodoit[3] = expo >> 16;
1054 Expodoit[4] = expo >> 8;
1055 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001056 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057 break;
1058 }
1059 case SENSOR_MI0360: {
1060 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1061 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1062
1063 if (expo > 0x0635)
1064 expo = 0x0635;
1065 else if (expo < 0x0001)
1066 expo = 0x0001;
1067 expoMi[3] = expo >> 8;
1068 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001069 i2c_w8(gspca_dev, expoMi);
1070 i2c_w8(gspca_dev, doit);
1071 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072 break;
1073 }
1074 case SENSOR_MO4000: {
1075 __u8 expoMof[] =
1076 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1077 __u8 expoMo10[] =
1078 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1079
1080 if (expo > 0x1fff)
1081 expo = 0x1fff;
1082 else if (expo < 0x0001)
1083 expo = 0x0001;
1084 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001085 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001086 expoMo10[3] = ((expo & 0x1c00) >> 10)
1087 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001088 i2c_w8(gspca_dev, expoMo10);
1089 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001090 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 ((expoMo10[3] & 0x07) << 10)
1092 | (expoMof[3] << 2)
1093 | ((expoMo10[3] & 0x30) >> 4));
1094 break;
1095 }
1096 }
1097 return expo;
1098}
1099
1100static void setbrightness(struct gspca_dev *gspca_dev)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103 unsigned int expo;
1104 __u8 k2;
1105
1106 switch (sd->sensor) {
1107 case SENSOR_HV7131R:
1108 expo = sd->brightness << 4;
1109 if (expo > 0x002dc6c0)
1110 expo = 0x002dc6c0;
1111 else if (expo < 0x02a0)
1112 expo = 0x02a0;
1113 sd->exposure = setexposure(gspca_dev, expo);
1114 break;
1115 case SENSOR_MI0360:
1116 expo = sd->brightness >> 4;
1117 sd->exposure = setexposure(gspca_dev, expo);
1118 break;
1119 case SENSOR_MO4000:
1120 expo = sd->brightness >> 4;
1121 sd->exposure = setexposure(gspca_dev, expo);
1122 break;
1123 case SENSOR_OV7660:
1124 return; /*jfm??*/
1125 }
1126
1127 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001128 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001129}
1130
1131static void setcontrast(struct gspca_dev *gspca_dev)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134 __u8 k2;
1135 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1136
1137 if (sd->sensor == SENSOR_OV7660)
1138 return; /*jfm??*/
1139 k2 = sd->contrast;
1140 contrast[2] = k2;
1141 contrast[0] = (k2 + 1) >> 1;
1142 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001143 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144}
1145
1146static void setcolors(struct gspca_dev *gspca_dev)
1147{
1148 struct sd *sd = (struct sd *) gspca_dev;
1149 __u8 data;
1150 int colour;
1151
1152 colour = sd->colors - 128;
1153 if (colour > 0)
1154 data = (colour + 32) & 0x7f; /* blue */
1155 else
1156 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001157 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001158}
1159
1160/* -- start the camera -- */
1161static void sd_start(struct gspca_dev *gspca_dev)
1162{
1163 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001164 int i;
1165 __u8 data;
1166 __u8 reg1;
1167 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001168 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001169 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001170 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1171 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1172 static const __u8 CA_sn9c120[] =
1173 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1174 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1175 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001176 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1177
1178 sn9c1xx = sn_tb[(int) sd->sensor];
1179 configure_gpio(gspca_dev, sn9c1xx);
1180
1181/*fixme:jfm this sequence should appear at end of sd_start */
1182/* with
Jean-Francois Moine60017612008-07-18 08:46:19 -03001183 reg_w1(gspca_dev, 0x01, 0x44); */
1184 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1185 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1186 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1187 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1188 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1189 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1190 reg_w1(gspca_dev, 0xd3, 0x50);
1191 reg_w1(gspca_dev, 0xc6, 0x00);
1192 reg_w1(gspca_dev, 0xc7, 0x00);
1193 reg_w1(gspca_dev, 0xc8, 0x50);
1194 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001195/*fixme:jfm end of ending sequence */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001196 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001197 switch (sd->bridge) {
1198 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001199 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001200 break;
1201 case BRIDGE_SN9C120:
1202 data = 0xa0;
1203 break;
1204 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001205 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001206 break;
1207 }
Jean-Francois Moine60017612008-07-18 08:46:19 -03001208 reg_w1(gspca_dev, 0x17, data);
1209 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1210 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1211 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1212 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001213 switch (sd->bridge) {
1214 case BRIDGE_SN9C325:
1215 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1216 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001218 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1219 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001220 reg_w1(gspca_dev, 0x9a, 0x0a);
1221 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001222 break;
1223 case BRIDGE_SN9C120:
1224 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1225 sizeof regsn20_sn9c120);
1226 for (i = 0; i < 2; i++)
1227 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1228 sizeof reg84_sn9c120_1);
1229 for (i = 0; i < 6; i++)
1230 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1231 sizeof reg84_sn9c120_2);
1232 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1233 sizeof reg84_sn9c120_3);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001234 reg_w1(gspca_dev, 0x9a, 0x05);
1235 reg_w1(gspca_dev, 0x99, 0x5b);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001236 break;
1237 default:
1238 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001239 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001240 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001241 reg_w1(gspca_dev, 0x9a, 0x08);
1242 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001243 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001244 }
1245
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001246 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001247 if (mode)
1248 reg1 = 0x46; /* 320 clk 48Mhz */
1249 else
1250 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001251 reg17 = 0x61;
1252 switch (sd->sensor) {
1253 case SENSOR_HV7131R:
1254 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001255 break;
1256 case SENSOR_MI0360:
1257 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001258 break;
1259 case SENSOR_MO4000:
1260 mo4000_InitSensor(gspca_dev);
1261 if (mode) {
1262/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1263 reg1 = 0x06; /* clk 24Mz */
1264 } else {
1265 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001266/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001267 }
1268 break;
1269 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001270 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001271 reg17 = 0xa2;
1272 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001273/* if (mode)
1274 ; * 320x2...
1275 else
1276 ; * 640x... */
1277 break;
1278 default:
1279/* case SENSOR_OV7660: */
1280 ov7660_InitSensor(gspca_dev);
1281 if (mode) {
1282/* reg17 = 0x21; * 320 */
1283/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001284/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 } else {
1286 reg17 = 0xa2; /* 640 */
1287 reg1 = 0x40;
1288 }
1289 break;
1290 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001291 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001292 switch (sd->bridge) {
1293 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001294 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001295 break;
1296 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001297 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001298 break;
1299 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001300 switch (sd->bridge) {
1301 case BRIDGE_SN9C120: /*jfm ?? */
1302 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001303 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001304 break;
1305 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001306 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001307 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1308 break;
1309 }
1310
1311 /* here change size mode 0 -> VGA; 1 -> CIF */
1312 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001313 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001314
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001315 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1316 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001317
1318 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001319 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001320
Jean-Francois Moine60017612008-07-18 08:46:19 -03001321 reg_w1(gspca_dev, 0x17, reg17);
1322 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001323 setbrightness(gspca_dev);
1324 setcontrast(gspca_dev);
1325}
1326
1327static void sd_stopN(struct gspca_dev *gspca_dev)
1328{
1329 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001330 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001331 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001332 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001333 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001334 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001335 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001336
1337 data = 0x0b;
1338 switch (sd->sensor) {
1339 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001340 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001341 data = 0x2b;
1342 break;
1343 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001344 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001345 data = 0x29;
1346 break;
1347 case SENSOR_MO4000:
1348 break;
1349 case SENSOR_OV7648:
1350 data = 0x29;
1351 break;
1352 default:
1353/* case SENSOR_OV7660: */
1354 break;
1355 }
1356 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001357 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1358 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1359 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1360 reg_w1(gspca_dev, 0x01, data);
1361 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001362}
1363
1364static void sd_stop0(struct gspca_dev *gspca_dev)
1365{
1366}
1367
1368static void sd_close(struct gspca_dev *gspca_dev)
1369{
1370}
1371
1372static void setautogain(struct gspca_dev *gspca_dev)
1373{
1374 struct sd *sd = (struct sd *) gspca_dev;
1375 /* Thanks S., without your advice, autobright should not work :) */
1376 int delta;
1377 int expotimes = 0;
1378 __u8 luma_mean = 130;
1379 __u8 luma_delta = 20;
1380
1381 delta = sd->avg_lum;
1382 if (delta < luma_mean - luma_delta ||
1383 delta > luma_mean + luma_delta) {
1384 switch (sd->sensor) {
1385 case SENSOR_HV7131R:
1386 expotimes = sd->exposure >> 8;
1387 expotimes += (luma_mean - delta) >> 4;
1388 if (expotimes < 0)
1389 expotimes = 0;
1390 sd->exposure = setexposure(gspca_dev,
1391 (unsigned int) (expotimes << 8));
1392 break;
1393 case SENSOR_MO4000:
1394 case SENSOR_MI0360:
1395 expotimes = sd->exposure;
1396 expotimes += (luma_mean - delta) >> 6;
1397 if (expotimes < 0)
1398 expotimes = 0;
1399 sd->exposure = setexposure(gspca_dev,
1400 (unsigned int) expotimes);
1401 setcolors(gspca_dev);
1402 break;
1403 }
1404 }
1405}
1406
1407static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1408 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001409 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001410 int len) /* iso packet length */
1411{
1412 struct sd *sd = (struct sd *) gspca_dev;
1413 int sof, avg_lum;
1414
1415 sof = len - 64;
1416 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1417
1418 /* end of frame */
1419 gspca_frame_add(gspca_dev, LAST_PACKET,
1420 frame, data, sof + 2);
1421 if (sd->ag_cnt < 0)
1422 return;
1423 if (--sd->ag_cnt >= 0)
1424 return;
1425 sd->ag_cnt = AG_CNT_START;
1426/* w1 w2 w3 */
1427/* w4 w5 w6 */
1428/* w7 w8 */
1429/* w4 */
1430 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1431/* w6 */
1432 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1433/* w2 */
1434 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1435/* w8 */
1436 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1437/* w5 */
1438 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1439 avg_lum >>= 4;
1440 sd->avg_lum = avg_lum;
1441 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1442 setautogain(gspca_dev);
1443 return;
1444 }
1445 if (gspca_dev->last_packet_type == LAST_PACKET) {
1446
1447 /* put the JPEG 422 header */
1448 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1449 }
1450 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1451}
1452
1453static unsigned int getexposure(struct gspca_dev *gspca_dev)
1454{
1455 struct sd *sd = (struct sd *) gspca_dev;
1456 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001457
1458 switch (sd->sensor) {
1459 case SENSOR_HV7131R:
1460 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001461 i2c_r5(gspca_dev, 0x25);
1462 return (gspca_dev->usb_buf[0] << 16)
1463 | (gspca_dev->usb_buf[1] << 8)
1464 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001465 case SENSOR_MI0360:
1466 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001467 i2c_r5(gspca_dev, 0x09);
1468 return (gspca_dev->usb_buf[0] << 8)
1469 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001470 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001471 i2c_r5(gspca_dev, 0x0e);
1472 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1473 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1474 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001475 PDEBUG(D_CONF, "exposure %d",
1476 (hexpo << 10) | (mexpo << 2) | lexpo);
1477 return (hexpo << 10) | (mexpo << 2) | lexpo;
1478 default:
1479/* case SENSOR_OV7660: */
1480 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001481 i2c_r5(gspca_dev, 0x04);
1482 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1483 lexpo = gspca_dev->usb_buf[0] & 0x02;
1484 i2c_r5(gspca_dev, 0x08);
1485 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001486 return (hexpo << 10) | (mexpo << 2) | lexpo;
1487 }
1488}
1489
1490static void getbrightness(struct gspca_dev *gspca_dev)
1491{
1492 struct sd *sd = (struct sd *) gspca_dev;
1493
1494 /* hardcoded registers seem not readable */
1495 switch (sd->sensor) {
1496 case SENSOR_HV7131R:
1497/* sd->brightness = 0x7fff; */
1498 sd->brightness = getexposure(gspca_dev) >> 4;
1499 break;
1500 case SENSOR_MI0360:
1501 sd->brightness = getexposure(gspca_dev) << 4;
1502 break;
1503 case SENSOR_MO4000:
1504/* sd->brightness = 0x1fff; */
1505 sd->brightness = getexposure(gspca_dev) << 4;
1506 break;
1507 }
1508}
1509
1510static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1511{
1512 struct sd *sd = (struct sd *) gspca_dev;
1513
1514 sd->brightness = val;
1515 if (gspca_dev->streaming)
1516 setbrightness(gspca_dev);
1517 return 0;
1518}
1519
1520static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1521{
1522 struct sd *sd = (struct sd *) gspca_dev;
1523
1524 getbrightness(gspca_dev);
1525 *val = sd->brightness;
1526 return 0;
1527}
1528
1529static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1530{
1531 struct sd *sd = (struct sd *) gspca_dev;
1532
1533 sd->contrast = val;
1534 if (gspca_dev->streaming)
1535 setcontrast(gspca_dev);
1536 return 0;
1537}
1538
1539static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1540{
1541 struct sd *sd = (struct sd *) gspca_dev;
1542
1543 *val = sd->contrast;
1544 return 0;
1545}
1546
1547static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1548{
1549 struct sd *sd = (struct sd *) gspca_dev;
1550
1551 sd->colors = val;
1552 if (gspca_dev->streaming)
1553 setcolors(gspca_dev);
1554 return 0;
1555}
1556
1557static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1558{
1559 struct sd *sd = (struct sd *) gspca_dev;
1560
1561 *val = sd->colors;
1562 return 0;
1563}
1564
1565static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1566{
1567 struct sd *sd = (struct sd *) gspca_dev;
1568
1569 sd->autogain = val;
1570 if (val)
1571 sd->ag_cnt = AG_CNT_START;
1572 else
1573 sd->ag_cnt = -1;
1574 return 0;
1575}
1576
1577static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1578{
1579 struct sd *sd = (struct sd *) gspca_dev;
1580
1581 *val = sd->autogain;
1582 return 0;
1583}
1584
1585/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001586static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001587 .name = MODULE_NAME,
1588 .ctrls = sd_ctrls,
1589 .nctrls = ARRAY_SIZE(sd_ctrls),
1590 .config = sd_config,
1591 .open = sd_open,
1592 .start = sd_start,
1593 .stopN = sd_stopN,
1594 .stop0 = sd_stop0,
1595 .close = sd_close,
1596 .pkt_scan = sd_pkt_scan,
1597};
1598
1599/* -- module initialisation -- */
1600#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001601static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001602#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001603 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1604 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1605 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1606 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1607 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001608#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001609 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1610 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1611 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1612 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1613 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1614 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1615 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1616 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1617 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001618#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001619 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1620 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1621 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1622 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001623#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001624 {}
1625};
1626MODULE_DEVICE_TABLE(usb, device_table);
1627
1628/* -- device connect -- */
1629static int sd_probe(struct usb_interface *intf,
1630 const struct usb_device_id *id)
1631{
1632 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1633 THIS_MODULE);
1634}
1635
1636static struct usb_driver sd_driver = {
1637 .name = MODULE_NAME,
1638 .id_table = device_table,
1639 .probe = sd_probe,
1640 .disconnect = gspca_disconnect,
1641};
1642
1643/* -- module insert / remove -- */
1644static int __init sd_mod_init(void)
1645{
1646 if (usb_register(&sd_driver) < 0)
1647 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001648 info("registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001649 return 0;
1650}
1651static void __exit sd_mod_exit(void)
1652{
1653 usb_deregister(&sd_driver);
1654 info("deregistered");
1655}
1656
1657module_init(sd_mod_init);
1658module_exit(sd_mod_exit);