blob: 169004a95f8b86804c00633cbe690f2fd52b7474 [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,
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 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 Moinefadc7992008-10-08 08:06:08 -0300505static void setgamma(struct gspca_dev *gspca_dev)
506{
507 struct sd *sd = (struct sd *) gspca_dev;
508
509 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300510 reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300511}
512
513/* this function is called at probe and resume time */
514static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300515{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300516 /* some of this registers are not really neded, because
517 * they are overriden by setbrigthness, setcontrast, etc,
518 * but wont hurt anyway, and can help someone with similar webcam
519 * to see the initial parameters.*/
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300520 struct sd *sd = (struct sd *) gspca_dev;
521 int i;
522 __u8 byte, test_byte;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300523
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300524 static const __u8 read_indexs[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300525 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
526 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300527 static const __u8 n1[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300528 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300529 static const __u8 n2[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 {0x08, 0x00};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300531 static const __u8 n3[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300533 static const __u8 n4[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300534 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
535 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
536 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
537 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
538 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
539 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
540 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
541 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
542 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300543 static const __u8 nset4[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
545 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
546 0xe8, 0xe0
547 };
548 /* ojo puede ser 0xe6 en vez de 0xe9 */
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300549 static const __u8 nset2[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300550 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
551 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
552 0xd8, 0xc8, 0xd9, 0xfc
553 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300554 static const __u8 missing[] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300555 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300556 static const __u8 nset3[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300557 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
558 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
559 0xcf, 0xe0
560 };
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300561 static const __u8 nset5[] =
562 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300563 static const __u8 nset7[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300564 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300565 static const __u8 nset9[4] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300566 { 0x0b, 0x04, 0x0a, 0x78 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300567 static const __u8 nset8[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300568 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569 static const __u8 nset10[6] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
571
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300572 byte = reg_r(gspca_dev, 0x06);
573 test_byte = reg_r(gspca_dev, 0x07);
574 if (byte == 0x08 && test_byte == 0x07) {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300575 PDEBUG(D_CONF, "sensor om6802");
576 sd->sensor = SENSOR_OM6802;
577 } else if (byte == 0x08 && test_byte == 0x01) {
578 PDEBUG(D_CONF, "sensor tas5130a");
579 sd->sensor = SENSOR_TAS5130A;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300580 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300581 PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300582 sd->sensor = SENSOR_TAS5130A;
583 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300585 reg_w_buf(gspca_dev, n1, sizeof n1);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300586 test_byte = 0;
587 i = 5;
588 while (--i >= 0) {
Jean-Francois Moine392ee5a2008-10-17 05:00:59 -0300589 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300590 test_byte = reg_r(gspca_dev, 0x0063);
591 msleep(100);
592 if (test_byte == 0x17)
593 break; /* OK */
594 }
595 if (i < 0) {
596 err("Bad sensor reset %02x", test_byte);
597/* return -EIO; */
598/*fixme: test - continue */
599 }
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300600 reg_w_buf(gspca_dev, n2, sizeof n2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300601
602 i = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300603 while (read_indexs[i] != 0x00) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300604 test_byte = reg_r(gspca_dev, read_indexs[i]);
605 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300606 test_byte);
607 i++;
608 }
609
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300610 reg_w_buf(gspca_dev, n3, sizeof n3);
611 reg_w_buf(gspca_dev, n4, sizeof n4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300612 reg_r(gspca_dev, 0x0080);
613 reg_w(gspca_dev, 0x2c80);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300614 reg_w_buf(gspca_dev, nset2, sizeof nset2);
615 reg_w_buf(gspca_dev, nset3, sizeof nset3);
616 reg_w_buf(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300617 reg_w(gspca_dev, 0x3880);
618 reg_w(gspca_dev, 0x3880);
619 reg_w(gspca_dev, 0x338e);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300620 reg_w_buf(gspca_dev, nset5, sizeof nset5);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300621 reg_w(gspca_dev, 0x00a9);
622 setgamma(gspca_dev);
623 reg_w(gspca_dev, 0x86bb);
624 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300625
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300626 reg_w_buf(gspca_dev, missing, sizeof missing);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300628 reg_w(gspca_dev, 0x2087);
629 reg_w(gspca_dev, 0x2088);
630 reg_w(gspca_dev, 0x2089);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300631
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300632 reg_w_buf(gspca_dev, nset7, sizeof nset7);
633 reg_w_buf(gspca_dev, nset10, sizeof nset10);
634 reg_w_buf(gspca_dev, nset8, sizeof nset8);
635 reg_w_buf(gspca_dev, nset9, sizeof nset9);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300637 reg_w(gspca_dev, 0x2880);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300638 reg_w_buf(gspca_dev, nset2, sizeof nset2);
639 reg_w_buf(gspca_dev, nset3, sizeof nset3);
640 reg_w_buf(gspca_dev, nset4, sizeof nset4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300641
642 return 0;
643}
644
645static void setbrightness(struct gspca_dev *gspca_dev)
646{
647 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 unsigned int brightness;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300649 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 };
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300650
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300651 brightness = sd->brightness;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300652 if (brightness < 7) {
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300653 set6[3] = 0x70 - brightness * 0x10;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300654 } else {
655 set6[1] = 0x24;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300656 set6[3] = 0x00 + ((brightness - 7) * 0x10);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300657 }
658
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300659 reg_w_buf(gspca_dev, set6, sizeof set6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660}
661
662static void setflip(struct gspca_dev *gspca_dev)
663{
664 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300665 __u8 flipcmd[8] =
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300666 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300668 if (sd->mirror)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300669 flipcmd[3] = 0x01;
670
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300671 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300672}
673
674static void seteffect(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 Moinef89be032008-10-17 04:42:29 -0300678 reg_w_buf(gspca_dev, effects_table[sd->effect],
679 sizeof effects_table[0]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300680 if (sd->effect == 1 || sd->effect == 5) {
681 PDEBUG(D_CONF,
682 "This effect have been disabled for webcam \"safety\"");
683 return;
684 }
685
686 if (sd->effect == 1 || sd->effect == 4)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300687 reg_w(gspca_dev, 0x4aa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300688 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300689 reg_w(gspca_dev, 0xfaa6);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690}
691
692static void setwhitebalance(struct gspca_dev *gspca_dev)
693{
694 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300696 __u8 white_balance[8] =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300697 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
698
699 if (sd->whitebalance == 1)
700 white_balance[7] = 0x3c;
701
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300702 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300703}
704
705static void setlightfreq(struct gspca_dev *gspca_dev)
706{
707 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300708 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
709
710 if (sd->freq == 2) /* 60hz */
711 freq[1] = 0x00;
712
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300713 reg_w_buf(gspca_dev, freq, sizeof freq);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300714}
715
716static void setcontrast(struct gspca_dev *gspca_dev)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300719 unsigned int contrast = sd->contrast;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300720 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300721
722 if (contrast < 7)
723 reg_to_write = 0x8ea9 - (0x200 * contrast);
724 else
725 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
726
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300727 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300728}
729
730static void setcolors(struct gspca_dev *gspca_dev)
731{
732 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300733 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300734
735 reg_to_write = 0xc0bb + sd->colors * 0x100;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300736 reg_w(gspca_dev, reg_to_write);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300737}
738
739static void setsharpness(struct gspca_dev *gspca_dev)
740{
741 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300742 __u16 reg_to_write;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300743
744 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
745
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300746 reg_w(gspca_dev, reg_to_write);
747}
748
749static int sd_start(struct gspca_dev *gspca_dev)
750{
751 struct sd *sd = (struct sd *) gspca_dev;
752 int i, mode;
753 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
754 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
755 static const __u8 t3[] =
756 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
757 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
758 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
759
760 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
761 switch (mode) {
762 case 1: /* 352x288 */
763 t2[1] = 0x40;
764 break;
765 case 2: /* 320x240 */
766 t2[1] = 0x10;
767 break;
768 case 3: /* 176x144 */
769 t2[1] = 0x50;
770 break;
771 case 4: /* 160x120 */
772 t2[1] = 0x20;
773 break;
774 default: /* 640x480 (0x00) */
775 break;
776 }
777
778 if (sd->sensor == SENSOR_TAS5130A) {
779 i = 0;
780 while (tas5130a_sensor_init[i][0] != 0) {
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300781 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300782 sizeof tas5130a_sensor_init[0]);
783 i++;
784 }
785 reg_w(gspca_dev, 0x3c80);
786 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300787 reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300788 sizeof tas5130a_sensor_init[0]);
789 reg_w(gspca_dev, 0x3c80);
790 } else {
Jean-Francois Moine236088d2008-10-17 04:53:02 -0300791 om6802_sensor_init(gspca_dev);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300792 }
793 /* just in case and to keep sync with logs (for mine) */
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300794 reg_w_buf(gspca_dev, t1, sizeof t1);
795 reg_w_buf(gspca_dev, t2, sizeof t2);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300796 reg_r(gspca_dev, 0x0012);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300797 reg_w_buf(gspca_dev, t3, sizeof t3);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300798 reg_w(gspca_dev, 0x0013);
Jean-Francois Moinef89be032008-10-17 04:42:29 -0300799 reg_w_buf(gspca_dev, t4, sizeof t4);
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300800 /* restart on each start, just in case, sometimes regs goes wrong
801 * when using controls from app */
802 setbrightness(gspca_dev);
803 setcontrast(gspca_dev);
804 setcolors(gspca_dev);
805 return 0;
806}
807
808static void sd_pkt_scan(struct gspca_dev *gspca_dev,
809 struct gspca_frame *frame, /* target */
810 __u8 *data, /* isoc packet */
811 int len) /* iso packet length */
812{
813 static __u8 ffd9[] = { 0xff, 0xd9 };
814
815 if (data[0] == 0x5a) {
816 /* Control Packet, after this came the header again,
817 * but extra bytes came in the packet before this,
818 * sometimes an EOF arrives, sometimes not... */
819 return;
820 }
821 data += 2;
822 len -= 2;
823 if (data[0] == 0xff && data[1] == 0xd8) {
824 /* extra bytes....., could be processed too but would be
825 * a waste of time, right now leave the application and
826 * libjpeg do it for ourserlves.. */
827 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
828 ffd9, 2);
829 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
830 return;
831 }
832
833 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
834 /* Just in case, i have seen packets with the marker,
835 * other's do not include it... */
836 len -= 2;
837 }
838 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300839}
840
841static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
842{
843 struct sd *sd = (struct sd *) gspca_dev;
844
845 sd->brightness = val;
846 if (gspca_dev->streaming)
847 setbrightness(gspca_dev);
848 return 0;
849}
850
851static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
852{
853 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300854
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300855 *val = sd->brightness;
856 return *val;
857}
858
859static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
860{
861 struct sd *sd = (struct sd *) gspca_dev;
862
863 sd->whitebalance = val;
864 if (gspca_dev->streaming)
865 setwhitebalance(gspca_dev);
866 return 0;
867}
868
869static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
870{
871 struct sd *sd = (struct sd *) gspca_dev;
872
873 *val = sd->whitebalance;
874 return *val;
875}
876
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300877static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
878{
879 struct sd *sd = (struct sd *) gspca_dev;
880
881 sd->mirror = val;
882 if (gspca_dev->streaming)
883 setflip(gspca_dev);
884 return 0;
885}
886
887static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
888{
889 struct sd *sd = (struct sd *) gspca_dev;
890
891 *val = sd->mirror;
892 return *val;
893}
894
895static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 sd->effect = val;
900 if (gspca_dev->streaming)
901 seteffect(gspca_dev);
902 return 0;
903}
904
905static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 *val = sd->effect;
910 return *val;
911}
912
913static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916
917 sd->contrast = val;
918 if (gspca_dev->streaming)
919 setcontrast(gspca_dev);
920 return 0;
921}
922
923static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926
927 *val = sd->contrast;
928 return *val;
929}
930
931static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
934
935 sd->colors = val;
936 if (gspca_dev->streaming)
937 setcolors(gspca_dev);
938 return 0;
939}
940
941static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
944
945 *val = sd->colors;
946 return 0;
947}
948
949static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
952
953 sd->gamma = val;
954 if (gspca_dev->streaming)
955 setgamma(gspca_dev);
956 return 0;
957}
958
959static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefadc7992008-10-08 08:06:08 -0300962
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300963 *val = sd->gamma;
964 return 0;
965}
966
967static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 sd->freq = val;
972 if (gspca_dev->streaming)
973 setlightfreq(gspca_dev);
974 return 0;
975}
976
977static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->freq;
982 return 0;
983}
984
985static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 sd->sharpness = val;
990 if (gspca_dev->streaming)
991 setsharpness(gspca_dev);
992 return 0;
993}
994
995static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 *val = sd->sharpness;
1000 return 0;
1001}
1002
1003/* Low Light set here......*/
1004static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1005{
1006 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001007
1008 sd->autogain = val;
1009 if (val != 0)
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001010 reg_w(gspca_dev, 0xf48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001011 else
Jean-Francois Moinefadc7992008-10-08 08:06:08 -03001012 reg_w(gspca_dev, 0xb48e);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001013 return 0;
1014}
1015
1016static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1017{
1018 struct sd *sd = (struct sd *) gspca_dev;
1019
1020 *val = sd->autogain;
1021 return 0;
1022}
1023
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001024static int sd_querymenu(struct gspca_dev *gspca_dev,
1025 struct v4l2_querymenu *menu)
1026{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001027 switch (menu->id) {
1028 case V4L2_CID_POWER_LINE_FREQUENCY:
1029 switch (menu->index) {
1030 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001031 strcpy((char *) menu->name, "50 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032 return 0;
1033 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001034 strcpy((char *) menu->name, "60 Hz");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001035 return 0;
1036 }
1037 break;
1038 case V4L2_CID_EFFECTS:
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001039 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1040 strncpy((char *) menu->name,
1041 effects_control[menu->index], 32);
1042 return 0;
1043 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 break;
1045 }
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001046 return -EINVAL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001047}
1048
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001050static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001051 .name = MODULE_NAME,
1052 .ctrls = sd_ctrls,
1053 .nctrls = ARRAY_SIZE(sd_ctrls),
1054 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001055 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 .start = sd_start,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057 .pkt_scan = sd_pkt_scan,
1058 .querymenu = sd_querymenu,
1059};
1060
1061/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001062static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine9d64fdb2008-07-25 08:53:03 -03001063 {USB_DEVICE(0x17a1, 0x0128)},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001064 {}
1065};
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001066MODULE_DEVICE_TABLE(usb, device_table);
1067
1068/* -- device connect -- */
1069static int sd_probe(struct usb_interface *intf,
1070 const struct usb_device_id *id)
1071{
1072 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1073 THIS_MODULE);
1074}
1075
1076static struct usb_driver sd_driver = {
1077 .name = MODULE_NAME,
1078 .id_table = device_table,
1079 .probe = sd_probe,
1080 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03001081#ifdef CONFIG_PM
1082 .suspend = gspca_suspend,
1083 .resume = gspca_resume,
1084#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001085};
1086
1087/* -- module insert / remove -- */
1088static int __init sd_mod_init(void)
1089{
1090 if (usb_register(&sd_driver) < 0)
1091 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001092 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001093 return 0;
1094}
1095static void __exit sd_mod_exit(void)
1096{
1097 usb_deregister(&sd_driver);
1098 PDEBUG(D_PROBE, "deregistered");
1099}
1100
1101module_init(sd_mod_init);
1102module_exit(sd_mod_exit);