OMAP3 SRF: Generic shared resource f/w
[linux-ginger.git] / drivers / media / video / gspca / m5602 / m5602_s5k4aa.c
blob59400e85896511781a7246148851966f08848844
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 = "Fujitsu-Siemens Amilo Pa 2548",
51 .matches = {
52 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
53 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
55 }, {
56 .ident = "MSI GX700",
57 .matches = {
58 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
59 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
60 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
62 }, {
63 .ident = "MSI GX700",
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
66 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
67 DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
69 }, {
70 .ident = "MSI GX700/GX705/EX700",
71 .matches = {
72 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
73 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
75 }, {
76 .ident = "MSI L735",
77 .matches = {
78 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
79 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
81 }, {
82 .ident = "Lenovo Y300",
83 .matches = {
84 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
85 DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
88 { }
91 static struct v4l2_pix_format s5k4aa_modes[] = {
93 640,
94 480,
95 V4L2_PIX_FMT_SBGGR8,
96 V4L2_FIELD_NONE,
97 .sizeimage =
98 640 * 480,
99 .bytesperline = 640,
100 .colorspace = V4L2_COLORSPACE_SRGB,
101 .priv = 0
104 1280,
105 1024,
106 V4L2_PIX_FMT_SBGGR8,
107 V4L2_FIELD_NONE,
108 .sizeimage =
109 1280 * 1024,
110 .bytesperline = 1280,
111 .colorspace = V4L2_COLORSPACE_SRGB,
112 .priv = 0
116 static const struct ctrl s5k4aa_ctrls[] = {
117 #define VFLIP_IDX 0
120 .id = V4L2_CID_VFLIP,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
122 .name = "vertical flip",
123 .minimum = 0,
124 .maximum = 1,
125 .step = 1,
126 .default_value = 0
128 .set = s5k4aa_set_vflip,
129 .get = s5k4aa_get_vflip
131 #define HFLIP_IDX 1
134 .id = V4L2_CID_HFLIP,
135 .type = V4L2_CTRL_TYPE_BOOLEAN,
136 .name = "horizontal flip",
137 .minimum = 0,
138 .maximum = 1,
139 .step = 1,
140 .default_value = 0
142 .set = s5k4aa_set_hflip,
143 .get = s5k4aa_get_hflip
145 #define GAIN_IDX 2
148 .id = V4L2_CID_GAIN,
149 .type = V4L2_CTRL_TYPE_INTEGER,
150 .name = "Gain",
151 .minimum = 0,
152 .maximum = 127,
153 .step = 1,
154 .default_value = S5K4AA_DEFAULT_GAIN,
155 .flags = V4L2_CTRL_FLAG_SLIDER
157 .set = s5k4aa_set_gain,
158 .get = s5k4aa_get_gain
160 #define EXPOSURE_IDX 3
163 .id = V4L2_CID_EXPOSURE,
164 .type = V4L2_CTRL_TYPE_INTEGER,
165 .name = "Exposure",
166 .minimum = 13,
167 .maximum = 0xfff,
168 .step = 1,
169 .default_value = 0x100,
170 .flags = V4L2_CTRL_FLAG_SLIDER
172 .set = s5k4aa_set_exposure,
173 .get = s5k4aa_get_exposure
175 #define NOISE_SUPP_IDX 4
178 .id = V4L2_CID_PRIVATE_BASE,
179 .type = V4L2_CTRL_TYPE_BOOLEAN,
180 .name = "Noise suppression (smoothing)",
181 .minimum = 0,
182 .maximum = 1,
183 .step = 1,
184 .default_value = 1,
186 .set = s5k4aa_set_noise,
187 .get = s5k4aa_get_noise
189 #define BRIGHTNESS_IDX 5
192 .id = V4L2_CID_BRIGHTNESS,
193 .type = V4L2_CTRL_TYPE_INTEGER,
194 .name = "Brightness",
195 .minimum = 0,
196 .maximum = 0x1f,
197 .step = 1,
198 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
200 .set = s5k4aa_set_brightness,
201 .get = s5k4aa_get_brightness
206 static void s5k4aa_dump_registers(struct sd *sd);
208 int s5k4aa_probe(struct sd *sd)
210 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
211 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
212 int i, err = 0;
213 s32 *sensor_settings;
215 if (force_sensor) {
216 if (force_sensor == S5K4AA_SENSOR) {
217 info("Forcing a %s sensor", s5k4aa.name);
218 goto sensor_found;
220 /* If we want to force another sensor, don't try to probe this
221 * one */
222 return -ENODEV;
225 info("Probing for a s5k4aa sensor");
227 /* Preinit the sensor */
228 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
229 u8 data[2] = {0x00, 0x00};
231 switch (preinit_s5k4aa[i][0]) {
232 case BRIDGE:
233 err = m5602_write_bridge(sd,
234 preinit_s5k4aa[i][1],
235 preinit_s5k4aa[i][2]);
236 break;
238 case SENSOR:
239 data[0] = preinit_s5k4aa[i][2];
240 err = m5602_write_sensor(sd,
241 preinit_s5k4aa[i][1],
242 data, 1);
243 break;
245 case SENSOR_LONG:
246 data[0] = preinit_s5k4aa[i][2];
247 data[1] = preinit_s5k4aa[i][3];
248 err = m5602_write_sensor(sd,
249 preinit_s5k4aa[i][1],
250 data, 2);
251 break;
252 default:
253 info("Invalid stream command, exiting init");
254 return -EINVAL;
258 /* Test some registers, but we don't know their exact meaning yet */
259 if (m5602_read_sensor(sd, 0x00, prod_id, 2))
260 return -ENODEV;
261 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
262 return -ENODEV;
263 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
264 return -ENODEV;
266 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
267 return -ENODEV;
268 else
269 info("Detected a s5k4aa sensor");
271 sensor_found:
272 sensor_settings = kmalloc(
273 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
274 if (!sensor_settings)
275 return -ENOMEM;
277 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
278 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
279 sd->desc->ctrls = s5k4aa_ctrls;
280 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
282 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
283 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
284 sd->sensor_priv = sensor_settings;
286 return 0;
289 int s5k4aa_start(struct sd *sd)
291 int i, err = 0;
292 u8 data[2];
293 struct cam *cam = &sd->gspca_dev.cam;
294 s32 *sensor_settings = sd->sensor_priv;
296 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
297 case 1280:
298 PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
300 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
301 switch (SXGA_s5k4aa[i][0]) {
302 case BRIDGE:
303 err = m5602_write_bridge(sd,
304 SXGA_s5k4aa[i][1],
305 SXGA_s5k4aa[i][2]);
306 break;
308 case SENSOR:
309 data[0] = SXGA_s5k4aa[i][2];
310 err = m5602_write_sensor(sd,
311 SXGA_s5k4aa[i][1],
312 data, 1);
313 break;
315 case SENSOR_LONG:
316 data[0] = SXGA_s5k4aa[i][2];
317 data[1] = SXGA_s5k4aa[i][3];
318 err = m5602_write_sensor(sd,
319 SXGA_s5k4aa[i][1],
320 data, 2);
321 break;
323 default:
324 err("Invalid stream command, exiting init");
325 return -EINVAL;
328 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
329 if (err < 0)
330 return err;
331 break;
333 case 640:
334 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
336 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
337 switch (VGA_s5k4aa[i][0]) {
338 case BRIDGE:
339 err = m5602_write_bridge(sd,
340 VGA_s5k4aa[i][1],
341 VGA_s5k4aa[i][2]);
342 break;
344 case SENSOR:
345 data[0] = VGA_s5k4aa[i][2];
346 err = m5602_write_sensor(sd,
347 VGA_s5k4aa[i][1],
348 data, 1);
349 break;
351 case SENSOR_LONG:
352 data[0] = VGA_s5k4aa[i][2];
353 data[1] = VGA_s5k4aa[i][3];
354 err = m5602_write_sensor(sd,
355 VGA_s5k4aa[i][1],
356 data, 2);
357 break;
359 default:
360 err("Invalid stream command, exiting init");
361 return -EINVAL;
364 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
365 if (err < 0)
366 return err;
367 break;
369 if (err < 0)
370 return err;
372 err = s5k4aa_set_exposure(&sd->gspca_dev,
373 sensor_settings[EXPOSURE_IDX]);
374 if (err < 0)
375 return err;
377 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
378 if (err < 0)
379 return err;
381 err = s5k4aa_set_brightness(&sd->gspca_dev,
382 sensor_settings[BRIGHTNESS_IDX]);
383 if (err < 0)
384 return err;
386 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
387 if (err < 0)
388 return err;
390 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
391 if (err < 0)
392 return err;
394 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
397 int s5k4aa_init(struct sd *sd)
399 int i, err = 0;
401 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
402 u8 data[2] = {0x00, 0x00};
404 switch (init_s5k4aa[i][0]) {
405 case BRIDGE:
406 err = m5602_write_bridge(sd,
407 init_s5k4aa[i][1],
408 init_s5k4aa[i][2]);
409 break;
411 case SENSOR:
412 data[0] = init_s5k4aa[i][2];
413 err = m5602_write_sensor(sd,
414 init_s5k4aa[i][1], data, 1);
415 break;
417 case SENSOR_LONG:
418 data[0] = init_s5k4aa[i][2];
419 data[1] = init_s5k4aa[i][3];
420 err = m5602_write_sensor(sd,
421 init_s5k4aa[i][1], data, 2);
422 break;
423 default:
424 info("Invalid stream command, exiting init");
425 return -EINVAL;
429 if (dump_sensor)
430 s5k4aa_dump_registers(sd);
432 return err;
435 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
437 struct sd *sd = (struct sd *) gspca_dev;
438 s32 *sensor_settings = sd->sensor_priv;
440 *val = sensor_settings[EXPOSURE_IDX];
441 PDEBUG(D_V4L2, "Read exposure %d", *val);
443 return 0;
446 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
448 struct sd *sd = (struct sd *) gspca_dev;
449 s32 *sensor_settings = sd->sensor_priv;
450 u8 data = S5K4AA_PAGE_MAP_2;
451 int err;
453 sensor_settings[EXPOSURE_IDX] = val;
454 PDEBUG(D_V4L2, "Set exposure to %d", val);
455 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
456 if (err < 0)
457 return err;
458 data = (val >> 8) & 0xff;
459 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
460 if (err < 0)
461 return err;
462 data = val & 0xff;
463 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
465 return err;
468 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
470 struct sd *sd = (struct sd *) gspca_dev;
471 s32 *sensor_settings = sd->sensor_priv;
473 *val = sensor_settings[VFLIP_IDX];
474 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
476 return 0;
479 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
481 struct sd *sd = (struct sd *) gspca_dev;
482 s32 *sensor_settings = sd->sensor_priv;
483 u8 data = S5K4AA_PAGE_MAP_2;
484 int err;
486 sensor_settings[VFLIP_IDX] = val;
488 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
489 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
490 if (err < 0)
491 return err;
493 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
494 if (err < 0)
495 return err;
497 if (dmi_check_system(s5k4aa_vflip_dmi_table))
498 val = !val;
500 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
501 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
502 if (err < 0)
503 return err;
505 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
506 if (err < 0)
507 return err;
508 data = (data & 0xfe) | !val;
509 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
510 return err;
513 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
515 struct sd *sd = (struct sd *) gspca_dev;
516 s32 *sensor_settings = sd->sensor_priv;
518 *val = sensor_settings[HFLIP_IDX];
519 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
521 return 0;
524 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
526 struct sd *sd = (struct sd *) gspca_dev;
527 s32 *sensor_settings = sd->sensor_priv;
528 u8 data = S5K4AA_PAGE_MAP_2;
529 int err;
531 sensor_settings[HFLIP_IDX] = val;
533 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
534 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
535 if (err < 0)
536 return err;
538 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
539 if (err < 0)
540 return err;
542 if (dmi_check_system(s5k4aa_vflip_dmi_table))
543 val = !val;
545 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
546 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
547 if (err < 0)
548 return err;
550 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
551 if (err < 0)
552 return err;
553 data = (data & 0xfe) | !val;
554 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
555 return err;
558 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
560 struct sd *sd = (struct sd *) gspca_dev;
561 s32 *sensor_settings = sd->sensor_priv;
563 *val = sensor_settings[GAIN_IDX];
564 PDEBUG(D_V4L2, "Read gain %d", *val);
565 return 0;
568 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
570 struct sd *sd = (struct sd *) gspca_dev;
571 s32 *sensor_settings = sd->sensor_priv;
572 u8 data = S5K4AA_PAGE_MAP_2;
573 int err;
575 sensor_settings[GAIN_IDX] = val;
577 PDEBUG(D_V4L2, "Set gain to %d", val);
578 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
579 if (err < 0)
580 return err;
582 data = val & 0xff;
583 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
585 return err;
588 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
590 struct sd *sd = (struct sd *) gspca_dev;
591 s32 *sensor_settings = sd->sensor_priv;
593 *val = sensor_settings[BRIGHTNESS_IDX];
594 PDEBUG(D_V4L2, "Read brightness %d", *val);
595 return 0;
598 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
600 struct sd *sd = (struct sd *) gspca_dev;
601 s32 *sensor_settings = sd->sensor_priv;
602 u8 data = S5K4AA_PAGE_MAP_2;
603 int err;
605 sensor_settings[BRIGHTNESS_IDX] = val;
607 PDEBUG(D_V4L2, "Set brightness to %d", val);
608 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
609 if (err < 0)
610 return err;
612 data = val & 0xff;
613 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
616 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
618 struct sd *sd = (struct sd *) gspca_dev;
619 s32 *sensor_settings = sd->sensor_priv;
621 *val = sensor_settings[NOISE_SUPP_IDX];
622 PDEBUG(D_V4L2, "Read noise %d", *val);
623 return 0;
626 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
628 struct sd *sd = (struct sd *) gspca_dev;
629 s32 *sensor_settings = sd->sensor_priv;
630 u8 data = S5K4AA_PAGE_MAP_2;
631 int err;
633 sensor_settings[NOISE_SUPP_IDX] = val;
635 PDEBUG(D_V4L2, "Set noise to %d", val);
636 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
637 if (err < 0)
638 return err;
640 data = val & 0x01;
641 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
644 void s5k4aa_disconnect(struct sd *sd)
646 sd->sensor = NULL;
647 kfree(sd->sensor_priv);
650 static void s5k4aa_dump_registers(struct sd *sd)
652 int address;
653 u8 page, old_page;
654 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
655 for (page = 0; page < 16; page++) {
656 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
657 info("Dumping the s5k4aa register state for page 0x%x", page);
658 for (address = 0; address <= 0xff; address++) {
659 u8 value = 0;
660 m5602_read_sensor(sd, address, &value, 1);
661 info("register 0x%x contains 0x%x",
662 address, value);
665 info("s5k4aa register state dump complete");
667 for (page = 0; page < 16; page++) {
668 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
669 info("Probing for which registers that are "
670 "read/write for page 0x%x", page);
671 for (address = 0; address <= 0xff; address++) {
672 u8 old_value, ctrl_value, test_value = 0xff;
674 m5602_read_sensor(sd, address, &old_value, 1);
675 m5602_write_sensor(sd, address, &test_value, 1);
676 m5602_read_sensor(sd, address, &ctrl_value, 1);
678 if (ctrl_value == test_value)
679 info("register 0x%x is writeable", address);
680 else
681 info("register 0x%x is read only", address);
683 /* Restore original value */
684 m5602_write_sensor(sd, address, &old_value, 1);
687 info("Read/write register probing complete");
688 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);