blob: aa4d10b823ea43c4ccbd3ea597494c096c9d06a9 [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/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300155 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300156/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300158/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300160/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300162};
163
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300164static const __u8 sn_mi0360[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300165/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300167/* rega regb regc regd rege regf reg10 reg11 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300169/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300171/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173};
174
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300175static const __u8 sn_mo4000[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300178/* reg9 rega regb regc regd rege regf reg10 reg11*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300180/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300182/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300184 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*/
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300200 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300201/* 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 Moine568788a2008-07-15 11:46:06 -0300218static const __u8 regsn20_sn9c120[] = {
219 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
220 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
221};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300222static const __u8 regsn20_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300223 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
224 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
225};
226
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300227static const __u8 reg84[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
229 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
230/* 0x00, 0x00, 0x00, 0x00, 0x00 */
231 0xf7, 0x0f, 0x0a, 0x00, 0x00
232};
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300233static const __u8 reg84_sn9c120_1[] = {
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x0c, 0x00, 0x00
237};
238static const __u8 reg84_sn9c120_2[] = {
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x0c, 0x02, 0x3b
242};
243static const __u8 reg84_sn9c120_3[] = {
244 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
245 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
246 0xf5, 0x0f, 0x0c, 0x02, 0x3b
247};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300248static const __u8 reg84_sn9c325[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300249 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
250 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
251 0xf8, 0x0f, 0x00, 0x00, 0x00
252};
253
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300254static const __u8 hv7131r_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300255 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
256 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
258 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
262
263 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
268 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
269 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
270 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
271
272 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
277
278 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300283 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300284};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300285static const __u8 mi0360_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300286 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
287 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
290 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
291 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
292 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
308 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
309 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
311 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
313 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
315 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
318 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
319
320 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
323 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
324 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
325
326 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
327 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
328 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
330
331 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
332 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
333/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
334/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
335 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
336 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300337 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300338};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300339static const __u8 mo4000_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300340 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300360 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300362static const __u8 ov7660_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300364/* (delay 20ms) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300365 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
366 /* Outformat ?? rawRGB */
367 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300368 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
369/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300370 /* GAIN BLUE RED VREF */
371 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
372 /* COM 1 BAVE GEAVE AECHH */
373 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
374 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300375 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
376/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300377 /* AECH CLKRC COM7 COM8 */
378 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
379 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
380 /* HSTART HSTOP VSTRT VSTOP */
381 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
382 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
383 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
384 /* BOS GBOS GROS ROS (BGGR offset) */
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300385 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
386/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300387 /* AEW AEB VPT BBIAS */
388 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
389 /* GbBIAS RSVD EXHCH EXHCL */
390 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
391 /* RBIAS ADVFL ASDVFH YAVE */
392 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
393 /* HSYST HSYEN HREF */
394 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
395 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
396 /* ADC ACOM OFON TSLB */
397 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
398 /* COM11 COM12 COM13 COM14 */
399 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
400 /* EDGE COM15 COM16 COM17 */
401 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
402 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
404 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
405 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
406 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
407 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
408 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
409 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
410 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
411 /* LCC1 LCC2 LCC3 LCC4 */
412 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
413 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
414 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
415 /* band gap reference [0..3] DBLV */
416 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
420 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
421 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
422 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
423 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
424 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
425 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
426/****** (some exchanges in the win trace) ******/
427 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
428 /* bits[3..0]reserved */
429 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
431 /* VREF vertical frame ctrl */
432 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
433 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
434 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300436/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
437 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
438 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300439/****** (some exchanges in the win trace) ******/
440 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
441 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
442 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300444 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300445/****** (some exchanges in the win trace) ******/
446/**********startsensor KO if changed !!****/
447 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
450 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
451/* here may start the isoc exchanges */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300452 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453};
454/* reg0x04 reg0x07 reg 0x10 */
455/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
456
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300457static const __u8 ov7648_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300458 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
459 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
460 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
461 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
462 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
464 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
465 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
466 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
467 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
468 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
469 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
471 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
472 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
473 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
474 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
475 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
476 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
477 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
478 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
479 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
480 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
481 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
482 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
483 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
484 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
485 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
486 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
487 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
488 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
489 * This is currently setting a
490 * blue tint, and some things more , i leave it here for future test if
491 * somene is having problems with color on this sensor
492 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
493 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
494 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
495 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
496 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
497 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
498 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
502 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
503 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
504 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
505 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
506 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
507 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
508 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
509/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300510 {}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511};
512
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300513static const __u8 qtable4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
515 0x06, 0x08, 0x0A, 0x11,
516 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
517 0x19, 0x19, 0x17, 0x15,
518 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
519 0x21, 0x2E, 0x21, 0x23,
520 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
521 0x25, 0x29, 0x2C, 0x29,
522 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
523 0x17, 0x1B, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
527 0x29, 0x29, 0x29, 0x29,
528 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
529 0x29, 0x29, 0x29, 0x29
530};
531
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300532/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
533static void reg_r(struct gspca_dev *gspca_dev,
534 __u16 value, int len)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300536 usb_control_msg(gspca_dev->dev,
537 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538 0,
539 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
540 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300541 gspca_dev->usb_buf, len,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 500);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300543 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544}
545
Jean-Francois Moine60017612008-07-18 08:46:19 -0300546static void reg_w1(struct gspca_dev *gspca_dev,
547 __u16 value,
548 __u8 data)
549{
550 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
551 gspca_dev->usb_buf[0] = data;
552 usb_control_msg(gspca_dev->dev,
553 usb_sndctrlpipe(gspca_dev->dev, 0),
554 0x08,
555 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
556 value,
557 0,
558 gspca_dev->usb_buf, 1,
559 500);
560}
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300561static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300562 __u16 value,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300563 const __u8 *buffer,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300564 int len)
565{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300566 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
567 value, buffer[0], buffer[1]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300568 if (len <= sizeof gspca_dev->usb_buf) {
569 memcpy(gspca_dev->usb_buf, buffer, len);
570 usb_control_msg(gspca_dev->dev,
571 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300572 0x08,
573 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
574 value, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300575 gspca_dev->usb_buf, len,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300576 500);
577 } else {
578 __u8 *tmpbuf;
579
580 tmpbuf = kmalloc(len, GFP_KERNEL);
581 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300582 usb_control_msg(gspca_dev->dev,
583 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300584 0x08,
585 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
586 value, 0,
587 tmpbuf, len,
588 500);
589 kfree(tmpbuf);
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300590 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591}
592
Jean-Francois Moine60017612008-07-18 08:46:19 -0300593/* I2C write 1 byte */
594static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595{
596 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597
Jean-Francois Moine60017612008-07-18 08:46:19 -0300598 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
599 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
600 gspca_dev->usb_buf[1] = sd->i2c_base;
601 gspca_dev->usb_buf[2] = reg;
602 gspca_dev->usb_buf[3] = val;
603 gspca_dev->usb_buf[4] = 0;
604 gspca_dev->usb_buf[5] = 0;
605 gspca_dev->usb_buf[6] = 0;
606 gspca_dev->usb_buf[7] = 0x10;
607 usb_control_msg(gspca_dev->dev,
608 usb_sndctrlpipe(gspca_dev->dev, 0),
609 0x08,
610 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
611 0x08, /* value = i2c */
612 0,
613 gspca_dev->usb_buf, 8,
614 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300615}
616
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300617/* I2C write 8 bytes */
618static void i2c_w8(struct gspca_dev *gspca_dev,
619 const __u8 *buffer)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300620{
Jean-Francois Moine60017612008-07-18 08:46:19 -0300621 memcpy(gspca_dev->usb_buf, buffer, 8);
622 usb_control_msg(gspca_dev->dev,
623 usb_sndctrlpipe(gspca_dev->dev, 0),
624 0x08,
625 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
626 0x08, 0, /* value, index */
627 gspca_dev->usb_buf, 8,
628 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629}
630
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300631/* read 5 bytes in gspca_dev->usb_buf */
632static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633{
634 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 __u8 mode[8];
636
Hans de Goede3647fea2008-07-15 05:36:30 -0300637 mode[0] = 0x81 | 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300638 mode[1] = sd->i2c_base;
639 mode[2] = reg;
640 mode[3] = 0;
641 mode[4] = 0;
642 mode[5] = 0;
643 mode[6] = 0;
644 mode[7] = 0x10;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300645 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300646 msleep(2);
Hans de Goede3647fea2008-07-15 05:36:30 -0300647 mode[0] = 0x81 | (5 << 4) | 0x02;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 mode[2] = 0;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300649 i2c_w8(gspca_dev, mode);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300650 msleep(2);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651 reg_r(gspca_dev, 0x0a, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652}
653
654static int probesensor(struct gspca_dev *gspca_dev)
655{
656 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300657
Jean-Francois Moine60017612008-07-18 08:46:19 -0300658 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300659 msleep(10);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300660 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300661 msleep(10);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300662 i2c_r5(gspca_dev, 0); /* read sensor id */
663 if (gspca_dev->usb_buf[0] == 0x02
664 && gspca_dev->usb_buf[1] == 0x09
665 && gspca_dev->usb_buf[2] == 0x01
666 && gspca_dev->usb_buf[3] == 0x00
667 && gspca_dev->usb_buf[4] == 0x00) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300668 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
669 sd->sensor = SENSOR_HV7131R;
670 return SENSOR_HV7131R;
671 }
Jean-Francois Moine60017612008-07-18 08:46:19 -0300672 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300673 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
674 gspca_dev->usb_buf[2]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
676 return -ENODEV;
677}
678
679static int configure_gpio(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300680 const __u8 *sn9c1xx)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300681{
682 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300683 const __u8 *reg9a;
684 static const __u8 reg9a_def[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300686 static const __u8 reg9a_sn9c120[] = /* from win trace */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300687 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300688 static const __u8 reg9a_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300689 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
690
Jean-Francois Moine60017612008-07-18 08:46:19 -0300691 reg_w1(gspca_dev, 0xf1, 0x00);
692 reg_w1(gspca_dev, 0x01, sn9c1xx[0]); /*fixme:jfm was [1] en v1*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693
694 /* configure gpio */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300695 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
696 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
Jean-Francois Moine60017612008-07-18 08:46:19 -0300697 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
Hans de Goede3647fea2008-07-15 05:36:30 -0300698 switch (sd->bridge) {
699 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300700 reg9a = reg9a_sn9c325;
701 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300702 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703 reg9a = reg9a_sn9c120;
704 break;
705 default:
706 reg9a = reg9a_def;
707 break;
708 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300709 reg_w(gspca_dev, 0x9a, reg9a, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710
Jean-Francois Moine60017612008-07-18 08:46:19 -0300711 reg_w1(gspca_dev, 0xd4, 0x60); /*fixme:jfm 60 00 00 (3) ? */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300712
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300713 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714
Hans de Goede3647fea2008-07-15 05:36:30 -0300715 switch (sd->bridge) {
716 case BRIDGE_SN9C120: /* from win trace */
Jean-Francois Moine60017612008-07-18 08:46:19 -0300717 reg_w1(gspca_dev, 0x01, 0x61);
718 reg_w1(gspca_dev, 0x17, 0x20);
719 reg_w1(gspca_dev, 0x01, 0x60);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720 break;
Hans de Goede3647fea2008-07-15 05:36:30 -0300721 case BRIDGE_SN9C325:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300722 reg_w1(gspca_dev, 0x01, 0x43);
723 reg_w1(gspca_dev, 0x17, 0xae);
724 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725 break;
726 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -0300727 reg_w1(gspca_dev, 0x01, 0x43);
728 reg_w1(gspca_dev, 0x17, 0x61);
729 reg_w1(gspca_dev, 0x01, 0x42);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300730 }
731
732 if (sd->sensor == SENSOR_HV7131R) {
733 if (probesensor(gspca_dev) < 0)
734 return -ENODEV;
735 }
736 return 0;
737}
738
739static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
740{
741 int i = 0;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300742 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
744
745 while (hv7131r_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300746 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300747 i++;
748 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300749 i2c_w8(gspca_dev, SetSensorClk);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300750}
751
752static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
753{
754 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300755
756 while (mi0360_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300757 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300758 i++;
759 }
760}
761
762static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
763{
764 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300765
766 while (mo4000_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300767 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300768 i++;
769 }
770}
771
772static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
773{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300774 int i = 0;
775
776 while (ov7648_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300778 i++;
779 }
780}
781
782static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
783{
784 int i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300785
Jean-Francois Moine60017612008-07-18 08:46:19 -0300786 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
787 i++;
788 msleep(20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789 while (ov7660_sensor_init[i][0]) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300790 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 i++;
792 }
793}
794
795/* this function is called at probe time */
796static int sd_config(struct gspca_dev *gspca_dev,
797 const struct usb_device_id *id)
798{
799 struct sd *sd = (struct sd *) gspca_dev;
800 struct cam *cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300801 __u16 product;
802
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300803 product = id->idProduct;
804 sd->sensor = -1;
Jean-Francois Moine60017612008-07-18 08:46:19 -0300805 switch (id->idVendor) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300806 case 0x0458: /* Genius */
807/* switch (product) {
808 case 0x7025: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300809 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300810 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300811 sd->i2c_base = 0x5d;
812/* break;
813 } */
814 break;
815 case 0x045e:
816/* switch (product) {
817 case 0x00f5:
818 case 0x00f7: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300819 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300820 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300821 sd->i2c_base = 0x21;
822/* break;
823 } */
824 break;
825 case 0x0471: /* Philips */
826/* switch (product) {
827 case 0x0327:
828 case 0x0328:
829 case 0x0330: */
Hans de Goede3647fea2008-07-15 05:36:30 -0300830 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300831 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300832 sd->i2c_base = 0x5d;
833/* break;
834 } */
835 break;
836 case 0x0c45: /* Sonix */
837 switch (product) {
838 case 0x6040:
Hans de Goede3647fea2008-07-15 05:36:30 -0300839 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300840/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
841/*fixme: MI0360 base=5d ? */
842 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300843 sd->i2c_base = 0x11;
844 break;
845/* case 0x607a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300846 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300847 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300848 sd->i2c_base = 0x??;
849 break; */
850 case 0x607c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300851 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300852 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 sd->i2c_base = 0x11;
854 break;
855/* case 0x607e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300856 sd->bridge = BRIDGE_SN9C102P;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300857 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300858 sd->i2c_base = 0x??;
859 break; */
860 case 0x60c0:
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_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300863 sd->i2c_base = 0x5d;
864 break;
865/* case 0x60c8: * from BW600.inf
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_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300868 sd->i2c_base = 0x??;
869 break; */
870/* case 0x60cc: * 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_HV7131GP;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300873 sd->i2c_base = 0x??;
874 break; */
875 case 0x60ec:
Hans de Goede3647fea2008-07-15 05:36:30 -0300876 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300878 sd->i2c_base = 0x21;
879 break;
880/* case 0x60ef: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300881 sd->bridge = BRIDGE_SN9C105;
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 0x60fa: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300886 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300887 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300888 sd->i2c_base = 0x??;
889 break; */
890 case 0x60fb:
Hans de Goede3647fea2008-07-15 05:36:30 -0300891 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300892 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300893 sd->i2c_base = 0x21;
894 break;
895 case 0x60fc:
Hans de Goede3647fea2008-07-15 05:36:30 -0300896 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300897 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300898 sd->i2c_base = 0x11;
899 break;
900/* case 0x60fe: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300901 sd->bridge = BRIDGE_SN9C105;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300902 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300903 sd->i2c_base = 0x??;
904 break; */
905/* case 0x6108: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300906 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300907 sd->sensor = SENSOR_OM6801;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300908 sd->i2c_base = 0x??;
909 break; */
910/* case 0x6122: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300911 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300912 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300913 sd->i2c_base = 0x??;
914 break; */
915 case 0x612a:
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300916/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
Hans de Goede3647fea2008-07-15 05:36:30 -0300917 sd->bridge = BRIDGE_SN9C325;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300918 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300919 sd->i2c_base = 0x21;
Jean-Francois Moine568788a2008-07-15 11:46:06 -0300920/*fixme: sensor_init has base = 00 et 6e!*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300921 break;
922/* case 0x6123: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300923 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300924 sd->sensor = SENSOR_SanyoCCD;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300925 sd->i2c_base = 0x??;
926 break; */
927 case 0x612c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300928 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300929 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300930 sd->i2c_base = 0x21;
931 break;
932/* case 0x612e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300933 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300934 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300935 sd->i2c_base = 0x??;
936 break; */
937/* case 0x612f: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300938 sd->bridge = BRIDGE_SN9C110;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300939 sd->sensor = SENSOR_ICM105C;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300940 sd->i2c_base = 0x??;
941 break; */
942 case 0x6130:
Hans de Goede3647fea2008-07-15 05:36:30 -0300943 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300944 sd->sensor = SENSOR_MI0360;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300945 sd->i2c_base = 0x5d;
946 break;
947 case 0x6138:
Hans de Goede3647fea2008-07-15 05:36:30 -0300948 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300949 sd->sensor = SENSOR_MO4000;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300950 sd->i2c_base = 0x21;
951 break;
952/* case 0x613a: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300953 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300954 sd->sensor = SENSOR_OV7648;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300955 sd->i2c_base = 0x??;
956 break; */
957 case 0x613b:
Hans de Goede3647fea2008-07-15 05:36:30 -0300958 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300959 sd->sensor = SENSOR_OV7660;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300960 sd->i2c_base = 0x21;
961 break;
962 case 0x613c:
Hans de Goede3647fea2008-07-15 05:36:30 -0300963 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300964 sd->sensor = SENSOR_HV7131R;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300965 sd->i2c_base = 0x11;
966 break;
967/* case 0x613e: * from BW600.inf
Hans de Goede3647fea2008-07-15 05:36:30 -0300968 sd->bridge = BRIDGE_SN9C120;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300969 sd->sensor = SENSOR_OV7630;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300970 sd->i2c_base = 0x??;
971 break; */
972 }
973 break;
974 }
975 if (sd->sensor < 0) {
976 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
Jean-Francois Moine60017612008-07-18 08:46:19 -0300977 id->idVendor, product);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300978 return -EINVAL;
979 }
980
981 cam = &gspca_dev->cam;
982 cam->dev_name = (char *) id->driver_info;
983 cam->epaddr = 0x01;
984 cam->cam_mode = vga_mode;
985 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300986
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300987 sd->qindex = 4; /* set the quantization table */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300988 sd->brightness = BRIGHTNESS_DEF;
989 sd->contrast = CONTRAST_DEF;
990 sd->colors = COLOR_DEF;
991 sd->autogain = AUTOGAIN_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300992 return 0;
993}
994
995/* this function is called at open time */
996static int sd_open(struct gspca_dev *gspca_dev)
997{
998 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300999/* const __u8 *sn9c1xx; */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001000 __u8 regGpio[] = { 0x29, 0x74 };
Jean-Francois Moine60017612008-07-18 08:46:19 -03001001 __u8 regF1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001002
Hans de Goede3647fea2008-07-15 05:36:30 -03001003 /* setup a selector by bridge */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001004 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001005 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001006 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001007 reg_r(gspca_dev, 0x00, 1);
1008 regF1 = gspca_dev->usb_buf[0];
Hans de Goede3647fea2008-07-15 05:36:30 -03001009 switch (sd->bridge) {
1010 case BRIDGE_SN9C102P:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 if (regF1 != 0x11)
1012 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001013 reg_w1(gspca_dev, 0x02, regGpio[1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001015 case BRIDGE_SN9C105:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001016 if (regF1 != 0x11)
1017 return -ENODEV;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001018 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001019 break;
Hans de Goede3647fea2008-07-15 05:36:30 -03001020 case BRIDGE_SN9C120:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 if (regF1 != 0x12)
1022 return -ENODEV;
1023 regGpio[1] = 0x70;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001024 reg_w(gspca_dev, 0x02, regGpio, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 break;
1026 default:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001027/* case BRIDGE_SN9C110: */
Hans de Goede3647fea2008-07-15 05:36:30 -03001028/* case BRIDGE_SN9C325: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001029 if (regF1 != 0x12)
1030 return -ENODEV;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001031 reg_w1(gspca_dev, 0x02, 0x62);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032 break;
1033 }
1034
Jean-Francois Moine60017612008-07-18 08:46:19 -03001035 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001036
1037 return 0;
1038}
1039
1040static unsigned int setexposure(struct gspca_dev *gspca_dev,
1041 unsigned int expo)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001044 static const __u8 doit[] = /* update sensor */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001045 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001046 static const __u8 sensorgo[] = /* sensor on */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001048 static const __u8 gainMo[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1050
1051 switch (sd->sensor) {
1052 case SENSOR_HV7131R: {
1053 __u8 Expodoit[] =
1054 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1055
1056 Expodoit[3] = expo >> 16;
1057 Expodoit[4] = expo >> 8;
1058 Expodoit[5] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001059 i2c_w8(gspca_dev, Expodoit);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001060 break;
1061 }
1062 case SENSOR_MI0360: {
1063 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1064 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1065
1066 if (expo > 0x0635)
1067 expo = 0x0635;
1068 else if (expo < 0x0001)
1069 expo = 0x0001;
1070 expoMi[3] = expo >> 8;
1071 expoMi[4] = expo;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001072 i2c_w8(gspca_dev, expoMi);
1073 i2c_w8(gspca_dev, doit);
1074 i2c_w8(gspca_dev, sensorgo);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 break;
1076 }
1077 case SENSOR_MO4000: {
1078 __u8 expoMof[] =
1079 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1080 __u8 expoMo10[] =
1081 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1082
1083 if (expo > 0x1fff)
1084 expo = 0x1fff;
1085 else if (expo < 0x0001)
1086 expo = 0x0001;
1087 expoMof[3] = (expo & 0x03fc) >> 2;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001088 i2c_w8(gspca_dev, expoMof);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001089 expoMo10[3] = ((expo & 0x1c00) >> 10)
1090 | ((expo & 0x0003) << 4);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001091 i2c_w8(gspca_dev, expoMo10);
1092 i2c_w8(gspca_dev, gainMo);
Jean-Francois Moine956e42d2008-07-01 10:03:42 -03001093 PDEBUG(D_CONF, "set exposure %d",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001094 ((expoMo10[3] & 0x07) << 10)
1095 | (expoMof[3] << 2)
1096 | ((expoMo10[3] & 0x30) >> 4));
1097 break;
1098 }
1099 }
1100 return expo;
1101}
1102
1103static void setbrightness(struct gspca_dev *gspca_dev)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106 unsigned int expo;
1107 __u8 k2;
1108
1109 switch (sd->sensor) {
1110 case SENSOR_HV7131R:
1111 expo = sd->brightness << 4;
1112 if (expo > 0x002dc6c0)
1113 expo = 0x002dc6c0;
1114 else if (expo < 0x02a0)
1115 expo = 0x02a0;
1116 sd->exposure = setexposure(gspca_dev, expo);
1117 break;
1118 case SENSOR_MI0360:
1119 expo = sd->brightness >> 4;
1120 sd->exposure = setexposure(gspca_dev, expo);
1121 break;
1122 case SENSOR_MO4000:
1123 expo = sd->brightness >> 4;
1124 sd->exposure = setexposure(gspca_dev, expo);
1125 break;
1126 case SENSOR_OV7660:
1127 return; /*jfm??*/
1128 }
1129
1130 k2 = sd->brightness >> 10;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001131 reg_w1(gspca_dev, 0x96, k2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001132}
1133
1134static void setcontrast(struct gspca_dev *gspca_dev)
1135{
1136 struct sd *sd = (struct sd *) gspca_dev;
1137 __u8 k2;
1138 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1139
1140 if (sd->sensor == SENSOR_OV7660)
1141 return; /*jfm??*/
1142 k2 = sd->contrast;
1143 contrast[2] = k2;
1144 contrast[0] = (k2 + 1) >> 1;
1145 contrast[4] = (k2 + 1) / 5;
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001146 reg_w(gspca_dev, 0x84, contrast, 6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001147}
1148
1149static void setcolors(struct gspca_dev *gspca_dev)
1150{
1151 struct sd *sd = (struct sd *) gspca_dev;
1152 __u8 data;
1153 int colour;
1154
1155 colour = sd->colors - 128;
1156 if (colour > 0)
1157 data = (colour + 32) & 0x7f; /* blue */
1158 else
1159 data = (-colour + 32) & 0x7f; /* red */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001160 reg_w1(gspca_dev, 0x05, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161}
1162
1163/* -- start the camera -- */
1164static void sd_start(struct gspca_dev *gspca_dev)
1165{
1166 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001167 int i;
1168 __u8 data;
1169 __u8 reg1;
1170 __u8 reg17;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001171 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001172 int mode;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001173 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1174 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1175 static const __u8 CA_sn9c120[] =
1176 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1177 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1178 static const __u8 CE_sn9c325[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001179 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1180
1181 sn9c1xx = sn_tb[(int) sd->sensor];
1182 configure_gpio(gspca_dev, sn9c1xx);
1183
1184/*fixme:jfm this sequence should appear at end of sd_start */
1185/* with
Jean-Francois Moine60017612008-07-18 08:46:19 -03001186 reg_w1(gspca_dev, 0x01, 0x44); */
1187 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1188 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1189 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1190 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1191 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1192 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1193 reg_w1(gspca_dev, 0xd3, 0x50);
1194 reg_w1(gspca_dev, 0xc6, 0x00);
1195 reg_w1(gspca_dev, 0xc7, 0x00);
1196 reg_w1(gspca_dev, 0xc8, 0x50);
1197 reg_w1(gspca_dev, 0xc9, 0x3c);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001198/*fixme:jfm end of ending sequence */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001199 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001200 switch (sd->bridge) {
1201 case BRIDGE_SN9C325:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001202 data = 0xae;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001203 break;
1204 case BRIDGE_SN9C120:
1205 data = 0xa0;
1206 break;
1207 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208 data = 0x60;
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001209 break;
1210 }
Jean-Francois Moine60017612008-07-18 08:46:19 -03001211 reg_w1(gspca_dev, 0x17, data);
1212 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1213 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1214 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1215 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001216 switch (sd->bridge) {
1217 case BRIDGE_SN9C325:
1218 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1219 sizeof regsn20_sn9c325);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001220 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001221 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1222 sizeof reg84_sn9c325);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001223 reg_w1(gspca_dev, 0x9a, 0x0a);
1224 reg_w1(gspca_dev, 0x99, 0x60);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001225 break;
1226 case BRIDGE_SN9C120:
1227 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1228 sizeof regsn20_sn9c120);
1229 for (i = 0; i < 2; i++)
1230 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1231 sizeof reg84_sn9c120_1);
1232 for (i = 0; i < 6; i++)
1233 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1234 sizeof reg84_sn9c120_2);
1235 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1236 sizeof reg84_sn9c120_3);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001237 reg_w1(gspca_dev, 0x9a, 0x05);
1238 reg_w1(gspca_dev, 0x99, 0x5b);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001239 break;
1240 default:
1241 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001242 for (i = 0; i < 8; i++)
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001243 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001244 reg_w1(gspca_dev, 0x9a, 0x08);
1245 reg_w1(gspca_dev, 0x99, 0x59);
Jean-Francois Moine568788a2008-07-15 11:46:06 -03001246 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001247 }
1248
Jean-Francois Moinec2446b32008-07-05 11:49:20 -03001249 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine60017612008-07-18 08:46:19 -03001250 if (mode)
1251 reg1 = 0x46; /* 320 clk 48Mhz */
1252 else
1253 reg1 = 0x06; /* 640 clk 24Mz */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001254 reg17 = 0x61;
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 hv7131R_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001258 break;
1259 case SENSOR_MI0360:
1260 mi0360_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001261 break;
1262 case SENSOR_MO4000:
1263 mo4000_InitSensor(gspca_dev);
1264 if (mode) {
1265/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1266 reg1 = 0x06; /* clk 24Mz */
1267 } else {
1268 reg17 = 0x22; /* 640 MCKSIZE */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001269/* reg1 = 0x06; * 640 clk 24Mz (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001270 }
1271 break;
1272 case SENSOR_OV7648:
Jean-Francois Moine60017612008-07-18 08:46:19 -03001273 ov7648_InitSensor(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001274 reg17 = 0xa2;
1275 reg1 = 0x44;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001276/* if (mode)
1277 ; * 320x2...
1278 else
1279 ; * 640x... */
1280 break;
1281 default:
1282/* case SENSOR_OV7660: */
1283 ov7660_InitSensor(gspca_dev);
1284 if (mode) {
1285/* reg17 = 0x21; * 320 */
1286/* reg1 = 0x44; */
Jean-Francois Moine60017612008-07-18 08:46:19 -03001287/* reg1 = 0x46; (done) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001288 } else {
1289 reg17 = 0xa2; /* 640 */
1290 reg1 = 0x40;
1291 }
1292 break;
1293 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001294 reg_w(gspca_dev, 0xc0, C0, 6);
Hans de Goede3647fea2008-07-15 05:36:30 -03001295 switch (sd->bridge) {
1296 case BRIDGE_SN9C120: /*jfm ?? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001297 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001298 break;
1299 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001300 reg_w(gspca_dev, 0xca, CA, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001301 break;
1302 }
Hans de Goede3647fea2008-07-15 05:36:30 -03001303 switch (sd->bridge) {
1304 case BRIDGE_SN9C120: /*jfm ?? */
1305 case BRIDGE_SN9C325:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001306 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001307 break;
1308 default:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001309 reg_w(gspca_dev, 0xce, CE, 4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001310 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1311 break;
1312 }
1313
1314 /* here change size mode 0 -> VGA; 1 -> CIF */
1315 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001316 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001317
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001318 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1319 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001320
1321 data = sn9c1xx[0x18] | (mode << 4);
Jean-Francois Moine60017612008-07-18 08:46:19 -03001322 reg_w1(gspca_dev, 0x18, data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001323
Jean-Francois Moine60017612008-07-18 08:46:19 -03001324 reg_w1(gspca_dev, 0x17, reg17);
1325 reg_w1(gspca_dev, 0x01, reg1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001326 setbrightness(gspca_dev);
1327 setcontrast(gspca_dev);
1328}
1329
1330static void sd_stopN(struct gspca_dev *gspca_dev)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001333 static const __u8 stophv7131[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001334 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001335 static const __u8 stopmi0360[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001336 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001337 __u8 data;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001338 const __u8 *sn9c1xx;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001339
1340 data = 0x0b;
1341 switch (sd->sensor) {
1342 case SENSOR_HV7131R:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001343 i2c_w8(gspca_dev, stophv7131);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 data = 0x2b;
1345 break;
1346 case SENSOR_MI0360:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001347 i2c_w8(gspca_dev, stopmi0360);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001348 data = 0x29;
1349 break;
1350 case SENSOR_MO4000:
1351 break;
1352 case SENSOR_OV7648:
1353 data = 0x29;
1354 break;
1355 default:
1356/* case SENSOR_OV7660: */
1357 break;
1358 }
1359 sn9c1xx = sn_tb[(int) sd->sensor];
Jean-Francois Moine60017612008-07-18 08:46:19 -03001360 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1361 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1362 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1363 reg_w1(gspca_dev, 0x01, data);
1364 reg_w1(gspca_dev, 0xf1, 0x01);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001365}
1366
1367static void sd_stop0(struct gspca_dev *gspca_dev)
1368{
1369}
1370
1371static void sd_close(struct gspca_dev *gspca_dev)
1372{
1373}
1374
1375static void setautogain(struct gspca_dev *gspca_dev)
1376{
1377 struct sd *sd = (struct sd *) gspca_dev;
1378 /* Thanks S., without your advice, autobright should not work :) */
1379 int delta;
1380 int expotimes = 0;
1381 __u8 luma_mean = 130;
1382 __u8 luma_delta = 20;
1383
1384 delta = sd->avg_lum;
1385 if (delta < luma_mean - luma_delta ||
1386 delta > luma_mean + luma_delta) {
1387 switch (sd->sensor) {
1388 case SENSOR_HV7131R:
1389 expotimes = sd->exposure >> 8;
1390 expotimes += (luma_mean - delta) >> 4;
1391 if (expotimes < 0)
1392 expotimes = 0;
1393 sd->exposure = setexposure(gspca_dev,
1394 (unsigned int) (expotimes << 8));
1395 break;
1396 case SENSOR_MO4000:
1397 case SENSOR_MI0360:
1398 expotimes = sd->exposure;
1399 expotimes += (luma_mean - delta) >> 6;
1400 if (expotimes < 0)
1401 expotimes = 0;
1402 sd->exposure = setexposure(gspca_dev,
1403 (unsigned int) expotimes);
1404 setcolors(gspca_dev);
1405 break;
1406 }
1407 }
1408}
1409
1410static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1411 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001412 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001413 int len) /* iso packet length */
1414{
1415 struct sd *sd = (struct sd *) gspca_dev;
1416 int sof, avg_lum;
1417
1418 sof = len - 64;
1419 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1420
1421 /* end of frame */
1422 gspca_frame_add(gspca_dev, LAST_PACKET,
1423 frame, data, sof + 2);
1424 if (sd->ag_cnt < 0)
1425 return;
1426 if (--sd->ag_cnt >= 0)
1427 return;
1428 sd->ag_cnt = AG_CNT_START;
1429/* w1 w2 w3 */
1430/* w4 w5 w6 */
1431/* w7 w8 */
1432/* w4 */
1433 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1434/* w6 */
1435 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1436/* w2 */
1437 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1438/* w8 */
1439 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1440/* w5 */
1441 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1442 avg_lum >>= 4;
1443 sd->avg_lum = avg_lum;
1444 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1445 setautogain(gspca_dev);
1446 return;
1447 }
1448 if (gspca_dev->last_packet_type == LAST_PACKET) {
1449
1450 /* put the JPEG 422 header */
1451 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1452 }
1453 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1454}
1455
1456static unsigned int getexposure(struct gspca_dev *gspca_dev)
1457{
1458 struct sd *sd = (struct sd *) gspca_dev;
1459 __u8 hexpo, mexpo, lexpo;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001460
1461 switch (sd->sensor) {
1462 case SENSOR_HV7131R:
1463 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001464 i2c_r5(gspca_dev, 0x25);
1465 return (gspca_dev->usb_buf[0] << 16)
1466 | (gspca_dev->usb_buf[1] << 8)
1467 | gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001468 case SENSOR_MI0360:
1469 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001470 i2c_r5(gspca_dev, 0x09);
1471 return (gspca_dev->usb_buf[0] << 8)
1472 | gspca_dev->usb_buf[1];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001473 case SENSOR_MO4000:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001474 i2c_r5(gspca_dev, 0x0e);
1475 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1476 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1477 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001478 PDEBUG(D_CONF, "exposure %d",
1479 (hexpo << 10) | (mexpo << 2) | lexpo);
1480 return (hexpo << 10) | (mexpo << 2) | lexpo;
1481 default:
1482/* case SENSOR_OV7660: */
1483 /* read sensor exposure */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001484 i2c_r5(gspca_dev, 0x04);
1485 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1486 lexpo = gspca_dev->usb_buf[0] & 0x02;
1487 i2c_r5(gspca_dev, 0x08);
1488 mexpo = gspca_dev->usb_buf[2];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001489 return (hexpo << 10) | (mexpo << 2) | lexpo;
1490 }
1491}
1492
1493static void getbrightness(struct gspca_dev *gspca_dev)
1494{
1495 struct sd *sd = (struct sd *) gspca_dev;
1496
1497 /* hardcoded registers seem not readable */
1498 switch (sd->sensor) {
1499 case SENSOR_HV7131R:
1500/* sd->brightness = 0x7fff; */
1501 sd->brightness = getexposure(gspca_dev) >> 4;
1502 break;
1503 case SENSOR_MI0360:
1504 sd->brightness = getexposure(gspca_dev) << 4;
1505 break;
1506 case SENSOR_MO4000:
1507/* sd->brightness = 0x1fff; */
1508 sd->brightness = getexposure(gspca_dev) << 4;
1509 break;
1510 }
1511}
1512
1513static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1514{
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 sd->brightness = val;
1518 if (gspca_dev->streaming)
1519 setbrightness(gspca_dev);
1520 return 0;
1521}
1522
1523static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1524{
1525 struct sd *sd = (struct sd *) gspca_dev;
1526
1527 getbrightness(gspca_dev);
1528 *val = sd->brightness;
1529 return 0;
1530}
1531
1532static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1533{
1534 struct sd *sd = (struct sd *) gspca_dev;
1535
1536 sd->contrast = val;
1537 if (gspca_dev->streaming)
1538 setcontrast(gspca_dev);
1539 return 0;
1540}
1541
1542static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1543{
1544 struct sd *sd = (struct sd *) gspca_dev;
1545
1546 *val = sd->contrast;
1547 return 0;
1548}
1549
1550static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1551{
1552 struct sd *sd = (struct sd *) gspca_dev;
1553
1554 sd->colors = val;
1555 if (gspca_dev->streaming)
1556 setcolors(gspca_dev);
1557 return 0;
1558}
1559
1560static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 *val = sd->colors;
1565 return 0;
1566}
1567
1568static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1569{
1570 struct sd *sd = (struct sd *) gspca_dev;
1571
1572 sd->autogain = val;
1573 if (val)
1574 sd->ag_cnt = AG_CNT_START;
1575 else
1576 sd->ag_cnt = -1;
1577 return 0;
1578}
1579
1580static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1581{
1582 struct sd *sd = (struct sd *) gspca_dev;
1583
1584 *val = sd->autogain;
1585 return 0;
1586}
1587
1588/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001589static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001590 .name = MODULE_NAME,
1591 .ctrls = sd_ctrls,
1592 .nctrls = ARRAY_SIZE(sd_ctrls),
1593 .config = sd_config,
1594 .open = sd_open,
1595 .start = sd_start,
1596 .stopN = sd_stopN,
1597 .stop0 = sd_stop0,
1598 .close = sd_close,
1599 .pkt_scan = sd_pkt_scan,
1600};
1601
1602/* -- module initialisation -- */
1603#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001604static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001605#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001606 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1607 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1608 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1609 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1610 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001611#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001612 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1613 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1614 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1615 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1616 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1617 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1618 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1619 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1620 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001621#ifndef CONFIG_USB_SN9C102
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001622 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1623 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1624 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1625 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
Jean-Francois Moinec41492c2008-07-07 08:31:16 -03001626#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001627 {}
1628};
1629MODULE_DEVICE_TABLE(usb, device_table);
1630
1631/* -- device connect -- */
1632static int sd_probe(struct usb_interface *intf,
1633 const struct usb_device_id *id)
1634{
1635 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1636 THIS_MODULE);
1637}
1638
1639static struct usb_driver sd_driver = {
1640 .name = MODULE_NAME,
1641 .id_table = device_table,
1642 .probe = sd_probe,
1643 .disconnect = gspca_disconnect,
1644};
1645
1646/* -- module insert / remove -- */
1647static int __init sd_mod_init(void)
1648{
1649 if (usb_register(&sd_driver) < 0)
1650 return -1;
1651 info("v%s registered", version);
1652 return 0;
1653}
1654static void __exit sd_mod_exit(void)
1655{
1656 usb_deregister(&sd_driver);
1657 info("deregistered");
1658}
1659
1660module_init(sd_mod_init);
1661module_exit(sd_mod_exit);