Linux 2.6.34-rc3
[pohmelfs.git] / drivers / media / video / gspca / m5602 / m5602_s5k4aa.c
blobda0a38c78708b6b7e78cd2923ab43f72c069c59a
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 = "BRUNEINIT",
39 .matches = {
40 DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
41 DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
42 DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
44 }, {
45 .ident = "Fujitsu-Siemens Amilo Xa 2528",
46 .matches = {
47 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
48 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
50 }, {
51 .ident = "Fujitsu-Siemens Amilo Xi 2428",
52 .matches = {
53 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
54 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
56 }, {
57 .ident = "Fujitsu-Siemens Amilo Xi 2528",
58 .matches = {
59 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
60 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
62 }, {
63 .ident = "Fujitsu-Siemens Amilo Xi 2550",
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
66 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
68 }, {
69 .ident = "Fujitsu-Siemens Amilo Pa 2548",
70 .matches = {
71 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
72 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
74 }, {
75 .ident = "MSI GX700",
76 .matches = {
77 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
78 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
79 DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
81 }, {
82 .ident = "MSI GX700",
83 .matches = {
84 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
85 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
86 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
88 }, {
89 .ident = "MSI GX700",
90 .matches = {
91 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
92 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
93 DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
95 }, {
96 .ident = "MSI GX700/GX705/EX700",
97 .matches = {
98 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
99 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
101 }, {
102 .ident = "MSI L735",
103 .matches = {
104 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
105 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
107 }, {
108 .ident = "Lenovo Y300",
109 .matches = {
110 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
111 DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
117 static struct v4l2_pix_format s5k4aa_modes[] = {
119 640,
120 480,
121 V4L2_PIX_FMT_SBGGR8,
122 V4L2_FIELD_NONE,
123 .sizeimage =
124 640 * 480,
125 .bytesperline = 640,
126 .colorspace = V4L2_COLORSPACE_SRGB,
127 .priv = 0
130 1280,
131 1024,
132 V4L2_PIX_FMT_SBGGR8,
133 V4L2_FIELD_NONE,
134 .sizeimage =
135 1280 * 1024,
136 .bytesperline = 1280,
137 .colorspace = V4L2_COLORSPACE_SRGB,
138 .priv = 0
142 static const struct ctrl s5k4aa_ctrls[] = {
143 #define VFLIP_IDX 0
146 .id = V4L2_CID_VFLIP,
147 .type = V4L2_CTRL_TYPE_BOOLEAN,
148 .name = "vertical flip",
149 .minimum = 0,
150 .maximum = 1,
151 .step = 1,
152 .default_value = 0
154 .set = s5k4aa_set_vflip,
155 .get = s5k4aa_get_vflip
157 #define HFLIP_IDX 1
160 .id = V4L2_CID_HFLIP,
161 .type = V4L2_CTRL_TYPE_BOOLEAN,
162 .name = "horizontal flip",
163 .minimum = 0,
164 .maximum = 1,
165 .step = 1,
166 .default_value = 0
168 .set = s5k4aa_set_hflip,
169 .get = s5k4aa_get_hflip
171 #define GAIN_IDX 2
174 .id = V4L2_CID_GAIN,
175 .type = V4L2_CTRL_TYPE_INTEGER,
176 .name = "Gain",
177 .minimum = 0,
178 .maximum = 127,
179 .step = 1,
180 .default_value = S5K4AA_DEFAULT_GAIN,
181 .flags = V4L2_CTRL_FLAG_SLIDER
183 .set = s5k4aa_set_gain,
184 .get = s5k4aa_get_gain
186 #define EXPOSURE_IDX 3
189 .id = V4L2_CID_EXPOSURE,
190 .type = V4L2_CTRL_TYPE_INTEGER,
191 .name = "Exposure",
192 .minimum = 13,
193 .maximum = 0xfff,
194 .step = 1,
195 .default_value = 0x100,
196 .flags = V4L2_CTRL_FLAG_SLIDER
198 .set = s5k4aa_set_exposure,
199 .get = s5k4aa_get_exposure
201 #define NOISE_SUPP_IDX 4
204 .id = V4L2_CID_PRIVATE_BASE,
205 .type = V4L2_CTRL_TYPE_BOOLEAN,
206 .name = "Noise suppression (smoothing)",
207 .minimum = 0,
208 .maximum = 1,
209 .step = 1,
210 .default_value = 1,
212 .set = s5k4aa_set_noise,
213 .get = s5k4aa_get_noise
215 #define BRIGHTNESS_IDX 5
218 .id = V4L2_CID_BRIGHTNESS,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "Brightness",
221 .minimum = 0,
222 .maximum = 0x1f,
223 .step = 1,
224 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
226 .set = s5k4aa_set_brightness,
227 .get = s5k4aa_get_brightness
232 static void s5k4aa_dump_registers(struct sd *sd);
234 int s5k4aa_probe(struct sd *sd)
236 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
237 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
238 int i, err = 0;
239 s32 *sensor_settings;
241 if (force_sensor) {
242 if (force_sensor == S5K4AA_SENSOR) {
243 info("Forcing a %s sensor", s5k4aa.name);
244 goto sensor_found;
246 /* If we want to force another sensor, don't try to probe this
247 * one */
248 return -ENODEV;
251 PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
253 /* Preinit the sensor */
254 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
255 u8 data[2] = {0x00, 0x00};
257 switch (preinit_s5k4aa[i][0]) {
258 case BRIDGE:
259 err = m5602_write_bridge(sd,
260 preinit_s5k4aa[i][1],
261 preinit_s5k4aa[i][2]);
262 break;
264 case SENSOR:
265 data[0] = preinit_s5k4aa[i][2];
266 err = m5602_write_sensor(sd,
267 preinit_s5k4aa[i][1],
268 data, 1);
269 break;
271 case SENSOR_LONG:
272 data[0] = preinit_s5k4aa[i][2];
273 data[1] = preinit_s5k4aa[i][3];
274 err = m5602_write_sensor(sd,
275 preinit_s5k4aa[i][1],
276 data, 2);
277 break;
278 default:
279 info("Invalid stream command, exiting init");
280 return -EINVAL;
284 /* Test some registers, but we don't know their exact meaning yet */
285 if (m5602_read_sensor(sd, 0x00, prod_id, 2))
286 return -ENODEV;
287 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
288 return -ENODEV;
289 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
290 return -ENODEV;
292 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
293 return -ENODEV;
294 else
295 info("Detected a s5k4aa sensor");
297 sensor_found:
298 sensor_settings = kmalloc(
299 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
300 if (!sensor_settings)
301 return -ENOMEM;
303 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
304 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
305 sd->desc->ctrls = s5k4aa_ctrls;
306 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
308 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
309 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
310 sd->sensor_priv = sensor_settings;
312 return 0;
315 int s5k4aa_start(struct sd *sd)
317 int i, err = 0;
318 u8 data[2];
319 struct cam *cam = &sd->gspca_dev.cam;
320 s32 *sensor_settings = sd->sensor_priv;
322 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
323 case 1280:
324 PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
326 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
327 switch (SXGA_s5k4aa[i][0]) {
328 case BRIDGE:
329 err = m5602_write_bridge(sd,
330 SXGA_s5k4aa[i][1],
331 SXGA_s5k4aa[i][2]);
332 break;
334 case SENSOR:
335 data[0] = SXGA_s5k4aa[i][2];
336 err = m5602_write_sensor(sd,
337 SXGA_s5k4aa[i][1],
338 data, 1);
339 break;
341 case SENSOR_LONG:
342 data[0] = SXGA_s5k4aa[i][2];
343 data[1] = SXGA_s5k4aa[i][3];
344 err = m5602_write_sensor(sd,
345 SXGA_s5k4aa[i][1],
346 data, 2);
347 break;
349 default:
350 err("Invalid stream command, exiting init");
351 return -EINVAL;
354 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
355 if (err < 0)
356 return err;
357 break;
359 case 640:
360 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
362 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
363 switch (VGA_s5k4aa[i][0]) {
364 case BRIDGE:
365 err = m5602_write_bridge(sd,
366 VGA_s5k4aa[i][1],
367 VGA_s5k4aa[i][2]);
368 break;
370 case SENSOR:
371 data[0] = VGA_s5k4aa[i][2];
372 err = m5602_write_sensor(sd,
373 VGA_s5k4aa[i][1],
374 data, 1);
375 break;
377 case SENSOR_LONG:
378 data[0] = VGA_s5k4aa[i][2];
379 data[1] = VGA_s5k4aa[i][3];
380 err = m5602_write_sensor(sd,
381 VGA_s5k4aa[i][1],
382 data, 2);
383 break;
385 default:
386 err("Invalid stream command, exiting init");
387 return -EINVAL;
390 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
391 if (err < 0)
392 return err;
393 break;
395 if (err < 0)
396 return err;
398 err = s5k4aa_set_exposure(&sd->gspca_dev,
399 sensor_settings[EXPOSURE_IDX]);
400 if (err < 0)
401 return err;
403 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
404 if (err < 0)
405 return err;
407 err = s5k4aa_set_brightness(&sd->gspca_dev,
408 sensor_settings[BRIGHTNESS_IDX]);
409 if (err < 0)
410 return err;
412 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
413 if (err < 0)
414 return err;
416 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
417 if (err < 0)
418 return err;
420 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
423 int s5k4aa_init(struct sd *sd)
425 int i, err = 0;
427 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
428 u8 data[2] = {0x00, 0x00};
430 switch (init_s5k4aa[i][0]) {
431 case BRIDGE:
432 err = m5602_write_bridge(sd,
433 init_s5k4aa[i][1],
434 init_s5k4aa[i][2]);
435 break;
437 case SENSOR:
438 data[0] = init_s5k4aa[i][2];
439 err = m5602_write_sensor(sd,
440 init_s5k4aa[i][1], data, 1);
441 break;
443 case SENSOR_LONG:
444 data[0] = init_s5k4aa[i][2];
445 data[1] = init_s5k4aa[i][3];
446 err = m5602_write_sensor(sd,
447 init_s5k4aa[i][1], data, 2);
448 break;
449 default:
450 info("Invalid stream command, exiting init");
451 return -EINVAL;
455 if (dump_sensor)
456 s5k4aa_dump_registers(sd);
458 return err;
461 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
463 struct sd *sd = (struct sd *) gspca_dev;
464 s32 *sensor_settings = sd->sensor_priv;
466 *val = sensor_settings[EXPOSURE_IDX];
467 PDEBUG(D_V4L2, "Read exposure %d", *val);
469 return 0;
472 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
474 struct sd *sd = (struct sd *) gspca_dev;
475 s32 *sensor_settings = sd->sensor_priv;
476 u8 data = S5K4AA_PAGE_MAP_2;
477 int err;
479 sensor_settings[EXPOSURE_IDX] = val;
480 PDEBUG(D_V4L2, "Set exposure to %d", val);
481 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
482 if (err < 0)
483 return err;
484 data = (val >> 8) & 0xff;
485 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
486 if (err < 0)
487 return err;
488 data = val & 0xff;
489 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
491 return err;
494 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
496 struct sd *sd = (struct sd *) gspca_dev;
497 s32 *sensor_settings = sd->sensor_priv;
499 *val = sensor_settings[VFLIP_IDX];
500 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
502 return 0;
505 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
507 struct sd *sd = (struct sd *) gspca_dev;
508 s32 *sensor_settings = sd->sensor_priv;
509 u8 data = S5K4AA_PAGE_MAP_2;
510 int err;
512 sensor_settings[VFLIP_IDX] = val;
514 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
515 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
516 if (err < 0)
517 return err;
519 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
520 if (err < 0)
521 return err;
523 if (dmi_check_system(s5k4aa_vflip_dmi_table))
524 val = !val;
526 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
527 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
528 if (err < 0)
529 return err;
531 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
532 if (err < 0)
533 return err;
534 if (val)
535 data &= 0xfe;
536 else
537 data |= 0x01;
538 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
539 return err;
542 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
544 struct sd *sd = (struct sd *) gspca_dev;
545 s32 *sensor_settings = sd->sensor_priv;
547 *val = sensor_settings[HFLIP_IDX];
548 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
550 return 0;
553 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
555 struct sd *sd = (struct sd *) gspca_dev;
556 s32 *sensor_settings = sd->sensor_priv;
557 u8 data = S5K4AA_PAGE_MAP_2;
558 int err;
560 sensor_settings[HFLIP_IDX] = val;
562 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
563 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
564 if (err < 0)
565 return err;
567 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
568 if (err < 0)
569 return err;
571 if (dmi_check_system(s5k4aa_vflip_dmi_table))
572 val = !val;
574 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
575 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
576 if (err < 0)
577 return err;
579 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
580 if (err < 0)
581 return err;
582 if (val)
583 data &= 0xfe;
584 else
585 data |= 0x01;
586 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
587 return err;
590 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
592 struct sd *sd = (struct sd *) gspca_dev;
593 s32 *sensor_settings = sd->sensor_priv;
595 *val = sensor_settings[GAIN_IDX];
596 PDEBUG(D_V4L2, "Read gain %d", *val);
597 return 0;
600 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
602 struct sd *sd = (struct sd *) gspca_dev;
603 s32 *sensor_settings = sd->sensor_priv;
604 u8 data = S5K4AA_PAGE_MAP_2;
605 int err;
607 sensor_settings[GAIN_IDX] = val;
609 PDEBUG(D_V4L2, "Set gain to %d", val);
610 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
611 if (err < 0)
612 return err;
614 data = val & 0xff;
615 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
617 return err;
620 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
622 struct sd *sd = (struct sd *) gspca_dev;
623 s32 *sensor_settings = sd->sensor_priv;
625 *val = sensor_settings[BRIGHTNESS_IDX];
626 PDEBUG(D_V4L2, "Read brightness %d", *val);
627 return 0;
630 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
632 struct sd *sd = (struct sd *) gspca_dev;
633 s32 *sensor_settings = sd->sensor_priv;
634 u8 data = S5K4AA_PAGE_MAP_2;
635 int err;
637 sensor_settings[BRIGHTNESS_IDX] = val;
639 PDEBUG(D_V4L2, "Set brightness to %d", val);
640 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
641 if (err < 0)
642 return err;
644 data = val & 0xff;
645 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
648 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
650 struct sd *sd = (struct sd *) gspca_dev;
651 s32 *sensor_settings = sd->sensor_priv;
653 *val = sensor_settings[NOISE_SUPP_IDX];
654 PDEBUG(D_V4L2, "Read noise %d", *val);
655 return 0;
658 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
660 struct sd *sd = (struct sd *) gspca_dev;
661 s32 *sensor_settings = sd->sensor_priv;
662 u8 data = S5K4AA_PAGE_MAP_2;
663 int err;
665 sensor_settings[NOISE_SUPP_IDX] = val;
667 PDEBUG(D_V4L2, "Set noise to %d", val);
668 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
669 if (err < 0)
670 return err;
672 data = val & 0x01;
673 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
676 void s5k4aa_disconnect(struct sd *sd)
678 sd->sensor = NULL;
679 kfree(sd->sensor_priv);
682 static void s5k4aa_dump_registers(struct sd *sd)
684 int address;
685 u8 page, old_page;
686 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
687 for (page = 0; page < 16; page++) {
688 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
689 info("Dumping the s5k4aa register state for page 0x%x", page);
690 for (address = 0; address <= 0xff; address++) {
691 u8 value = 0;
692 m5602_read_sensor(sd, address, &value, 1);
693 info("register 0x%x contains 0x%x",
694 address, value);
697 info("s5k4aa register state dump complete");
699 for (page = 0; page < 16; page++) {
700 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
701 info("Probing for which registers that are "
702 "read/write for page 0x%x", page);
703 for (address = 0; address <= 0xff; address++) {
704 u8 old_value, ctrl_value, test_value = 0xff;
706 m5602_read_sensor(sd, address, &old_value, 1);
707 m5602_write_sensor(sd, address, &test_value, 1);
708 m5602_read_sensor(sd, address, &ctrl_value, 1);
710 if (ctrl_value == test_value)
711 info("register 0x%x is writeable", address);
712 else
713 info("register 0x%x is read only", address);
715 /* Restore original value */
716 m5602_write_sensor(sd, address, &old_value, 1);
719 info("Read/write register probing complete");
720 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);