]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/video/gspca/m5602/m5602_ov9650.c
V4L/DVB (11405): gspca - m5602: Simplify error handling
[mirror_ubuntu-jammy-kernel.git] / drivers / media / video / gspca / m5602 / m5602_ov9650.c
CommitLineData
c109f816
EA
1/*
2 * Driver for the ov9650 sensor
3 *
0c505e68 4 * Copyright (C) 2008 Erik Andrén
c109f816
EA
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_ov9650.h"
20
30881ab7
EA
21/* Vertically and horizontally flips the image if matched, needed for machines
22 where the sensor is mounted upside down */
23static
24 const
25 struct dmi_system_id ov9650_flip_dmi_table[] = {
26 {
27 .ident = "ASUS A6VC",
28 .matches = {
29 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
30 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
31 }
32 },
33 {
34 .ident = "ASUS A6VM",
35 .matches = {
36 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
37 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
38 }
39 },
40 {
41 .ident = "ASUS A6JC",
42 .matches = {
43 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
44 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
45 }
46 },
3efb6bda
EA
47 {
48 .ident = "ASUS A6Ja",
49 .matches = {
50 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
51 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
52 }
53 },
30881ab7
EA
54 {
55 .ident = "ASUS A6Kt",
56 .matches = {
57 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
58 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
59 }
60 },
7e08e66a
EA
61 {
62 .ident = "Alienware Aurora m9700",
63 .matches = {
64 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
65 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
66 }
67 },
30881ab7
EA
68 { }
69};
70
658efb63
EA
71static void ov9650_dump_registers(struct sd *sd);
72
c109f816
EA
73int ov9650_probe(struct sd *sd)
74{
75 u8 prod_id = 0, ver_id = 0, i;
76
77 if (force_sensor) {
78 if (force_sensor == OV9650_SENSOR) {
79 info("Forcing an %s sensor", ov9650.name);
80 goto sensor_found;
81 }
82 /* If we want to force another sensor,
83 don't try to probe this one */
84 return -ENODEV;
85 }
86
87 info("Probing for an ov9650 sensor");
88
89 /* Run the pre-init to actually probe the unit */
90 for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
91 u8 data = preinit_ov9650[i][2];
92 if (preinit_ov9650[i][0] == SENSOR)
6dc4cff0 93 m5602_write_sensor(sd,
c109f816
EA
94 preinit_ov9650[i][1], &data, 1);
95 else
96 m5602_write_bridge(sd, preinit_ov9650[i][1], data);
97 }
98
905aabaf 99 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
c109f816
EA
100 return -ENODEV;
101
905aabaf 102 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
c109f816
EA
103 return -ENODEV;
104
105 if ((prod_id == 0x96) && (ver_id == 0x52)) {
106 info("Detected an ov9650 sensor");
107 goto sensor_found;
108 }
109
110 return -ENODEV;
111
112sensor_found:
113 sd->gspca_dev.cam.cam_mode = ov9650.modes;
114 sd->gspca_dev.cam.nmodes = ov9650.nmodes;
d2d7e9ae
EA
115 sd->desc->ctrls = ov9650.ctrls;
116 sd->desc->nctrls = ov9650.nctrls;
c109f816
EA
117 return 0;
118}
119
120int ov9650_init(struct sd *sd)
121{
122 int i, err = 0;
123 u8 data;
124
125 if (dump_sensor)
126 ov9650_dump_registers(sd);
127
128 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
129 data = init_ov9650[i][2];
130 if (init_ov9650[i][0] == SENSOR)
6dc4cff0 131 err = m5602_write_sensor(sd, init_ov9650[i][1],
c109f816
EA
132 &data, 1);
133 else
134 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
135 }
136
e07b14e8 137 if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
c109f816
EA
138 info("vflip quirk active");
139 data = 0x30;
6dc4cff0 140 err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1);
c109f816 141 }
e07b14e8 142 return err;
c109f816
EA
143}
144
082aa893
EA
145int ov9650_start(struct sd *sd)
146{
147 int i, err = 0;
148 struct cam *cam = &sd->gspca_dev.cam;
149
27b1e4ca
EA
150 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
151 u8 data = res_init_ov9650[i][1];
152 err = m5602_write_bridge(sd, res_init_ov9650[i][0], data);
153 }
154 if (err < 0)
155 return err;
156
082aa893
EA
157 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width)
158 {
082aa893
EA
159 case 640:
160 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
161
162 for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) {
163 u8 data = VGA_ov9650[i][2];
164 if (VGA_ov9650[i][0] == SENSOR)
165 err = m5602_write_sensor(sd,
166 VGA_ov9650[i][1], &data, 1);
167 else
168 err = m5602_write_bridge(sd, VGA_ov9650[i][1], data);
169 }
170 break;
3b2f3327 171
03f46de9
EA
172 case 352:
173 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
174
175 for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) {
176 u8 data = CIF_ov9650[i][2];
177 if (CIF_ov9650[i][0] == SENSOR)
178 err = m5602_write_sensor(sd,
179 CIF_ov9650[i][1], &data, 1);
180 else
181 err = m5602_write_bridge(sd, CIF_ov9650[i][1], data);
182 }
183 break;
184
3b2f3327
EA
185 case 320:
186 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
187
188 for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) {
189 u8 data = QVGA_ov9650[i][2];
190 if (QVGA_ov9650[i][0] == SENSOR)
191 err = m5602_write_sensor(sd,
192 QVGA_ov9650[i][1], &data, 1);
193 else
194 err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data);
195 }
196 break;
082aa893
EA
197 }
198 return err;
199}
200
c109f816
EA
201int ov9650_power_down(struct sd *sd)
202{
e07b14e8
EA
203 int i, err = 0;
204 for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
c109f816
EA
205 u8 data = power_down_ov9650[i][2];
206 if (power_down_ov9650[i][0] == SENSOR)
6dc4cff0 207 err = m5602_write_sensor(sd,
c109f816
EA
208 power_down_ov9650[i][1], &data, 1);
209 else
082ec3b8
EA
210 err = m5602_write_bridge(sd, power_down_ov9650[i][1],
211 data);
c109f816
EA
212 }
213
e07b14e8 214 return err;
c109f816
EA
215}
216
217int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
218{
219 struct sd *sd = (struct sd *) gspca_dev;
220 u8 i2c_data;
221 int err;
222
905aabaf 223 err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
c109f816 224 if (err < 0)
051781b3 225 return err;
c109f816
EA
226 *val = i2c_data & 0x03;
227
905aabaf 228 err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
c109f816 229 if (err < 0)
051781b3 230 return err;
c109f816
EA
231 *val |= (i2c_data << 2);
232
905aabaf 233 err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
c109f816 234 if (err < 0)
051781b3 235 return err;
c109f816
EA
236 *val |= (i2c_data & 0x3f) << 10;
237
17ea88ae 238 PDEBUG(D_V4L2, "Read exposure %d", *val);
051781b3 239
e07b14e8 240 return err;
c109f816
EA
241}
242
243int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 u8 i2c_data;
247 int err;
248
17ea88ae 249 PDEBUG(D_V4L2, "Set exposure to %d",
c109f816
EA
250 val & 0xffff);
251
252 /* The 6 MSBs */
253 i2c_data = (val >> 10) & 0x3f;
6dc4cff0 254 err = m5602_write_sensor(sd, OV9650_AECHM,
c109f816
EA
255 &i2c_data, 1);
256 if (err < 0)
051781b3 257 return err;
c109f816
EA
258
259 /* The 8 middle bits */
260 i2c_data = (val >> 2) & 0xff;
6dc4cff0 261 err = m5602_write_sensor(sd, OV9650_AECH,
c109f816
EA
262 &i2c_data, 1);
263 if (err < 0)
051781b3 264 return err;
c109f816
EA
265
266 /* The 2 LSBs */
267 i2c_data = val & 0x03;
6dc4cff0 268 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
c109f816 269
e07b14e8 270 return err;
c109f816
EA
271}
272
273int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
274{
275 int err;
276 u8 i2c_data;
277 struct sd *sd = (struct sd *) gspca_dev;
278
905aabaf 279 m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816
EA
280 *val = (i2c_data & 0x03) << 8;
281
905aabaf 282 err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
c109f816 283 *val |= i2c_data;
17ea88ae 284 PDEBUG(D_V4L2, "Read gain %d", *val);
e07b14e8 285 return err;
c109f816
EA
286}
287
288int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
289{
290 int err;
291 u8 i2c_data;
292 struct sd *sd = (struct sd *) gspca_dev;
293
294 /* The 2 MSB */
295 /* Read the OV9650_VREF register first to avoid
296 corrupting the VREF high and low bits */
905aabaf 297 m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816
EA
298 /* Mask away all uninteresting bits */
299 i2c_data = ((val & 0x0300) >> 2) |
300 (i2c_data & 0x3F);
6dc4cff0 301 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816
EA
302
303 /* The 8 LSBs */
304 i2c_data = val & 0xff;
6dc4cff0 305 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
e07b14e8 306 return err;
c109f816
EA
307}
308
309int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
310{
311 int err;
312 u8 i2c_data;
313 struct sd *sd = (struct sd *) gspca_dev;
314
905aabaf 315 err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1);
c109f816
EA
316 *val = i2c_data;
317
17ea88ae 318 PDEBUG(D_V4L2, "Read red gain %d", *val);
c109f816 319
e07b14e8 320 return err;
c109f816
EA
321}
322
323int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
324{
325 int err;
326 u8 i2c_data;
327 struct sd *sd = (struct sd *) gspca_dev;
328
17ea88ae 329 PDEBUG(D_V4L2, "Set red gain to %d",
c109f816
EA
330 val & 0xff);
331
332 i2c_data = val & 0xff;
6dc4cff0 333 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
c109f816 334
e07b14e8 335 return err;
c109f816
EA
336}
337
338int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
339{
340 int err;
341 u8 i2c_data;
342 struct sd *sd = (struct sd *) gspca_dev;
343
905aabaf 344 err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
c109f816
EA
345 *val = i2c_data;
346
17ea88ae 347 PDEBUG(D_V4L2, "Read blue gain %d", *val);
c109f816 348
e07b14e8 349 return err;
c109f816
EA
350}
351
352int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
353{
354 int err;
355 u8 i2c_data;
356 struct sd *sd = (struct sd *) gspca_dev;
357
17ea88ae 358 PDEBUG(D_V4L2, "Set blue gain to %d",
c109f816
EA
359 val & 0xff);
360
361 i2c_data = val & 0xff;
6dc4cff0 362 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
c109f816 363
e07b14e8 364 return err;
c109f816
EA
365}
366
367int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
368{
369 int err;
370 u8 i2c_data;
371 struct sd *sd = (struct sd *) gspca_dev;
372
905aabaf 373 err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
c109f816
EA
374 if (dmi_check_system(ov9650_flip_dmi_table))
375 *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
376 else
377 *val = (i2c_data & OV9650_HFLIP) >> 5;
17ea88ae 378 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
c109f816 379
e07b14e8 380 return err;
c109f816
EA
381}
382
383int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
384{
385 int err;
386 u8 i2c_data;
387 struct sd *sd = (struct sd *) gspca_dev;
388
17ea88ae 389 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
905aabaf 390 err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
c109f816 391 if (err < 0)
051781b3 392 return err;
c109f816
EA
393
394 if (dmi_check_system(ov9650_flip_dmi_table))
395 i2c_data = ((i2c_data & 0xdf) |
e07b14e8 396 (((val ? 0 : 1) & 0x01) << 5));
c109f816
EA
397 else
398 i2c_data = ((i2c_data & 0xdf) |
e07b14e8 399 ((val & 0x01) << 5));
c109f816 400
6dc4cff0 401 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
051781b3 402
e07b14e8 403 return err;
c109f816
EA
404}
405
406int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
407{
408 int err;
409 u8 i2c_data;
410 struct sd *sd = (struct sd *) gspca_dev;
411
905aabaf 412 err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
c109f816
EA
413 if (dmi_check_system(ov9650_flip_dmi_table))
414 *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
415 else
416 *val = (i2c_data & 0x10) >> 4;
17ea88ae 417 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
c109f816 418
e07b14e8 419 return err;
c109f816
EA
420}
421
422int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
423{
424 int err;
425 u8 i2c_data;
426 struct sd *sd = (struct sd *) gspca_dev;
427
17ea88ae 428 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
905aabaf 429 err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
c109f816 430 if (err < 0)
051781b3 431 return err;
c109f816
EA
432
433 if (dmi_check_system(ov9650_flip_dmi_table))
434 i2c_data = ((i2c_data & 0xef) |
435 (((val ? 0 : 1) & 0x01) << 4));
436 else
437 i2c_data = ((i2c_data & 0xef) |
438 ((val & 0x01) << 4));
439
6dc4cff0 440 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
051781b3 441
e07b14e8 442 return err;
c109f816
EA
443}
444
445int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
446{
447 int err;
448 u8 i2c_data;
449 struct sd *sd = (struct sd *) gspca_dev;
450
905aabaf 451 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816 452 if (err < 0)
051781b3 453 return err;
c109f816
EA
454 *val = (i2c_data & 0x03) << 8;
455
905aabaf 456 err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
c109f816 457 *val |= i2c_data;
17ea88ae 458 PDEBUG(D_V4L2, "Read gain %d", *val);
051781b3 459
e07b14e8 460 return err;
c109f816
EA
461}
462
463int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
464{
465 int err;
466 u8 i2c_data;
467 struct sd *sd = (struct sd *) gspca_dev;
468
17ea88ae 469 PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff);
c109f816
EA
470
471 /* Read the OV9650_VREF register first to avoid
472 corrupting the VREF high and low bits */
905aabaf 473 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816 474 if (err < 0)
051781b3 475 return err;
c109f816
EA
476
477 /* Mask away all uninteresting bits */
478 i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
6dc4cff0 479 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
c109f816 480 if (err < 0)
051781b3 481 return err;
c109f816
EA
482
483 /* The 8 LSBs */
484 i2c_data = val & 0xff;
6dc4cff0 485 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
c109f816 486
e07b14e8 487 return err;
c109f816
EA
488}
489
490int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
491{
492 int err;
493 u8 i2c_data;
494 struct sd *sd = (struct sd *) gspca_dev;
495
905aabaf 496 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 497 *val = (i2c_data & OV9650_AWB_EN) >> 1;
17ea88ae 498 PDEBUG(D_V4L2, "Read auto white balance %d", *val);
c109f816 499
e07b14e8 500 return err;
c109f816
EA
501}
502
503int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
504{
505 int err;
506 u8 i2c_data;
507 struct sd *sd = (struct sd *) gspca_dev;
508
17ea88ae 509 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
905aabaf 510 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 511 if (err < 0)
051781b3 512 return err;
c109f816
EA
513
514 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
6dc4cff0 515 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
051781b3 516
e07b14e8 517 return err;
c109f816
EA
518}
519
520int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
521{
522 int err;
523 u8 i2c_data;
524 struct sd *sd = (struct sd *) gspca_dev;
525
905aabaf 526 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 527 *val = (i2c_data & OV9650_AGC_EN) >> 2;
17ea88ae 528 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
c109f816 529
e07b14e8 530 return err;
c109f816
EA
531}
532
533int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
534{
535 int err;
536 u8 i2c_data;
537 struct sd *sd = (struct sd *) gspca_dev;
538
17ea88ae 539 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
905aabaf 540 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
c109f816 541 if (err < 0)
051781b3 542 return err;
c109f816
EA
543
544 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
6dc4cff0 545 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
051781b3 546
e07b14e8 547 return err;
c109f816
EA
548}
549
658efb63 550static void ov9650_dump_registers(struct sd *sd)
c109f816
EA
551{
552 int address;
553 info("Dumping the ov9650 register state");
554 for (address = 0; address < 0xa9; address++) {
555 u8 value;
905aabaf 556 m5602_read_sensor(sd, address, &value, 1);
c109f816
EA
557 info("register 0x%x contains 0x%x",
558 address, value);
559 }
560
561 info("ov9650 register state dump complete");
562
563 info("Probing for which registers that are read/write");
564 for (address = 0; address < 0xff; address++) {
565 u8 old_value, ctrl_value;
566 u8 test_value[2] = {0xff, 0xff};
567
905aabaf 568 m5602_read_sensor(sd, address, &old_value, 1);
6dc4cff0 569 m5602_write_sensor(sd, address, test_value, 1);
905aabaf 570 m5602_read_sensor(sd, address, &ctrl_value, 1);
c109f816
EA
571
572 if (ctrl_value == test_value[0])
573 info("register 0x%x is writeable", address);
574 else
575 info("register 0x%x is read only", address);
576
577 /* Restore original value */
6dc4cff0 578 m5602_write_sensor(sd, address, &old_value, 1);
c109f816
EA
579 }
580}