blob: 3ffbf37e946d1361ad5486e53a5038ecb92372e7 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030017 *
18 *Notes: * t613 + tas5130A
19 * * Focus to light do not balance well as in win.
20 * Quality in win is not good, but its kinda better.
21 * * Fix some "extraneous bytes", most of apps will show the image anyway
22 * * Gamma table, is there, but its really doing something?
23 * * 7~8 Fps, its ok, max on win its 10.
24 * Costantino Leandro
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030025 */
26
27#define MODULE_NAME "t613"
Jean-Francois Moine10b0e962008-07-22 05:35:10 -030028
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029#include "gspca.h"
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030030
Jean-Francois Moinef9b4a372008-09-03 16:48:14 -030031#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030032
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
40 unsigned char brightness;
41 unsigned char contrast;
42 unsigned char colors;
43 unsigned char autogain;
44 unsigned char gamma;
45 unsigned char sharpness;
46 unsigned char freq;
47 unsigned char whitebalance;
48 unsigned char mirror;
49 unsigned char effect;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030050
51 __u8 sensor;
52#define SENSOR_TAS5130A 0
Jean-Francois Moine236088d2008-10-17 04:53:02 -030053#define SENSOR_OM6802 1
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030054};
55
56/* V4L2 controls supported by the driver */
57static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80static struct ctrl sd_ctrls[] = {
81#define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030088 .maximum = 14,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030089 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -030090 .default_value = 8,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030091 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95#define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109#define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300123#define GAMMA_MAX 16
124#define GAMMA_DEF 10
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300125 {
126 {
127 .id = V4L2_CID_GAMMA, /* (gamma on win) */
128 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300129 .name = "Gamma",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300131 .maximum = GAMMA_MAX - 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300132 .step = 1,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300133 .default_value = GAMMA_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300134 },
135 .set = sd_setgamma,
136 .get = sd_getgamma,
137 },
138#define SD_AUTOGAIN 4
139 {
140 {
141 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
142 * some apps dont bring up the
143 * backligth_compensation control) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Low Light",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149 .default_value = 0x01,
150 },
151 .set = sd_setlowlight,
152 .get = sd_getlowlight,
153 },
154#define SD_MIRROR 5
155 {
156 {
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
163 .default_value = 0,
164 },
165 .set = sd_setflip,
166 .get = sd_getflip
167 },
168#define SD_LIGHTFREQ 6
169 {
170 {
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
175 .maximum = 2,
176 .step = 1,
177 .default_value = 1,
178 },
179 .set = sd_setfreq,
180 .get = sd_getfreq},
181
182#define SD_WHITE_BALANCE 7
183 {
184 {
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
188 .minimum = 0,
189 .maximum = 1,
190 .step = 1,
Jean-Francois Moinecbc51c62008-10-17 05:07:45 -0300191 .default_value = 0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192 },
193 .set = sd_setwhitebalance,
194 .get = sd_getwhitebalance
195 },
196#define SD_SHARPNESS 8 /* (aka definition on win) */
197 {
198 {
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Sharpness",
202 .minimum = 0,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300203 .maximum = 15,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300204 .step = 1,
205 .default_value = 0x06,
206 },
207 .set = sd_setsharpness,
208 .get = sd_getsharpness,
209 },
210#define SD_EFFECTS 9
211 {
212 {
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
216 .minimum = 0,
217 .maximum = 4,
218 .step = 1,
219 .default_value = 0,
220 },
221 .set = sd_seteffect,
222 .get = sd_geteffect
223 },
224};
225
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300226static char *effects_control[] = {
227 "Normal",
228 "Emboss", /* disabled */
229 "Monochrome",
230 "Sepia",
231 "Sketch",
232 "Sun Effect", /* disabled */
233 "Negative",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300234};
235
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300236static struct v4l2_pix_format vga_mode_t16[] = {
237 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
238 .bytesperline = 160,
Jean-Francois Moine5d052942008-09-03 16:48:09 -0300239 .sizeimage = 160 * 120 * 4 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300240 .colorspace = V4L2_COLORSPACE_JPEG,
241 .priv = 4},
242 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
243 .bytesperline = 176,
244 .sizeimage = 176 * 144 * 3 / 8 + 590,
245 .colorspace = V4L2_COLORSPACE_JPEG,
246 .priv = 3},
247 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
248 .bytesperline = 320,
249 .sizeimage = 320 * 240 * 3 / 8 + 590,
250 .colorspace = V4L2_COLORSPACE_JPEG,
251 .priv = 2},
252 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .bytesperline = 352,
254 .sizeimage = 352 * 288 * 3 / 8 + 590,
255 .colorspace = V4L2_COLORSPACE_JPEG,
256 .priv = 1},
257 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
258 .bytesperline = 640,
259 .sizeimage = 640 * 480 * 3 / 8 + 590,
260 .colorspace = V4L2_COLORSPACE_JPEG,
261 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300262};
263
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300264#define MAX_EFFECTS 7
265/* easily done by soft, this table could be removed,
266 * i keep it here just in case */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300267static const __u8 effects_table[MAX_EFFECTS][6] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
269 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
270 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
271 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
272 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
273 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
274 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
275};
276
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300277static const __u8 gamma_table[GAMMA_MAX][34] = {
278 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300279 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
280 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
281 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
282 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300283 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */
284 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
285 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
286 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300287 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300288 {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */
289 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
290 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
291 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300292 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300293 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */
294 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
295 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
296 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300297 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300298 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300299 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300300 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
301 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300302 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300303 {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300304 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300305 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
306 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300307 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300308 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300309 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
310 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
311 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
312 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300313 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */
314 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
315 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
316 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300317 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300318 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */
319 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
320 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
321 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300322 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300323 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300324 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
325 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
326 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
327 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300328 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */
329 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
330 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
331 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300332 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300333 {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */
334 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
335 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
336 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300337 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300338 {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */
339 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
340 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
341 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300342 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300343 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */
344 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
345 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
346 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300347 0xa0, 0xff},
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300348 {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */
349 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
350 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
351 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
352 0xa0, 0xff},
353 {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */
354 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
355 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
356 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
357 0xa0, 0xff}
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300358};
359
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300360static const __u8 tas5130a_sensor_init[][8] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
362 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
363 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
364 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
365 {},
366};
367
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300368static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
369
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300370/* read 1 byte */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300371static int reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300372 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300373{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300374 usb_control_msg(gspca_dev->dev,
375 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376 0, /* request */
377 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
378 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300379 index,
380 gspca_dev->usb_buf, 1, 500);
381 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382}
383
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300384static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300385 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300387 usb_control_msg(gspca_dev->dev,
388 usb_sndctrlpipe(gspca_dev->dev, 0),
389 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300390 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300391 0, index,
392 NULL, 0, 500);
393}
394
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300395static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300396 const __u8 *buffer, __u16 len)
397{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300398 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300399 memcpy(gspca_dev->usb_buf, buffer, len);
400 usb_control_msg(gspca_dev->dev,
401 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300402 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300403 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300404 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300405 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300406 } else {
407 __u8 *tmpbuf;
408
409 tmpbuf = kmalloc(len, GFP_KERNEL);
410 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300411 usb_control_msg(gspca_dev->dev,
412 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300413 0,
Jean-Francois Moine0bc99b52008-10-17 04:45:27 -0300414 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300415 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300416 tmpbuf, len, 500);
417 kfree(tmpbuf);
418 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300419}
420
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300421/* Reported as OM6802*/
422static void om6802_sensor_init(struct gspca_dev *gspca_dev)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300423{
424 int i;
425 const __u8 *p;
426 __u8 byte;
427 __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
428 static const __u8 sensor_init[] = {
429 0xdf, 0x6d,
430 0xdd, 0x18,
431 0x5a, 0xe0,
432 0x5c, 0x07,
433 0x5d, 0xb0,
434 0x5e, 0x1e,
435 0x60, 0x71,
436 0xef, 0x00,
437 0xe9, 0x00,
438 0xea, 0x00,
439 0x90, 0x24,
440 0x91, 0xb2,
441 0x82, 0x32,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300442 0xfd, 0x41,
443 0x00 /* table end */
444 };
445
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300446 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
447 msleep(5);
448 i = 4;
449 while (--i < 0) {
450 byte = reg_r(gspca_dev, 0x0060);
451 if (!(byte & 0x01))
452 break;
453 msleep(100);
454 }
455 byte = reg_r(gspca_dev, 0x0063);
456 if (byte != 0x17) {
457 err("Bad sensor reset %02x", byte);
458 /* continue? */
459 }
460
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300461 p = sensor_init;
462 while (*p != 0) {
463 val[1] = *p++;
464 val[3] = *p++;
465 if (*p == 0)
466 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300467 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300468 i = 4;
469 while (--i >= 0) {
470 msleep(15);
471 byte = reg_r(gspca_dev, 0x60);
472 if (!(byte & 0x01))
473 break;
474 }
475 }
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300476 msleep(15);
477 reg_w(gspca_dev, 0x3c80);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300478}
479
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480/* this function is called at probe time */
481static int sd_config(struct gspca_dev *gspca_dev,
482 const struct usb_device_id *id)
483{
484 struct sd *sd = (struct sd *) gspca_dev;
485 struct cam *cam;
486
487 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300488 cam->epaddr = 0x01;
489
490 cam->cam_mode = vga_mode_t16;
491 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
492
493 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
494 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
495 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300496 sd->gamma = GAMMA_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300497 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
498 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
499 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
500 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
501 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
502 return 0;
503}
504
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300505static void setbrightness(struct gspca_dev *gspca_dev)
506{
507 struct sd *sd = (struct sd *) gspca_dev;
508 unsigned int brightness;
509 __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
510
511 brightness = sd->brightness;
512 if (brightness < 7) {
513 set6[1] = 0x26;
514 set6[3] = 0x70 - brightness * 0x10;
515 } else {
516 set6[3] = 0x00 + ((brightness - 7) * 0x10);
517 }
518
519 reg_w_buf(gspca_dev, set6, sizeof set6);
520}
521
522static void setcontrast(struct gspca_dev *gspca_dev)
523{
524 struct sd *sd = (struct sd *) gspca_dev;
525 unsigned int contrast = sd->contrast;
526 __u16 reg_to_write;
527
528 if (contrast < 7)
529 reg_to_write = 0x8ea9 - contrast * 0x200;
530 else
531 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
532
533 reg_w(gspca_dev, reg_to_write);
534}
535
536static void setcolors(struct gspca_dev *gspca_dev)
537{
538 struct sd *sd = (struct sd *) gspca_dev;
539 __u16 reg_to_write;
540
541 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
542 reg_w(gspca_dev, reg_to_write);
543}
544
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300545static void setgamma(struct gspca_dev *gspca_dev)
546{
547 struct sd *sd = (struct sd *) gspca_dev;
548
549 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300550 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300551}
552
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300553static void setwhitebalance(struct gspca_dev *gspca_dev)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556
557 __u8 white_balance[8] =
558 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
559
560 if (sd->whitebalance)
561 white_balance[7] = 0x3c;
562
563 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
564}
565
566static void setsharpness(struct gspca_dev *gspca_dev)
567{
568 struct sd *sd = (struct sd *) gspca_dev;
569 __u16 reg_to_write;
570
571 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
572
573 reg_w(gspca_dev, reg_to_write);
574}
575
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300576/* this function is called at probe and resume time */
577static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300579 /* some of this registers are not really neded, because
580 * they are overriden by setbrigthness, setcontrast, etc,
581 * but wont hurt anyway, and can help someone with similar webcam
582 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300583 struct sd *sd = (struct sd *) gspca_dev;
584 int i;
585 __u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300587 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300588 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
589 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300590 static const __u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300591 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300592 static const __u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300593 {0x08, 0x00};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300594 static const __u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300595 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300596 static const __u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300597 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
598 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
599 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
600 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
601 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
602 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
603 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
604 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
605 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300606 static const __u8 nset4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300607 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
608 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
609 0xe8, 0xe0
610 };
611 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300612 static const __u8 nset2[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300613 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
614 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
615 0xd8, 0xc8, 0xd9, 0xfc
616 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300617 static const __u8 nset3[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300618 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
619 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
620 0xcf, 0xe0
621 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300622 static const __u8 nset5[] =
623 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300624 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300626 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300628 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300629 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300630 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
632
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300633 byte = reg_r(gspca_dev, 0x06);
634 test_byte = reg_r(gspca_dev, 0x07);
635 if (byte == 0x08 && test_byte == 0x07) {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300636 PDEBUG(D_CONF, "sensor om6802");
637 sd->sensor = SENSOR_OM6802;
638 } else if (byte == 0x08 && test_byte == 0x01) {
639 PDEBUG(D_CONF, "sensor tas5130a");
640 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300641 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300642 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300643 sd->sensor = SENSOR_TAS5130A;
644 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300645
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300646 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300647 test_byte = 0;
648 i = 5;
649 while (--i >= 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300650 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300651 test_byte = reg_r(gspca_dev, 0x0063);
652 msleep(100);
653 if (test_byte == 0x17)
654 break; /* OK */
655 }
656 if (i < 0) {
657 err("Bad sensor reset %02x", test_byte);
658/* return -EIO; */
659/*fixme: test - continue */
660 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300661 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300662
663 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300664 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300665 test_byte = reg_r(gspca_dev, read_indexs[i]);
666 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667 test_byte);
668 i++;
669 }
670
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300671 reg_w_buf(gspca_dev, n3, sizeof n3);
672 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300673 reg_r(gspca_dev, 0x0080);
674 reg_w(gspca_dev, 0x2c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300675 reg_w_buf(gspca_dev, nset2, sizeof nset2);
676 reg_w_buf(gspca_dev, nset3, sizeof nset3);
677 reg_w_buf(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300678 reg_w(gspca_dev, 0x3880);
679 reg_w(gspca_dev, 0x3880);
680 reg_w(gspca_dev, 0x338e);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300681nset5 - missing
682 setbrightness(gspca_dev);
683 setcontrast(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300684 setgamma(gspca_dev);
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300685 setcolors(gspca_dev);
686 setsharpness(gspca_dev);
687 setwhitebalance(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300688
Jean-Francois Moine35480b62008-10-17 05:19:46 -0300689 reg_w(gspca_dev, 0x2087); /* tied to white balance? */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300690 reg_w(gspca_dev, 0x2088);
691 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300693 reg_w_buf(gspca_dev, nset7, sizeof nset7);
694 reg_w_buf(gspca_dev, nset10, sizeof nset10);
695 reg_w_buf(gspca_dev, nset8, sizeof nset8);
696 reg_w_buf(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300698 reg_w(gspca_dev, 0x2880);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300699 reg_w_buf(gspca_dev, nset2, sizeof nset2);
700 reg_w_buf(gspca_dev, nset3, sizeof nset3);
701 reg_w_buf(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702
703 return 0;
704}
705
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706static void setflip(struct gspca_dev *gspca_dev)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300709 __u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300710 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300712 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 flipcmd[3] = 0x01;
714
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300715 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716}
717
718static void seteffect(struct gspca_dev *gspca_dev)
719{
720 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300721
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300722 reg_w_buf(gspca_dev, effects_table[sd->effect],
723 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300724 if (sd->effect == 1 || sd->effect == 5) {
725 PDEBUG(D_CONF,
726 "This effect have been disabled for webcam \"safety\"");
727 return;
728 }
729
730 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300731 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300732 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300733 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734}
735
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736static void setlightfreq(struct gspca_dev *gspca_dev)
737{
738 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
740
741 if (sd->freq == 2) /* 60hz */
742 freq[1] = 0x00;
743
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300744 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745}
746
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300747static int sd_start(struct gspca_dev *gspca_dev)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750 int i, mode;
751 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
752 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
753 static const __u8 t3[] =
754 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
755 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
756 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
757
758 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
759 switch (mode) {
760 case 1: /* 352x288 */
761 t2[1] = 0x40;
762 break;
763 case 2: /* 320x240 */
764 t2[1] = 0x10;
765 break;
766 case 3: /* 176x144 */
767 t2[1] = 0x50;
768 break;
769 case 4: /* 160x120 */
770 t2[1] = 0x20;
771 break;
772 default: /* 640x480 (0x00) */
773 break;
774 }
775
776 if (sd->sensor == SENSOR_TAS5130A) {
777 i = 0;
778 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300779 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300780 sizeof tas5130a_sensor_init[0]);
781 i++;
782 }
783 reg_w(gspca_dev, 0x3c80);
784 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300785 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300786 sizeof tas5130a_sensor_init[0]);
787 reg_w(gspca_dev, 0x3c80);
788 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300789 om6802_sensor_init(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300790 }
791 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300792 reg_w_buf(gspca_dev, t1, sizeof t1);
793 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300794 reg_r(gspca_dev, 0x0012);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300795 reg_w_buf(gspca_dev, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300796 reg_w(gspca_dev, 0x0013);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300797 reg_w_buf(gspca_dev, t4, sizeof t4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300798 /* restart on each start, just in case, sometimes regs goes wrong
799 * when using controls from app */
800 setbrightness(gspca_dev);
801 setcontrast(gspca_dev);
802 setcolors(gspca_dev);
803 return 0;
804}
805
806static void sd_pkt_scan(struct gspca_dev *gspca_dev,
807 struct gspca_frame *frame, /* target */
808 __u8 *data, /* isoc packet */
809 int len) /* iso packet length */
810{
811 static __u8 ffd9[] = { 0xff, 0xd9 };
812
813 if (data[0] == 0x5a) {
814 /* Control Packet, after this came the header again,
815 * but extra bytes came in the packet before this,
816 * sometimes an EOF arrives, sometimes not... */
817 return;
818 }
819 data += 2;
820 len -= 2;
821 if (data[0] == 0xff && data[1] == 0xd8) {
822 /* extra bytes....., could be processed too but would be
823 * a waste of time, right now leave the application and
824 * libjpeg do it for ourserlves.. */
825 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
826 ffd9, 2);
827 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
828 return;
829 }
830
831 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
832 /* Just in case, i have seen packets with the marker,
833 * other's do not include it... */
834 len -= 2;
835 }
836 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837}
838
839static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
840{
841 struct sd *sd = (struct sd *) gspca_dev;
842
843 sd->brightness = val;
844 if (gspca_dev->streaming)
845 setbrightness(gspca_dev);
846 return 0;
847}
848
849static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
850{
851 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300852
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300853 *val = sd->brightness;
854 return *val;
855}
856
857static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
858{
859 struct sd *sd = (struct sd *) gspca_dev;
860
861 sd->whitebalance = val;
862 if (gspca_dev->streaming)
863 setwhitebalance(gspca_dev);
864 return 0;
865}
866
867static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
868{
869 struct sd *sd = (struct sd *) gspca_dev;
870
871 *val = sd->whitebalance;
872 return *val;
873}
874
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300875static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
876{
877 struct sd *sd = (struct sd *) gspca_dev;
878
879 sd->mirror = val;
880 if (gspca_dev->streaming)
881 setflip(gspca_dev);
882 return 0;
883}
884
885static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
886{
887 struct sd *sd = (struct sd *) gspca_dev;
888
889 *val = sd->mirror;
890 return *val;
891}
892
893static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
894{
895 struct sd *sd = (struct sd *) gspca_dev;
896
897 sd->effect = val;
898 if (gspca_dev->streaming)
899 seteffect(gspca_dev);
900 return 0;
901}
902
903static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906
907 *val = sd->effect;
908 return *val;
909}
910
911static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
912{
913 struct sd *sd = (struct sd *) gspca_dev;
914
915 sd->contrast = val;
916 if (gspca_dev->streaming)
917 setcontrast(gspca_dev);
918 return 0;
919}
920
921static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
922{
923 struct sd *sd = (struct sd *) gspca_dev;
924
925 *val = sd->contrast;
926 return *val;
927}
928
929static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
930{
931 struct sd *sd = (struct sd *) gspca_dev;
932
933 sd->colors = val;
934 if (gspca_dev->streaming)
935 setcolors(gspca_dev);
936 return 0;
937}
938
939static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
940{
941 struct sd *sd = (struct sd *) gspca_dev;
942
943 *val = sd->colors;
944 return 0;
945}
946
947static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
948{
949 struct sd *sd = (struct sd *) gspca_dev;
950
951 sd->gamma = val;
952 if (gspca_dev->streaming)
953 setgamma(gspca_dev);
954 return 0;
955}
956
957static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300960
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300961 *val = sd->gamma;
962 return 0;
963}
964
965static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
968
969 sd->freq = val;
970 if (gspca_dev->streaming)
971 setlightfreq(gspca_dev);
972 return 0;
973}
974
975static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 *val = sd->freq;
980 return 0;
981}
982
983static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
984{
985 struct sd *sd = (struct sd *) gspca_dev;
986
987 sd->sharpness = val;
988 if (gspca_dev->streaming)
989 setsharpness(gspca_dev);
990 return 0;
991}
992
993static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996
997 *val = sd->sharpness;
998 return 0;
999}
1000
1001/* Low Light set here......*/
1002static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1003{
1004 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001005
1006 sd->autogain = val;
1007 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001008 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001010 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 return 0;
1012}
1013
1014static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1015{
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 *val = sd->autogain;
1019 return 0;
1020}
1021
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022static int sd_querymenu(struct gspca_dev *gspca_dev,
1023 struct v4l2_querymenu *menu)
1024{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001025 switch (menu->id) {
1026 case V4L2_CID_POWER_LINE_FREQUENCY:
1027 switch (menu->index) {
1028 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001029 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001030 return 0;
1031 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001032 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001033 return 0;
1034 }
1035 break;
1036 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001037 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1038 strncpy((char *) menu->name,
1039 effects_control[menu->index], 32);
1040 return 0;
1041 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001042 break;
1043 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001044 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001045}
1046
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001048static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049 .name = MODULE_NAME,
1050 .ctrls = sd_ctrls,
1051 .nctrls = ARRAY_SIZE(sd_ctrls),
1052 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001053 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001054 .start = sd_start,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001055 .pkt_scan = sd_pkt_scan,
1056 .querymenu = sd_querymenu,
1057};
1058
1059/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001060static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001061 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001062 {}
1063};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064MODULE_DEVICE_TABLE(usb, device_table);
1065
1066/* -- device connect -- */
1067static int sd_probe(struct usb_interface *intf,
1068 const struct usb_device_id *id)
1069{
1070 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1071 THIS_MODULE);
1072}
1073
1074static struct usb_driver sd_driver = {
1075 .name = MODULE_NAME,
1076 .id_table = device_table,
1077 .probe = sd_probe,
1078 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001079#ifdef CONFIG_PM
1080 .suspend = gspca_suspend,
1081 .resume = gspca_resume,
1082#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001083};
1084
1085/* -- module insert / remove -- */
1086static int __init sd_mod_init(void)
1087{
1088 if (usb_register(&sd_driver) < 0)
1089 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001090 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001091 return 0;
1092}
1093static void __exit sd_mod_exit(void)
1094{
1095 usb_deregister(&sd_driver);
1096 PDEBUG(D_PROBE, "deregistered");
1097}
1098
1099module_init(sd_mod_init);
1100module_exit(sd_mod_exit);