blob: b561f7c4f066632571d8b12265b1ed776dc49231 [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
53#define SENSOR_OTHER 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,
191 .default_value = 1,
192 },
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 Moine739570b2008-07-14 09:38:29 -0300368/* read 1 byte */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300369static int reg_r(struct gspca_dev *gspca_dev,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300370 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300371{
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300372 usb_control_msg(gspca_dev->dev,
373 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300374 0, /* request */
375 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 0, /* value */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300377 index,
378 gspca_dev->usb_buf, 1, 500);
379 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300380}
381
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300382static void reg_w(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300383 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300384{
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300385 usb_control_msg(gspca_dev->dev,
386 usb_sndctrlpipe(gspca_dev->dev, 0),
387 0,
388 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
389 0, index,
390 NULL, 0, 500);
391}
392
393static void i2c_w(struct gspca_dev *gspca_dev,
394 const __u8 *buffer, __u16 len)
395{
Jean-Francois Moine8295d992008-09-03 17:12:19 -0300396 if (len <= USB_BUF_SZ) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300397 memcpy(gspca_dev->usb_buf, buffer, len);
398 usb_control_msg(gspca_dev->dev,
399 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300400 0,
401 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300402 0x01, 0,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300403 gspca_dev->usb_buf, len, 500);
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300404 } else {
405 __u8 *tmpbuf;
406
407 tmpbuf = kmalloc(len, GFP_KERNEL);
408 memcpy(tmpbuf, buffer, len);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300411 0,
412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300413 0x01, 0,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300414 tmpbuf, len, 500);
415 kfree(tmpbuf);
416 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300417}
418
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300419static void other_sensor_init(struct gspca_dev *gspca_dev)
420{
421 int i;
422 const __u8 *p;
423 __u8 byte;
424 __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
425 static const __u8 sensor_init[] = {
426 0xdf, 0x6d,
427 0xdd, 0x18,
428 0x5a, 0xe0,
429 0x5c, 0x07,
430 0x5d, 0xb0,
431 0x5e, 0x1e,
432 0x60, 0x71,
433 0xef, 0x00,
434 0xe9, 0x00,
435 0xea, 0x00,
436 0x90, 0x24,
437 0x91, 0xb2,
438 0x82, 0x32,
439 0xfd, 0x00,
440 0xfd, 0x01,
441 0xfd, 0x41,
442 0x00 /* table end */
443 };
444
445 p = sensor_init;
446 while (*p != 0) {
447 val[1] = *p++;
448 val[3] = *p++;
449 if (*p == 0)
450 reg_w(gspca_dev, 0x3c80);
451 i2c_w(gspca_dev, val, sizeof val);
452 i = 4;
453 while (--i >= 0) {
454 msleep(15);
455 byte = reg_r(gspca_dev, 0x60);
456 if (!(byte & 0x01))
457 break;
458 }
459 }
460 reg_w(gspca_dev, 0x3c80);
461}
462
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463/* this function is called at probe time */
464static int sd_config(struct gspca_dev *gspca_dev,
465 const struct usb_device_id *id)
466{
467 struct sd *sd = (struct sd *) gspca_dev;
468 struct cam *cam;
469
470 cam = &gspca_dev->cam;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300471 cam->epaddr = 0x01;
472
473 cam->cam_mode = vga_mode_t16;
474 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
475
476 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
477 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
478 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300479 sd->gamma = GAMMA_DEF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300480 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
481 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
482 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
483 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
484 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
485 return 0;
486}
487
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300488static void setgamma(struct gspca_dev *gspca_dev)
489{
490 struct sd *sd = (struct sd *) gspca_dev;
491
492 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
493 i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
494}
495
496/* this function is called at probe and resume time */
497static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300498{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300499 /* some of this registers are not really neded, because
500 * they are overriden by setbrigthness, setcontrast, etc,
501 * but wont hurt anyway, and can help someone with similar webcam
502 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300503 struct sd *sd = (struct sd *) gspca_dev;
504 int i;
505 __u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300507 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300508 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
509 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300510 static const __u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300512 static const __u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300513 {0x08, 0x00};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300514 static const __u8 nset[] =
515 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
516 static const __u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300518 static const __u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300519 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
520 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
521 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
522 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
523 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
524 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
525 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
526 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
527 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300528 static const __u8 nset4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
530 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
531 0xe8, 0xe0
532 };
533 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300534 static const __u8 nset2[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
536 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
537 0xd8, 0xc8, 0xd9, 0xfc
538 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300539 static const __u8 missing[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300540 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300541 static const __u8 nset3[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300542 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
543 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
544 0xcf, 0xe0
545 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300546 static const __u8 nset5[] =
547 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300548 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300549 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300550 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300552 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300553 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300554 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
556
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300557 byte = reg_r(gspca_dev, 0x06);
558 test_byte = reg_r(gspca_dev, 0x07);
559 if (byte == 0x08 && test_byte == 0x07) {
560 PDEBUG(D_CONF, "other sensor");
561 sd->sensor = SENSOR_OTHER;
562 } else {
563 PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte);
564 sd->sensor = SENSOR_TAS5130A;
565 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300567 i2c_w(gspca_dev, n1, sizeof n1);
568 test_byte = 0;
569 i = 5;
570 while (--i >= 0) {
571 i2c_w(gspca_dev, nset, sizeof nset);
572 msleep(5);
573 test_byte = reg_r(gspca_dev, 0x0063);
574 msleep(100);
575 if (test_byte == 0x17)
576 break; /* OK */
577 }
578 if (i < 0) {
579 err("Bad sensor reset %02x", test_byte);
580/* return -EIO; */
581/*fixme: test - continue */
582 }
583 i2c_w(gspca_dev, n2, sizeof n2);
584
585 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300586 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300587 test_byte = reg_r(gspca_dev, read_indexs[i]);
588 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300589 test_byte);
590 i++;
591 }
592
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300593 i2c_w(gspca_dev, n3, sizeof n3);
594 i2c_w(gspca_dev, n4, sizeof n4);
595 reg_r(gspca_dev, 0x0080);
596 reg_w(gspca_dev, 0x2c80);
597 i2c_w(gspca_dev, nset2, sizeof nset2);
598 i2c_w(gspca_dev, nset3, sizeof nset3);
599 i2c_w(gspca_dev, nset4, sizeof nset4);
600 reg_w(gspca_dev, 0x3880);
601 reg_w(gspca_dev, 0x3880);
602 reg_w(gspca_dev, 0x338e);
603 i2c_w(gspca_dev, nset5, sizeof nset5);
604 reg_w(gspca_dev, 0x00a9);
605 setgamma(gspca_dev);
606 reg_w(gspca_dev, 0x86bb);
607 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300608
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300609 i2c_w(gspca_dev, missing, sizeof missing);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300610
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300611 reg_w(gspca_dev, 0x2087);
612 reg_w(gspca_dev, 0x2088);
613 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300615 i2c_w(gspca_dev, nset7, sizeof nset7);
616 i2c_w(gspca_dev, nset10, sizeof nset10);
617 i2c_w(gspca_dev, nset8, sizeof nset8);
618 i2c_w(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300619
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300620 reg_w(gspca_dev, 0x2880);
621 i2c_w(gspca_dev, nset2, sizeof nset2);
622 i2c_w(gspca_dev, nset3, sizeof nset3);
623 i2c_w(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624
625 return 0;
626}
627
628static void setbrightness(struct gspca_dev *gspca_dev)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631 unsigned int brightness;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300632 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300634 brightness = sd->brightness;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300635 if (brightness < 7) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300636 set6[3] = 0x70 - brightness * 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637 } else {
638 set6[1] = 0x24;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300639 set6[3] = 0x00 + ((brightness - 7) * 0x10);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300640 }
641
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300642 i2c_w(gspca_dev, set6, sizeof set6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643}
644
645static void setflip(struct gspca_dev *gspca_dev)
646{
647 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300648 __u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300649 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300651 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 flipcmd[3] = 0x01;
653
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300654 i2c_w(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300655}
656
657static void seteffect(struct gspca_dev *gspca_dev)
658{
659 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300661 i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300662 if (sd->effect == 1 || sd->effect == 5) {
663 PDEBUG(D_CONF,
664 "This effect have been disabled for webcam \"safety\"");
665 return;
666 }
667
668 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300669 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300671 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672}
673
674static void setwhitebalance(struct gspca_dev *gspca_dev)
675{
676 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300677
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300678 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300679 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
680
681 if (sd->whitebalance == 1)
682 white_balance[7] = 0x3c;
683
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300684 i2c_w(gspca_dev, white_balance, sizeof white_balance);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300685}
686
687static void setlightfreq(struct gspca_dev *gspca_dev)
688{
689 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
691
692 if (sd->freq == 2) /* 60hz */
693 freq[1] = 0x00;
694
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300695 i2c_w(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696}
697
698static void setcontrast(struct gspca_dev *gspca_dev)
699{
700 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701 unsigned int contrast = sd->contrast;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300702 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703
704 if (contrast < 7)
705 reg_to_write = 0x8ea9 - (0x200 * contrast);
706 else
707 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
708
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300709 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300710}
711
712static void setcolors(struct gspca_dev *gspca_dev)
713{
714 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300715 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716
717 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300718 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719}
720
721static void setsharpness(struct gspca_dev *gspca_dev)
722{
723 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300724 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300725
726 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
727
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300728 reg_w(gspca_dev, reg_to_write);
729}
730
731static int sd_start(struct gspca_dev *gspca_dev)
732{
733 struct sd *sd = (struct sd *) gspca_dev;
734 int i, mode;
735 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
736 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
737 static const __u8 t3[] =
738 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
739 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
740 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
741
742 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
743 switch (mode) {
744 case 1: /* 352x288 */
745 t2[1] = 0x40;
746 break;
747 case 2: /* 320x240 */
748 t2[1] = 0x10;
749 break;
750 case 3: /* 176x144 */
751 t2[1] = 0x50;
752 break;
753 case 4: /* 160x120 */
754 t2[1] = 0x20;
755 break;
756 default: /* 640x480 (0x00) */
757 break;
758 }
759
760 if (sd->sensor == SENSOR_TAS5130A) {
761 i = 0;
762 while (tas5130a_sensor_init[i][0] != 0) {
763 i2c_w(gspca_dev, tas5130a_sensor_init[i],
764 sizeof tas5130a_sensor_init[0]);
765 i++;
766 }
767 reg_w(gspca_dev, 0x3c80);
768 /* just in case and to keep sync with logs (for mine) */
769 i2c_w(gspca_dev, tas5130a_sensor_init[3],
770 sizeof tas5130a_sensor_init[0]);
771 reg_w(gspca_dev, 0x3c80);
772 } else {
773 other_sensor_init(gspca_dev);
774 }
775 /* just in case and to keep sync with logs (for mine) */
776 i2c_w(gspca_dev, t1, sizeof t1);
777 i2c_w(gspca_dev, t2, sizeof t2);
778 reg_r(gspca_dev, 0x0012);
779 i2c_w(gspca_dev, t3, sizeof t3);
780 reg_w(gspca_dev, 0x0013);
781 i2c_w(gspca_dev, t4, sizeof t4);
782 /* restart on each start, just in case, sometimes regs goes wrong
783 * when using controls from app */
784 setbrightness(gspca_dev);
785 setcontrast(gspca_dev);
786 setcolors(gspca_dev);
787 return 0;
788}
789
790static void sd_pkt_scan(struct gspca_dev *gspca_dev,
791 struct gspca_frame *frame, /* target */
792 __u8 *data, /* isoc packet */
793 int len) /* iso packet length */
794{
795 static __u8 ffd9[] = { 0xff, 0xd9 };
796
797 if (data[0] == 0x5a) {
798 /* Control Packet, after this came the header again,
799 * but extra bytes came in the packet before this,
800 * sometimes an EOF arrives, sometimes not... */
801 return;
802 }
803 data += 2;
804 len -= 2;
805 if (data[0] == 0xff && data[1] == 0xd8) {
806 /* extra bytes....., could be processed too but would be
807 * a waste of time, right now leave the application and
808 * libjpeg do it for ourserlves.. */
809 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
810 ffd9, 2);
811 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
812 return;
813 }
814
815 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
816 /* Just in case, i have seen packets with the marker,
817 * other's do not include it... */
818 len -= 2;
819 }
820 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300821}
822
823static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826
827 sd->brightness = val;
828 if (gspca_dev->streaming)
829 setbrightness(gspca_dev);
830 return 0;
831}
832
833static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
834{
835 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300836
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 *val = sd->brightness;
838 return *val;
839}
840
841static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
842{
843 struct sd *sd = (struct sd *) gspca_dev;
844
845 sd->whitebalance = val;
846 if (gspca_dev->streaming)
847 setwhitebalance(gspca_dev);
848 return 0;
849}
850
851static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
852{
853 struct sd *sd = (struct sd *) gspca_dev;
854
855 *val = sd->whitebalance;
856 return *val;
857}
858
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300859static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
860{
861 struct sd *sd = (struct sd *) gspca_dev;
862
863 sd->mirror = val;
864 if (gspca_dev->streaming)
865 setflip(gspca_dev);
866 return 0;
867}
868
869static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
870{
871 struct sd *sd = (struct sd *) gspca_dev;
872
873 *val = sd->mirror;
874 return *val;
875}
876
877static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
878{
879 struct sd *sd = (struct sd *) gspca_dev;
880
881 sd->effect = val;
882 if (gspca_dev->streaming)
883 seteffect(gspca_dev);
884 return 0;
885}
886
887static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
888{
889 struct sd *sd = (struct sd *) gspca_dev;
890
891 *val = sd->effect;
892 return *val;
893}
894
895static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 sd->contrast = val;
900 if (gspca_dev->streaming)
901 setcontrast(gspca_dev);
902 return 0;
903}
904
905static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 *val = sd->contrast;
910 return *val;
911}
912
913static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916
917 sd->colors = val;
918 if (gspca_dev->streaming)
919 setcolors(gspca_dev);
920 return 0;
921}
922
923static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926
927 *val = sd->colors;
928 return 0;
929}
930
931static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
934
935 sd->gamma = val;
936 if (gspca_dev->streaming)
937 setgamma(gspca_dev);
938 return 0;
939}
940
941static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300944
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300945 *val = sd->gamma;
946 return 0;
947}
948
949static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
952
953 sd->freq = val;
954 if (gspca_dev->streaming)
955 setlightfreq(gspca_dev);
956 return 0;
957}
958
959static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 *val = sd->freq;
964 return 0;
965}
966
967static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 sd->sharpness = val;
972 if (gspca_dev->streaming)
973 setsharpness(gspca_dev);
974 return 0;
975}
976
977static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->sharpness;
982 return 0;
983}
984
985/* Low Light set here......*/
986static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
987{
988 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300989
990 sd->autogain = val;
991 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300992 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300993 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300994 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300995 return 0;
996}
997
998static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
999{
1000 struct sd *sd = (struct sd *) gspca_dev;
1001
1002 *val = sd->autogain;
1003 return 0;
1004}
1005
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001006static int sd_querymenu(struct gspca_dev *gspca_dev,
1007 struct v4l2_querymenu *menu)
1008{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 switch (menu->id) {
1010 case V4L2_CID_POWER_LINE_FREQUENCY:
1011 switch (menu->index) {
1012 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001013 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014 return 0;
1015 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001016 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001017 return 0;
1018 }
1019 break;
1020 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001021 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1022 strncpy((char *) menu->name,
1023 effects_control[menu->index], 32);
1024 return 0;
1025 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026 break;
1027 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001028 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001029}
1030
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001032static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001033 .name = MODULE_NAME,
1034 .ctrls = sd_ctrls,
1035 .nctrls = ARRAY_SIZE(sd_ctrls),
1036 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001037 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038 .start = sd_start,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001039 .pkt_scan = sd_pkt_scan,
1040 .querymenu = sd_querymenu,
1041};
1042
1043/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001044static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001045 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001046 {}
1047};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001048MODULE_DEVICE_TABLE(usb, device_table);
1049
1050/* -- device connect -- */
1051static int sd_probe(struct usb_interface *intf,
1052 const struct usb_device_id *id)
1053{
1054 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1055 THIS_MODULE);
1056}
1057
1058static struct usb_driver sd_driver = {
1059 .name = MODULE_NAME,
1060 .id_table = device_table,
1061 .probe = sd_probe,
1062 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001063#ifdef CONFIG_PM
1064 .suspend = gspca_suspend,
1065 .resume = gspca_resume,
1066#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001067};
1068
1069/* -- module insert / remove -- */
1070static int __init sd_mod_init(void)
1071{
1072 if (usb_register(&sd_driver) < 0)
1073 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001074 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001075 return 0;
1076}
1077static void __exit sd_mod_exit(void)
1078{
1079 usb_deregister(&sd_driver);
1080 PDEBUG(D_PROBE, "deregistered");
1081}
1082
1083module_init(sd_mod_init);
1084module_exit(sd_mod_exit);