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