ext3: Update MAINTAINERS for ext3 and JBD
[linux/fpc-iii.git] / drivers / media / video / gspca / m5602 / m5602_s5k4aa.c
blob0163903d1c0fb4a5dbbe0ec0a0b5bd5fa1b11284
1 /*
2 * Driver for the s5k4aa sensor
4 * Copyright (C) 2008 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>
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
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.
19 #include "m5602_s5k4aa.h"
21 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
22 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
23 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
24 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
25 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
30 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
31 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
32 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
34 static
35 const
36 struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
38 .ident = "Fujitsu-Siemens Amilo Xa 2528",
39 .matches = {
40 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
41 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
43 }, {
44 .ident = "Fujitsu-Siemens Amilo Xi 2550",
45 .matches = {
46 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
47 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
49 }, {
50 .ident = "MSI GX700",
51 .matches = {
52 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
53 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
54 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
56 }, {
57 .ident = "MSI GX700/GX705/EX700",
58 .matches = {
59 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
60 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
62 }, {
63 .ident = "MSI L735",
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
66 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
68 }, {
69 .ident = "Lenovo Y300",
70 .matches = {
71 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
72 DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
75 { }
78 static struct v4l2_pix_format s5k4aa_modes[] = {
80 640,
81 480,
82 V4L2_PIX_FMT_SBGGR8,
83 V4L2_FIELD_NONE,
84 .sizeimage =
85 640 * 480,
86 .bytesperline = 640,
87 .colorspace = V4L2_COLORSPACE_SRGB,
88 .priv = 0
91 1280,
92 1024,
93 V4L2_PIX_FMT_SBGGR8,
94 V4L2_FIELD_NONE,
95 .sizeimage =
96 1280 * 1024,
97 .bytesperline = 1280,
98 .colorspace = V4L2_COLORSPACE_SRGB,
99 .priv = 0
103 static const struct ctrl s5k4aa_ctrls[] = {
104 #define VFLIP_IDX 0
107 .id = V4L2_CID_VFLIP,
108 .type = V4L2_CTRL_TYPE_BOOLEAN,
109 .name = "vertical flip",
110 .minimum = 0,
111 .maximum = 1,
112 .step = 1,
113 .default_value = 0
115 .set = s5k4aa_set_vflip,
116 .get = s5k4aa_get_vflip
118 #define HFLIP_IDX 1
121 .id = V4L2_CID_HFLIP,
122 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 .name = "horizontal flip",
124 .minimum = 0,
125 .maximum = 1,
126 .step = 1,
127 .default_value = 0
129 .set = s5k4aa_set_hflip,
130 .get = s5k4aa_get_hflip
132 #define GAIN_IDX 2
135 .id = V4L2_CID_GAIN,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "Gain",
138 .minimum = 0,
139 .maximum = 127,
140 .step = 1,
141 .default_value = S5K4AA_DEFAULT_GAIN,
142 .flags = V4L2_CTRL_FLAG_SLIDER
144 .set = s5k4aa_set_gain,
145 .get = s5k4aa_get_gain
147 #define EXPOSURE_IDX 3
150 .id = V4L2_CID_EXPOSURE,
151 .type = V4L2_CTRL_TYPE_INTEGER,
152 .name = "Exposure",
153 .minimum = 13,
154 .maximum = 0xfff,
155 .step = 1,
156 .default_value = 0x100,
157 .flags = V4L2_CTRL_FLAG_SLIDER
159 .set = s5k4aa_set_exposure,
160 .get = s5k4aa_get_exposure
162 #define NOISE_SUPP_IDX 4
165 .id = V4L2_CID_PRIVATE_BASE,
166 .type = V4L2_CTRL_TYPE_BOOLEAN,
167 .name = "Noise suppression (smoothing)",
168 .minimum = 0,
169 .maximum = 1,
170 .step = 1,
171 .default_value = 1,
173 .set = s5k4aa_set_noise,
174 .get = s5k4aa_get_noise
176 #define BRIGHTNESS_IDX 5
179 .id = V4L2_CID_BRIGHTNESS,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Brightness",
182 .minimum = 0,
183 .maximum = 0x1f,
184 .step = 1,
185 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
187 .set = s5k4aa_set_brightness,
188 .get = s5k4aa_get_brightness
193 static void s5k4aa_dump_registers(struct sd *sd);
195 int s5k4aa_probe(struct sd *sd)
197 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
198 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
199 int i, err = 0;
200 s32 *sensor_settings;
202 if (force_sensor) {
203 if (force_sensor == S5K4AA_SENSOR) {
204 info("Forcing a %s sensor", s5k4aa.name);
205 goto sensor_found;
207 /* If we want to force another sensor, don't try to probe this
208 * one */
209 return -ENODEV;
212 info("Probing for a s5k4aa sensor");
214 /* Preinit the sensor */
215 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
216 u8 data[2] = {0x00, 0x00};
218 switch (preinit_s5k4aa[i][0]) {
219 case BRIDGE:
220 err = m5602_write_bridge(sd,
221 preinit_s5k4aa[i][1],
222 preinit_s5k4aa[i][2]);
223 break;
225 case SENSOR:
226 data[0] = preinit_s5k4aa[i][2];
227 err = m5602_write_sensor(sd,
228 preinit_s5k4aa[i][1],
229 data, 1);
230 break;
232 case SENSOR_LONG:
233 data[0] = preinit_s5k4aa[i][2];
234 data[1] = preinit_s5k4aa[i][3];
235 err = m5602_write_sensor(sd,
236 preinit_s5k4aa[i][1],
237 data, 2);
238 break;
239 default:
240 info("Invalid stream command, exiting init");
241 return -EINVAL;
245 /* Test some registers, but we don't know their exact meaning yet */
246 if (m5602_read_sensor(sd, 0x00, prod_id, 2))
247 return -ENODEV;
248 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
249 return -ENODEV;
250 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
251 return -ENODEV;
253 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
254 return -ENODEV;
255 else
256 info("Detected a s5k4aa sensor");
258 sensor_found:
259 sensor_settings = kmalloc(
260 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
261 if (!sensor_settings)
262 return -ENOMEM;
264 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
265 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
266 sd->desc->ctrls = s5k4aa_ctrls;
267 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
269 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
270 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
271 sd->sensor_priv = sensor_settings;
273 return 0;
276 int s5k4aa_start(struct sd *sd)
278 int i, err = 0;
279 u8 data[2];
280 struct cam *cam = &sd->gspca_dev.cam;
281 s32 *sensor_settings = sd->sensor_priv;
283 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
284 case 1280:
285 PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
287 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
288 switch (SXGA_s5k4aa[i][0]) {
289 case BRIDGE:
290 err = m5602_write_bridge(sd,
291 SXGA_s5k4aa[i][1],
292 SXGA_s5k4aa[i][2]);
293 break;
295 case SENSOR:
296 data[0] = SXGA_s5k4aa[i][2];
297 err = m5602_write_sensor(sd,
298 SXGA_s5k4aa[i][1],
299 data, 1);
300 break;
302 case SENSOR_LONG:
303 data[0] = SXGA_s5k4aa[i][2];
304 data[1] = SXGA_s5k4aa[i][3];
305 err = m5602_write_sensor(sd,
306 SXGA_s5k4aa[i][1],
307 data, 2);
308 break;
310 default:
311 err("Invalid stream command, exiting init");
312 return -EINVAL;
315 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
316 if (err < 0)
317 return err;
318 break;
320 case 640:
321 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
323 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
324 switch (VGA_s5k4aa[i][0]) {
325 case BRIDGE:
326 err = m5602_write_bridge(sd,
327 VGA_s5k4aa[i][1],
328 VGA_s5k4aa[i][2]);
329 break;
331 case SENSOR:
332 data[0] = VGA_s5k4aa[i][2];
333 err = m5602_write_sensor(sd,
334 VGA_s5k4aa[i][1],
335 data, 1);
336 break;
338 case SENSOR_LONG:
339 data[0] = VGA_s5k4aa[i][2];
340 data[1] = VGA_s5k4aa[i][3];
341 err = m5602_write_sensor(sd,
342 VGA_s5k4aa[i][1],
343 data, 2);
344 break;
346 default:
347 err("Invalid stream command, exiting init");
348 return -EINVAL;
351 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
352 if (err < 0)
353 return err;
354 break;
356 if (err < 0)
357 return err;
359 err = s5k4aa_set_exposure(&sd->gspca_dev,
360 sensor_settings[EXPOSURE_IDX]);
361 if (err < 0)
362 return err;
364 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
365 if (err < 0)
366 return err;
368 err = s5k4aa_set_brightness(&sd->gspca_dev,
369 sensor_settings[BRIGHTNESS_IDX]);
370 if (err < 0)
371 return err;
373 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
374 if (err < 0)
375 return err;
377 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
378 if (err < 0)
379 return err;
381 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
384 int s5k4aa_init(struct sd *sd)
386 int i, err = 0;
388 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
389 u8 data[2] = {0x00, 0x00};
391 switch (init_s5k4aa[i][0]) {
392 case BRIDGE:
393 err = m5602_write_bridge(sd,
394 init_s5k4aa[i][1],
395 init_s5k4aa[i][2]);
396 break;
398 case SENSOR:
399 data[0] = init_s5k4aa[i][2];
400 err = m5602_write_sensor(sd,
401 init_s5k4aa[i][1], data, 1);
402 break;
404 case SENSOR_LONG:
405 data[0] = init_s5k4aa[i][2];
406 data[1] = init_s5k4aa[i][3];
407 err = m5602_write_sensor(sd,
408 init_s5k4aa[i][1], data, 2);
409 break;
410 default:
411 info("Invalid stream command, exiting init");
412 return -EINVAL;
416 if (dump_sensor)
417 s5k4aa_dump_registers(sd);
419 return err;
422 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
424 struct sd *sd = (struct sd *) gspca_dev;
425 s32 *sensor_settings = sd->sensor_priv;
427 *val = sensor_settings[EXPOSURE_IDX];
428 PDEBUG(D_V4L2, "Read exposure %d", *val);
430 return 0;
433 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
435 struct sd *sd = (struct sd *) gspca_dev;
436 s32 *sensor_settings = sd->sensor_priv;
437 u8 data = S5K4AA_PAGE_MAP_2;
438 int err;
440 sensor_settings[EXPOSURE_IDX] = val;
441 PDEBUG(D_V4L2, "Set exposure to %d", val);
442 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
443 if (err < 0)
444 return err;
445 data = (val >> 8) & 0xff;
446 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
447 if (err < 0)
448 return err;
449 data = val & 0xff;
450 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
452 return err;
455 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
457 struct sd *sd = (struct sd *) gspca_dev;
458 s32 *sensor_settings = sd->sensor_priv;
460 *val = sensor_settings[VFLIP_IDX];
461 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
463 return 0;
466 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
468 struct sd *sd = (struct sd *) gspca_dev;
469 s32 *sensor_settings = sd->sensor_priv;
470 u8 data = S5K4AA_PAGE_MAP_2;
471 int err;
473 sensor_settings[VFLIP_IDX] = val;
475 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
476 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
477 if (err < 0)
478 return err;
480 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
481 if (err < 0)
482 return err;
484 if (dmi_check_system(s5k4aa_vflip_dmi_table))
485 val = !val;
487 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
488 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
489 if (err < 0)
490 return err;
492 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
493 if (err < 0)
494 return err;
495 data = (data & 0xfe) | !val;
496 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
497 return err;
500 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
502 struct sd *sd = (struct sd *) gspca_dev;
503 s32 *sensor_settings = sd->sensor_priv;
505 *val = sensor_settings[HFLIP_IDX];
506 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
508 return 0;
511 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
513 struct sd *sd = (struct sd *) gspca_dev;
514 s32 *sensor_settings = sd->sensor_priv;
515 u8 data = S5K4AA_PAGE_MAP_2;
516 int err;
518 sensor_settings[HFLIP_IDX] = val;
520 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
521 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
522 if (err < 0)
523 return err;
525 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
526 if (err < 0)
527 return err;
529 if (dmi_check_system(s5k4aa_vflip_dmi_table))
530 val = !val;
532 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
533 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
534 if (err < 0)
535 return err;
537 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
538 if (err < 0)
539 return err;
540 data = (data & 0xfe) | !val;
541 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
542 return err;
545 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
547 struct sd *sd = (struct sd *) gspca_dev;
548 s32 *sensor_settings = sd->sensor_priv;
550 *val = sensor_settings[GAIN_IDX];
551 PDEBUG(D_V4L2, "Read gain %d", *val);
552 return 0;
555 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
557 struct sd *sd = (struct sd *) gspca_dev;
558 s32 *sensor_settings = sd->sensor_priv;
559 u8 data = S5K4AA_PAGE_MAP_2;
560 int err;
562 sensor_settings[GAIN_IDX] = val;
564 PDEBUG(D_V4L2, "Set gain to %d", val);
565 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
566 if (err < 0)
567 return err;
569 data = val & 0xff;
570 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
572 return err;
575 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
577 struct sd *sd = (struct sd *) gspca_dev;
578 s32 *sensor_settings = sd->sensor_priv;
580 *val = sensor_settings[BRIGHTNESS_IDX];
581 PDEBUG(D_V4L2, "Read brightness %d", *val);
582 return 0;
585 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
587 struct sd *sd = (struct sd *) gspca_dev;
588 s32 *sensor_settings = sd->sensor_priv;
589 u8 data = S5K4AA_PAGE_MAP_2;
590 int err;
592 sensor_settings[BRIGHTNESS_IDX] = val;
594 PDEBUG(D_V4L2, "Set brightness to %d", val);
595 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
596 if (err < 0)
597 return err;
599 data = val & 0xff;
600 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
603 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
605 struct sd *sd = (struct sd *) gspca_dev;
606 s32 *sensor_settings = sd->sensor_priv;
608 *val = sensor_settings[NOISE_SUPP_IDX];
609 PDEBUG(D_V4L2, "Read noise %d", *val);
610 return 0;
613 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
615 struct sd *sd = (struct sd *) gspca_dev;
616 s32 *sensor_settings = sd->sensor_priv;
617 u8 data = S5K4AA_PAGE_MAP_2;
618 int err;
620 sensor_settings[NOISE_SUPP_IDX] = val;
622 PDEBUG(D_V4L2, "Set noise to %d", val);
623 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
624 if (err < 0)
625 return err;
627 data = val & 0x01;
628 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
631 void s5k4aa_disconnect(struct sd *sd)
633 sd->sensor = NULL;
634 kfree(sd->sensor_priv);
637 static void s5k4aa_dump_registers(struct sd *sd)
639 int address;
640 u8 page, old_page;
641 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
642 for (page = 0; page < 16; page++) {
643 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
644 info("Dumping the s5k4aa register state for page 0x%x", page);
645 for (address = 0; address <= 0xff; address++) {
646 u8 value = 0;
647 m5602_read_sensor(sd, address, &value, 1);
648 info("register 0x%x contains 0x%x",
649 address, value);
652 info("s5k4aa register state dump complete");
654 for (page = 0; page < 16; page++) {
655 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
656 info("Probing for which registers that are "
657 "read/write for page 0x%x", page);
658 for (address = 0; address <= 0xff; address++) {
659 u8 old_value, ctrl_value, test_value = 0xff;
661 m5602_read_sensor(sd, address, &old_value, 1);
662 m5602_write_sensor(sd, address, &test_value, 1);
663 m5602_read_sensor(sd, address, &ctrl_value, 1);
665 if (ctrl_value == test_value)
666 info("register 0x%x is writeable", address);
667 else
668 info("register 0x%x is read only", address);
670 /* Restore original value */
671 m5602_write_sensor(sd, address, &old_value, 1);
674 info("Read/write register probing complete");
675 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);