blob: 9c8562f2390015aac4003b1dbac486844559067f [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
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300393static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300394 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);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300451 reg_w_buf(gspca_dev, val, sizeof val);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300452 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);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300493 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300494}
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 Moinef89be032008-10-17 04:42:29 -0300567 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300568 test_byte = 0;
569 i = 5;
570 while (--i >= 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300571 reg_w_buf(gspca_dev, nset, sizeof nset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300572 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 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300583 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300584
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 Moinef89be032008-10-17 04:42:29 -0300593 reg_w_buf(gspca_dev, n3, sizeof n3);
594 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300595 reg_r(gspca_dev, 0x0080);
596 reg_w(gspca_dev, 0x2c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300597 reg_w_buf(gspca_dev, nset2, sizeof nset2);
598 reg_w_buf(gspca_dev, nset3, sizeof nset3);
599 reg_w_buf(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300600 reg_w(gspca_dev, 0x3880);
601 reg_w(gspca_dev, 0x3880);
602 reg_w(gspca_dev, 0x338e);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300603 reg_w_buf(gspca_dev, nset5, sizeof nset5);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300604 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 Moinef89be032008-10-17 04:42:29 -0300609 reg_w_buf(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 Moinef89be032008-10-17 04:42:29 -0300615 reg_w_buf(gspca_dev, nset7, sizeof nset7);
616 reg_w_buf(gspca_dev, nset10, sizeof nset10);
617 reg_w_buf(gspca_dev, nset8, sizeof nset8);
618 reg_w_buf(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);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300621 reg_w_buf(gspca_dev, nset2, sizeof nset2);
622 reg_w_buf(gspca_dev, nset3, sizeof nset3);
623 reg_w_buf(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 Moinef89be032008-10-17 04:42:29 -0300642 reg_w_buf(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 Moinef89be032008-10-17 04:42:29 -0300654 reg_w_buf(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 Moinef89be032008-10-17 04:42:29 -0300661 reg_w_buf(gspca_dev, effects_table[sd->effect],
662 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300663 if (sd->effect == 1 || sd->effect == 5) {
664 PDEBUG(D_CONF,
665 "This effect have been disabled for webcam \"safety\"");
666 return;
667 }
668
669 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300670 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300671 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300672 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673}
674
675static void setwhitebalance(struct gspca_dev *gspca_dev)
676{
677 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300679 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
681
682 if (sd->whitebalance == 1)
683 white_balance[7] = 0x3c;
684
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300685 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686}
687
688static void setlightfreq(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300691 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
692
693 if (sd->freq == 2) /* 60hz */
694 freq[1] = 0x00;
695
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300696 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697}
698
699static void setcontrast(struct gspca_dev *gspca_dev)
700{
701 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300702 unsigned int contrast = sd->contrast;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300703 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704
705 if (contrast < 7)
706 reg_to_write = 0x8ea9 - (0x200 * contrast);
707 else
708 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
709
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300710 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300711}
712
713static void setcolors(struct gspca_dev *gspca_dev)
714{
715 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300716 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300717
718 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300719 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300720}
721
722static void setsharpness(struct gspca_dev *gspca_dev)
723{
724 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300725 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300726
727 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
728
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300729 reg_w(gspca_dev, reg_to_write);
730}
731
732static int sd_start(struct gspca_dev *gspca_dev)
733{
734 struct sd *sd = (struct sd *) gspca_dev;
735 int i, mode;
736 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
737 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
738 static const __u8 t3[] =
739 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
740 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
741 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
742
743 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
744 switch (mode) {
745 case 1: /* 352x288 */
746 t2[1] = 0x40;
747 break;
748 case 2: /* 320x240 */
749 t2[1] = 0x10;
750 break;
751 case 3: /* 176x144 */
752 t2[1] = 0x50;
753 break;
754 case 4: /* 160x120 */
755 t2[1] = 0x20;
756 break;
757 default: /* 640x480 (0x00) */
758 break;
759 }
760
761 if (sd->sensor == SENSOR_TAS5130A) {
762 i = 0;
763 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300764 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300765 sizeof tas5130a_sensor_init[0]);
766 i++;
767 }
768 reg_w(gspca_dev, 0x3c80);
769 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300770 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300771 sizeof tas5130a_sensor_init[0]);
772 reg_w(gspca_dev, 0x3c80);
773 } else {
774 other_sensor_init(gspca_dev);
775 }
776 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300777 reg_w_buf(gspca_dev, t1, sizeof t1);
778 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300779 reg_r(gspca_dev, 0x0012);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300780 reg_w_buf(gspca_dev, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300781 reg_w(gspca_dev, 0x0013);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300782 reg_w_buf(gspca_dev, t4, sizeof t4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300783 /* restart on each start, just in case, sometimes regs goes wrong
784 * when using controls from app */
785 setbrightness(gspca_dev);
786 setcontrast(gspca_dev);
787 setcolors(gspca_dev);
788 return 0;
789}
790
791static void sd_pkt_scan(struct gspca_dev *gspca_dev,
792 struct gspca_frame *frame, /* target */
793 __u8 *data, /* isoc packet */
794 int len) /* iso packet length */
795{
796 static __u8 ffd9[] = { 0xff, 0xd9 };
797
798 if (data[0] == 0x5a) {
799 /* Control Packet, after this came the header again,
800 * but extra bytes came in the packet before this,
801 * sometimes an EOF arrives, sometimes not... */
802 return;
803 }
804 data += 2;
805 len -= 2;
806 if (data[0] == 0xff && data[1] == 0xd8) {
807 /* extra bytes....., could be processed too but would be
808 * a waste of time, right now leave the application and
809 * libjpeg do it for ourserlves.. */
810 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
811 ffd9, 2);
812 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
813 return;
814 }
815
816 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
817 /* Just in case, i have seen packets with the marker,
818 * other's do not include it... */
819 len -= 2;
820 }
821 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300822}
823
824static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
825{
826 struct sd *sd = (struct sd *) gspca_dev;
827
828 sd->brightness = val;
829 if (gspca_dev->streaming)
830 setbrightness(gspca_dev);
831 return 0;
832}
833
834static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
835{
836 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300837
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 *val = sd->brightness;
839 return *val;
840}
841
842static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
843{
844 struct sd *sd = (struct sd *) gspca_dev;
845
846 sd->whitebalance = val;
847 if (gspca_dev->streaming)
848 setwhitebalance(gspca_dev);
849 return 0;
850}
851
852static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
853{
854 struct sd *sd = (struct sd *) gspca_dev;
855
856 *val = sd->whitebalance;
857 return *val;
858}
859
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300860static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
861{
862 struct sd *sd = (struct sd *) gspca_dev;
863
864 sd->mirror = val;
865 if (gspca_dev->streaming)
866 setflip(gspca_dev);
867 return 0;
868}
869
870static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 *val = sd->mirror;
875 return *val;
876}
877
878static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
879{
880 struct sd *sd = (struct sd *) gspca_dev;
881
882 sd->effect = val;
883 if (gspca_dev->streaming)
884 seteffect(gspca_dev);
885 return 0;
886}
887
888static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
889{
890 struct sd *sd = (struct sd *) gspca_dev;
891
892 *val = sd->effect;
893 return *val;
894}
895
896static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
897{
898 struct sd *sd = (struct sd *) gspca_dev;
899
900 sd->contrast = val;
901 if (gspca_dev->streaming)
902 setcontrast(gspca_dev);
903 return 0;
904}
905
906static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
907{
908 struct sd *sd = (struct sd *) gspca_dev;
909
910 *val = sd->contrast;
911 return *val;
912}
913
914static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
915{
916 struct sd *sd = (struct sd *) gspca_dev;
917
918 sd->colors = val;
919 if (gspca_dev->streaming)
920 setcolors(gspca_dev);
921 return 0;
922}
923
924static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 *val = sd->colors;
929 return 0;
930}
931
932static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
933{
934 struct sd *sd = (struct sd *) gspca_dev;
935
936 sd->gamma = val;
937 if (gspca_dev->streaming)
938 setgamma(gspca_dev);
939 return 0;
940}
941
942static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
943{
944 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300945
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300946 *val = sd->gamma;
947 return 0;
948}
949
950static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
951{
952 struct sd *sd = (struct sd *) gspca_dev;
953
954 sd->freq = val;
955 if (gspca_dev->streaming)
956 setlightfreq(gspca_dev);
957 return 0;
958}
959
960static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
961{
962 struct sd *sd = (struct sd *) gspca_dev;
963
964 *val = sd->freq;
965 return 0;
966}
967
968static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
969{
970 struct sd *sd = (struct sd *) gspca_dev;
971
972 sd->sharpness = val;
973 if (gspca_dev->streaming)
974 setsharpness(gspca_dev);
975 return 0;
976}
977
978static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 *val = sd->sharpness;
983 return 0;
984}
985
986/* Low Light set here......*/
987static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
988{
989 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300990
991 sd->autogain = val;
992 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300993 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300994 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300995 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300996 return 0;
997}
998
999static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1000{
1001 struct sd *sd = (struct sd *) gspca_dev;
1002
1003 *val = sd->autogain;
1004 return 0;
1005}
1006
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007static int sd_querymenu(struct gspca_dev *gspca_dev,
1008 struct v4l2_querymenu *menu)
1009{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001010 switch (menu->id) {
1011 case V4L2_CID_POWER_LINE_FREQUENCY:
1012 switch (menu->index) {
1013 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001014 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015 return 0;
1016 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001017 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001018 return 0;
1019 }
1020 break;
1021 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001022 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1023 strncpy((char *) menu->name,
1024 effects_control[menu->index], 32);
1025 return 0;
1026 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 break;
1028 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001029 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001030}
1031
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001033static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001034 .name = MODULE_NAME,
1035 .ctrls = sd_ctrls,
1036 .nctrls = ARRAY_SIZE(sd_ctrls),
1037 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001038 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001039 .start = sd_start,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001040 .pkt_scan = sd_pkt_scan,
1041 .querymenu = sd_querymenu,
1042};
1043
1044/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001045static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001046 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047 {}
1048};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049MODULE_DEVICE_TABLE(usb, device_table);
1050
1051/* -- device connect -- */
1052static int sd_probe(struct usb_interface *intf,
1053 const struct usb_device_id *id)
1054{
1055 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1056 THIS_MODULE);
1057}
1058
1059static struct usb_driver sd_driver = {
1060 .name = MODULE_NAME,
1061 .id_table = device_table,
1062 .probe = sd_probe,
1063 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001064#ifdef CONFIG_PM
1065 .suspend = gspca_suspend,
1066 .resume = gspca_resume,
1067#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068};
1069
1070/* -- module insert / remove -- */
1071static int __init sd_mod_init(void)
1072{
1073 if (usb_register(&sd_driver) < 0)
1074 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001075 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001076 return 0;
1077}
1078static void __exit sd_mod_exit(void)
1079{
1080 usb_deregister(&sd_driver);
1081 PDEBUG(D_PROBE, "deregistered");
1082}
1083
1084module_init(sd_mod_init);
1085module_exit(sd_mod_exit);