Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[pandora-kernel.git] / drivers / media / video / gspca / m5602 / m5602_ov7660.c
1 /*
2  * Driver for the ov7660 sensor
3  *
4  * Copyright (C) 2009 Erik AndrĂ©n
5  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7  *
8  * Portions of code to USB interface and ALi driver software,
9  * Copyright (c) 2006 Willem Duinker
10  * v4l2 interface modeled after the V4L2 driver
11  * for SN9C10x PC Camera Controllers
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation, version 2.
16  *
17  */
18
19 #include "m5602_ov7660.h"
20
21 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
22 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
23 static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
24                                          __s32 *val);
25 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
26                                          __s32 val);
27 static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
28 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
29 static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
30 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
31 static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32 static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33 static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34 static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35
36 static const struct ctrl ov7660_ctrls[] = {
37 #define GAIN_IDX 1
38         {
39                 {
40                         .id             = V4L2_CID_GAIN,
41                         .type           = V4L2_CTRL_TYPE_INTEGER,
42                         .name           = "gain",
43                         .minimum        = 0x00,
44                         .maximum        = 0xff,
45                         .step           = 0x1,
46                         .default_value  = OV7660_DEFAULT_GAIN,
47                         .flags          = V4L2_CTRL_FLAG_SLIDER
48                 },
49                 .set = ov7660_set_gain,
50                 .get = ov7660_get_gain
51         },
52 #define BLUE_BALANCE_IDX 2
53 #define RED_BALANCE_IDX 3
54 #define AUTO_WHITE_BALANCE_IDX 4
55         {
56                 {
57                         .id             = V4L2_CID_AUTO_WHITE_BALANCE,
58                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
59                         .name           = "auto white balance",
60                         .minimum        = 0,
61                         .maximum        = 1,
62                         .step           = 1,
63                         .default_value  = 1
64                 },
65                 .set = ov7660_set_auto_white_balance,
66                 .get = ov7660_get_auto_white_balance
67         },
68 #define AUTO_GAIN_CTRL_IDX 5
69         {
70                 {
71                         .id             = V4L2_CID_AUTOGAIN,
72                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
73                         .name           = "auto gain control",
74                         .minimum        = 0,
75                         .maximum        = 1,
76                         .step           = 1,
77                         .default_value  = 1
78                 },
79                 .set = ov7660_set_auto_gain,
80                 .get = ov7660_get_auto_gain
81         },
82 #define AUTO_EXPOSURE_IDX 6
83         {
84                 {
85                         .id             = V4L2_CID_EXPOSURE_AUTO,
86                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
87                         .name           = "auto exposure",
88                         .minimum        = 0,
89                         .maximum        = 1,
90                         .step           = 1,
91                         .default_value  = 1
92                 },
93                 .set = ov7660_set_auto_exposure,
94                 .get = ov7660_get_auto_exposure
95         },
96 #define HFLIP_IDX 7
97         {
98                 {
99                         .id             = V4L2_CID_HFLIP,
100                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
101                         .name           = "horizontal flip",
102                         .minimum        = 0,
103                         .maximum        = 1,
104                         .step           = 1,
105                         .default_value  = 0
106                 },
107                 .set = ov7660_set_hflip,
108                 .get = ov7660_get_hflip
109         },
110 #define VFLIP_IDX 8
111         {
112                 {
113                         .id             = V4L2_CID_VFLIP,
114                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
115                         .name           = "vertical flip",
116                         .minimum        = 0,
117                         .maximum        = 1,
118                         .step           = 1,
119                         .default_value  = 0
120                 },
121                 .set = ov7660_set_vflip,
122                 .get = ov7660_get_vflip
123         },
124
125 };
126
127 static struct v4l2_pix_format ov7660_modes[] = {
128         {
129                 640,
130                 480,
131                 V4L2_PIX_FMT_SBGGR8,
132                 V4L2_FIELD_NONE,
133                 .sizeimage =
134                         640 * 480,
135                 .bytesperline = 640,
136                 .colorspace = V4L2_COLORSPACE_SRGB,
137                 .priv = 0
138         }
139 };
140
141 static void ov7660_dump_registers(struct sd *sd);
142
143 int ov7660_probe(struct sd *sd)
144 {
145         int err = 0, i;
146         u8 prod_id = 0, ver_id = 0;
147
148         s32 *sensor_settings;
149
150         if (force_sensor) {
151                 if (force_sensor == OV7660_SENSOR) {
152                         info("Forcing an %s sensor", ov7660.name);
153                         goto sensor_found;
154                 }
155                 /* If we want to force another sensor,
156                 don't try to probe this one */
157                 return -ENODEV;
158         }
159
160         /* Do the preinit */
161         for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
162                 u8 data[2];
163
164                 if (preinit_ov7660[i][0] == BRIDGE) {
165                         err = m5602_write_bridge(sd,
166                                 preinit_ov7660[i][1],
167                                 preinit_ov7660[i][2]);
168                 } else {
169                         data[0] = preinit_ov7660[i][2];
170                         err = m5602_write_sensor(sd,
171                                 preinit_ov7660[i][1], data, 1);
172                 }
173         }
174         if (err < 0)
175                 return err;
176
177         if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
178                 return -ENODEV;
179
180         if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
181                 return -ENODEV;
182
183         info("Sensor reported 0x%x%x", prod_id, ver_id);
184
185         if ((prod_id == 0x76) && (ver_id == 0x60)) {
186                 info("Detected a ov7660 sensor");
187                 goto sensor_found;
188         }
189         return -ENODEV;
190
191 sensor_found:
192         sensor_settings = kmalloc(
193                 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
194         if (!sensor_settings)
195                 return -ENOMEM;
196
197         sd->gspca_dev.cam.cam_mode = ov7660_modes;
198         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
199         sd->desc->ctrls = ov7660_ctrls;
200         sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
201
202         for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
203                 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
204         sd->sensor_priv = sensor_settings;
205
206         return 0;
207 }
208
209 int ov7660_init(struct sd *sd)
210 {
211         int i, err = 0;
212         s32 *sensor_settings = sd->sensor_priv;
213
214         /* Init the sensor */
215         for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
216                 u8 data[2];
217
218                 if (init_ov7660[i][0] == BRIDGE) {
219                         err = m5602_write_bridge(sd,
220                                 init_ov7660[i][1],
221                                 init_ov7660[i][2]);
222                 } else {
223                         data[0] = init_ov7660[i][2];
224                         err = m5602_write_sensor(sd,
225                                 init_ov7660[i][1], data, 1);
226                 }
227         }
228
229         if (dump_sensor)
230                 ov7660_dump_registers(sd);
231
232         err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
233         if (err < 0)
234                 return err;
235
236         err = ov7660_set_auto_white_balance(&sd->gspca_dev,
237                 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
238         if (err < 0)
239                 return err;
240
241         err = ov7660_set_auto_gain(&sd->gspca_dev,
242                 sensor_settings[AUTO_GAIN_CTRL_IDX]);
243         if (err < 0)
244                 return err;
245
246         err = ov7660_set_auto_exposure(&sd->gspca_dev,
247                 sensor_settings[AUTO_EXPOSURE_IDX]);
248         if (err < 0)
249                 return err;
250         err = ov7660_set_hflip(&sd->gspca_dev,
251                 sensor_settings[HFLIP_IDX]);
252         if (err < 0)
253                 return err;
254
255         err = ov7660_set_vflip(&sd->gspca_dev,
256                 sensor_settings[VFLIP_IDX]);
257
258         return err;
259 }
260
261 int ov7660_start(struct sd *sd)
262 {
263         return 0;
264 }
265
266 int ov7660_stop(struct sd *sd)
267 {
268         return 0;
269 }
270
271 void ov7660_disconnect(struct sd *sd)
272 {
273         ov7660_stop(sd);
274
275         sd->sensor = NULL;
276         kfree(sd->sensor_priv);
277 }
278
279 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
280 {
281         struct sd *sd = (struct sd *) gspca_dev;
282         s32 *sensor_settings = sd->sensor_priv;
283
284         *val = sensor_settings[GAIN_IDX];
285         PDEBUG(D_V4L2, "Read gain %d", *val);
286         return 0;
287 }
288
289 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
290 {
291         int err;
292         u8 i2c_data;
293         struct sd *sd = (struct sd *) gspca_dev;
294         s32 *sensor_settings = sd->sensor_priv;
295
296         PDEBUG(D_V4L2, "Setting gain to %d", val);
297
298         sensor_settings[GAIN_IDX] = val;
299
300         err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
301         return err;
302 }
303
304
305 static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
306                                          __s32 *val)
307 {
308         struct sd *sd = (struct sd *) gspca_dev;
309         s32 *sensor_settings = sd->sensor_priv;
310
311         *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
312         return 0;
313 }
314
315 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
316                                          __s32 val)
317 {
318         int err;
319         u8 i2c_data;
320         struct sd *sd = (struct sd *) gspca_dev;
321         s32 *sensor_settings = sd->sensor_priv;
322
323         PDEBUG(D_V4L2, "Set auto white balance to %d", val);
324
325         sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
326         err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
327         if (err < 0)
328                 return err;
329
330         i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
331         err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
332
333         return err;
334 }
335
336 static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
337 {
338         struct sd *sd = (struct sd *) gspca_dev;
339         s32 *sensor_settings = sd->sensor_priv;
340
341         *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
342         PDEBUG(D_V4L2, "Read auto gain control %d", *val);
343         return 0;
344 }
345
346 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
347 {
348         int err;
349         u8 i2c_data;
350         struct sd *sd = (struct sd *) gspca_dev;
351         s32 *sensor_settings = sd->sensor_priv;
352
353         PDEBUG(D_V4L2, "Set auto gain control to %d", val);
354
355         sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
356         err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
357         if (err < 0)
358                 return err;
359
360         i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
361
362         return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
363 }
364
365 static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
366 {
367         struct sd *sd = (struct sd *) gspca_dev;
368         s32 *sensor_settings = sd->sensor_priv;
369
370         *val = sensor_settings[AUTO_EXPOSURE_IDX];
371         PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
372         return 0;
373 }
374
375 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
376                                     __s32 val)
377 {
378         int err;
379         u8 i2c_data;
380         struct sd *sd = (struct sd *) gspca_dev;
381         s32 *sensor_settings = sd->sensor_priv;
382
383         PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
384
385         sensor_settings[AUTO_EXPOSURE_IDX] = val;
386         err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
387         if (err < 0)
388                 return err;
389
390         i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
391
392         return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
393 }
394
395 static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
396 {
397         struct sd *sd = (struct sd *) gspca_dev;
398         s32 *sensor_settings = sd->sensor_priv;
399
400         *val = sensor_settings[HFLIP_IDX];
401         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
402         return 0;
403 }
404
405 static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
406 {
407         int err;
408         u8 i2c_data;
409         struct sd *sd = (struct sd *) gspca_dev;
410         s32 *sensor_settings = sd->sensor_priv;
411
412         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
413
414         sensor_settings[HFLIP_IDX] = val;
415
416         i2c_data = ((val & 0x01) << 5) |
417                 (sensor_settings[VFLIP_IDX] << 4);
418
419         err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
420
421         return err;
422 }
423
424 static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
425 {
426         struct sd *sd = (struct sd *) gspca_dev;
427         s32 *sensor_settings = sd->sensor_priv;
428
429         *val = sensor_settings[VFLIP_IDX];
430         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
431
432         return 0;
433 }
434
435 static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
436 {
437         int err;
438         u8 i2c_data;
439         struct sd *sd = (struct sd *) gspca_dev;
440         s32 *sensor_settings = sd->sensor_priv;
441
442         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
443         sensor_settings[VFLIP_IDX] = val;
444
445         i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
446         err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
447         if (err < 0)
448                 return err;
449
450         /* When vflip is toggled we need to readjust the bridge hsync/vsync */
451         if (gspca_dev->streaming)
452                 err = ov7660_start(sd);
453
454         return err;
455 }
456
457 static void ov7660_dump_registers(struct sd *sd)
458 {
459         int address;
460         info("Dumping the ov7660 register state");
461         for (address = 0; address < 0xa9; address++) {
462                 u8 value;
463                 m5602_read_sensor(sd, address, &value, 1);
464                 info("register 0x%x contains 0x%x",
465                      address, value);
466         }
467
468         info("ov7660 register state dump complete");
469
470         info("Probing for which registers that are read/write");
471         for (address = 0; address < 0xff; address++) {
472                 u8 old_value, ctrl_value;
473                 u8 test_value[2] = {0xff, 0xff};
474
475                 m5602_read_sensor(sd, address, &old_value, 1);
476                 m5602_write_sensor(sd, address, test_value, 1);
477                 m5602_read_sensor(sd, address, &ctrl_value, 1);
478
479                 if (ctrl_value == test_value[0])
480                         info("register 0x%x is writeable", address);
481                 else
482                         info("register 0x%x is read only", address);
483
484                 /* Restore original value */
485                 m5602_write_sensor(sd, address, &old_value, 1);
486         }
487 }