]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/media/video/gspca/m5602/m5602_s5k83a.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / media / video / gspca / m5602 / m5602_s5k83a.c
CommitLineData
c109f816
EA
1/*
2 * Driver for the s5k83a 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
ac3d5bfe 19#include <linux/kthread.h>
5a0e3ad6 20#include <linux/slab.h>
c109f816
EA
21#include "m5602_s5k83a.h"
22
cf811d50
EA
23static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
24static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
25static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
26static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
27static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
28static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
29static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
31static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33
74cadfe1
EA
34static struct v4l2_pix_format s5k83a_modes[] = {
35 {
36 640,
37 480,
38 V4L2_PIX_FMT_SBGGR8,
39 V4L2_FIELD_NONE,
40 .sizeimage =
41 640 * 480,
42 .bytesperline = 640,
43 .colorspace = V4L2_COLORSPACE_SRGB,
44 .priv = 0
45 }
46};
47
2e03669d 48static const struct ctrl s5k83a_ctrls[] = {
ac3d5bfe 49#define GAIN_IDX 0
e17cc08c
EA
50 {
51 {
ac3d5bfe 52 .id = V4L2_CID_GAIN,
e17cc08c 53 .type = V4L2_CTRL_TYPE_INTEGER,
ac3d5bfe 54 .name = "gain",
e17cc08c
EA
55 .minimum = 0x00,
56 .maximum = 0xff,
57 .step = 0x01,
ac3d5bfe 58 .default_value = S5K83A_DEFAULT_GAIN,
e17cc08c
EA
59 .flags = V4L2_CTRL_FLAG_SLIDER
60 },
ac3d5bfe
LK
61 .set = s5k83a_set_gain,
62 .get = s5k83a_get_gain
e17cc08c 63
ac3d5bfe
LK
64 },
65#define BRIGHTNESS_IDX 1
66 {
e17cc08c 67 {
ac3d5bfe 68 .id = V4L2_CID_BRIGHTNESS,
e17cc08c 69 .type = V4L2_CTRL_TYPE_INTEGER,
ac3d5bfe 70 .name = "brightness",
e17cc08c
EA
71 .minimum = 0x00,
72 .maximum = 0xff,
73 .step = 0x01,
ac3d5bfe 74 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
e17cc08c
EA
75 .flags = V4L2_CTRL_FLAG_SLIDER
76 },
ac3d5bfe
LK
77 .set = s5k83a_set_brightness,
78 .get = s5k83a_get_brightness,
79 },
80#define EXPOSURE_IDX 2
81 {
e17cc08c 82 {
ac3d5bfe 83 .id = V4L2_CID_EXPOSURE,
e17cc08c 84 .type = V4L2_CTRL_TYPE_INTEGER,
ac3d5bfe 85 .name = "exposure",
e17cc08c 86 .minimum = 0x00,
ac3d5bfe 87 .maximum = S5K83A_MAXIMUM_EXPOSURE,
e17cc08c 88 .step = 0x01,
ac3d5bfe 89 .default_value = S5K83A_DEFAULT_EXPOSURE,
e17cc08c
EA
90 .flags = V4L2_CTRL_FLAG_SLIDER
91 },
ac3d5bfe
LK
92 .set = s5k83a_set_exposure,
93 .get = s5k83a_get_exposure
94 },
95#define HFLIP_IDX 3
96 {
e17cc08c 97 {
00e02567
EA
98 .id = V4L2_CID_HFLIP,
99 .type = V4L2_CTRL_TYPE_BOOLEAN,
100 .name = "horizontal flip",
101 .minimum = 0,
102 .maximum = 1,
103 .step = 1,
104 .default_value = 0
e17cc08c
EA
105 },
106 .set = s5k83a_set_hflip,
107 .get = s5k83a_get_hflip
ac3d5bfe
LK
108 },
109#define VFLIP_IDX 4
110 {
e17cc08c 111 {
00e02567
EA
112 .id = V4L2_CID_VFLIP,
113 .type = V4L2_CTRL_TYPE_BOOLEAN,
114 .name = "vertical flip",
115 .minimum = 0,
116 .maximum = 1,
117 .step = 1,
118 .default_value = 0
e17cc08c
EA
119 },
120 .set = s5k83a_set_vflip,
121 .get = s5k83a_get_vflip
122 }
123};
124
658efb63 125static void s5k83a_dump_registers(struct sd *sd);
ac3d5bfe
LK
126static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
127static int s5k83a_set_led_indication(struct sd *sd, u8 val);
57851d0c
EA
128static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
129 __s32 vflip, __s32 hflip);
658efb63 130
c109f816
EA
131int s5k83a_probe(struct sd *sd)
132{
ac3d5bfe 133 struct s5k83a_priv *sens_priv;
c109f816
EA
134 u8 prod_id = 0, ver_id = 0;
135 int i, err = 0;
136
137 if (force_sensor) {
138 if (force_sensor == S5K83A_SENSOR) {
139 info("Forcing a %s sensor", s5k83a.name);
140 goto sensor_found;
141 }
142 /* If we want to force another sensor, don't try to probe this
143 * one */
144 return -ENODEV;
145 }
146
969cc926 147 PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
c109f816
EA
148
149 /* Preinit the sensor */
150 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
151 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
152 if (preinit_s5k83a[i][0] == SENSOR)
6dc4cff0 153 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
c109f816
EA
154 data, 2);
155 else
156 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
157 data[0]);
158 }
159
160 /* We don't know what register (if any) that contain the product id
161 * Just pick the first addresses that seem to produce the same results
162 * on multiple machines */
6b9c0a2a 163 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
c109f816
EA
164 return -ENODEV;
165
6b9c0a2a 166 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
c109f816
EA
167 return -ENODEV;
168
169 if ((prod_id == 0xff) || (ver_id == 0xff))
170 return -ENODEV;
171 else
172 info("Detected a s5k83a sensor");
173
174sensor_found:
ac3d5bfe
LK
175 sens_priv = kmalloc(
176 sizeof(struct s5k83a_priv), GFP_KERNEL);
177 if (!sens_priv)
178 return -ENOMEM;
179
180 sens_priv->settings =
181 kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
b807d175
JL
182 if (!sens_priv->settings) {
183 kfree(sens_priv);
ac3d5bfe 184 return -ENOMEM;
b807d175 185 }
ac3d5bfe 186
74cadfe1
EA
187 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
188 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
e17cc08c 189 sd->desc->ctrls = s5k83a_ctrls;
e4cc4fcc 190 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
ac3d5bfe
LK
191
192 /* null the pointer! thread is't running now */
193 sens_priv->rotation_thread = NULL;
194
195 for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
196 sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
197
198 sd->sensor_priv = sens_priv;
c109f816
EA
199 return 0;
200}
201
c109f816
EA
202int s5k83a_init(struct sd *sd)
203{
204 int i, err = 0;
c41507ba
LK
205 s32 *sensor_settings =
206 ((struct s5k83a_priv *) sd->sensor_priv)->settings;
c109f816
EA
207
208 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
209 u8 data[2] = {0x00, 0x00};
210
211 switch (init_s5k83a[i][0]) {
212 case BRIDGE:
213 err = m5602_write_bridge(sd,
214 init_s5k83a[i][1],
215 init_s5k83a[i][2]);
216 break;
217
218 case SENSOR:
219 data[0] = init_s5k83a[i][2];
6dc4cff0 220 err = m5602_write_sensor(sd,
c109f816
EA
221 init_s5k83a[i][1], data, 1);
222 break;
223
224 case SENSOR_LONG:
225 data[0] = init_s5k83a[i][2];
226 data[1] = init_s5k83a[i][3];
6dc4cff0 227 err = m5602_write_sensor(sd,
c109f816
EA
228 init_s5k83a[i][1], data, 2);
229 break;
230 default:
231 info("Invalid stream command, exiting init");
232 return -EINVAL;
233 }
234 }
235
236 if (dump_sensor)
237 s5k83a_dump_registers(sd);
238
57851d0c
EA
239 err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
240 if (err < 0)
241 return err;
242
243 err = s5k83a_set_brightness(&sd->gspca_dev,
244 sensor_settings[BRIGHTNESS_IDX]);
245 if (err < 0)
246 return err;
247
248 err = s5k83a_set_exposure(&sd->gspca_dev,
249 sensor_settings[EXPOSURE_IDX]);
250 if (err < 0)
251 return err;
252
253 err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
254 if (err < 0)
255 return err;
256
257 err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
258
259 return err;
c109f816
EA
260}
261
ac3d5bfe
LK
262static int rotation_thread_function(void *data)
263{
264 struct sd *sd = (struct sd *) data;
265 struct s5k83a_priv *sens_priv = sd->sensor_priv;
266 u8 reg, previous_rotation = 0;
267 __s32 vflip, hflip;
268
269 set_current_state(TASK_INTERRUPTIBLE);
270 while (!schedule_timeout(100)) {
271 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
272 break;
273
274 s5k83a_get_rotation(sd, &reg);
275 if (previous_rotation != reg) {
276 previous_rotation = reg;
277 info("Camera was flipped");
278
279 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
280 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
281
282 if (reg) {
283 vflip = !vflip;
284 hflip = !hflip;
285 }
1b844b53
EA
286 s5k83a_set_flip_real((struct gspca_dev *) sd,
287 vflip, hflip);
ac3d5bfe
LK
288 }
289
290 mutex_unlock(&sd->gspca_dev.usb_lock);
291 set_current_state(TASK_INTERRUPTIBLE);
292 }
293
294 /* return to "front" flip */
295 if (previous_rotation) {
296 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
297 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
298 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
299 }
300
301 sens_priv->rotation_thread = NULL;
302 return 0;
303}
304
4a7581f0
LK
305int s5k83a_start(struct sd *sd)
306{
cde41bb2 307 int i, err = 0;
ac3d5bfe
LK
308 struct s5k83a_priv *sens_priv = sd->sensor_priv;
309
310 /* Create another thread, polling the GPIO ports of the camera to check
311 if it got rotated. This is how the windows driver does it so we have
312 to assume that there is no better way of accomplishing this */
57851d0c 313 sens_priv->rotation_thread = kthread_create(rotation_thread_function,
cde41bb2 314 sd, "rotation thread");
ac3d5bfe
LK
315 wake_up_process(sens_priv->rotation_thread);
316
cde41bb2
EA
317 /* Preinit the sensor */
318 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
319 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
320 if (start_s5k83a[i][0] == SENSOR)
321 err = m5602_write_sensor(sd, start_s5k83a[i][1],
322 data, 2);
323 else
324 err = m5602_write_bridge(sd, start_s5k83a[i][1],
325 data[0]);
326 }
327 if (err < 0)
328 return err;
329
4a7581f0
LK
330 return s5k83a_set_led_indication(sd, 1);
331}
332
333int s5k83a_stop(struct sd *sd)
334{
ac3d5bfe
LK
335 struct s5k83a_priv *sens_priv = sd->sensor_priv;
336
337 if (sens_priv->rotation_thread)
338 kthread_stop(sens_priv->rotation_thread);
339
4a7581f0
LK
340 return s5k83a_set_led_indication(sd, 0);
341}
342
ac3d5bfe 343void s5k83a_disconnect(struct sd *sd)
c109f816 344{
ac3d5bfe 345 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 346
ac3d5bfe 347 s5k83a_stop(sd);
c109f816 348
ac3d5bfe
LK
349 sd->sensor = NULL;
350 kfree(sens_priv->settings);
351 kfree(sens_priv);
352}
c109f816 353
cf811d50 354static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
c109f816 355{
c109f816 356 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 357 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 358
ac3d5bfe
LK
359 *val = sens_priv->settings[GAIN_IDX];
360 return 0;
c109f816
EA
361}
362
cf811d50 363static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
364{
365 int err;
366 u8 data[2];
367 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe
LK
368 struct s5k83a_priv *sens_priv = sd->sensor_priv;
369
370 sens_priv->settings[GAIN_IDX] = val;
c109f816
EA
371
372 data[0] = 0x00;
373 data[1] = 0x20;
6dc4cff0 374 err = m5602_write_sensor(sd, 0x14, data, 2);
c109f816 375 if (err < 0)
051781b3 376 return err;
c109f816
EA
377
378 data[0] = 0x01;
379 data[1] = 0x00;
6dc4cff0 380 err = m5602_write_sensor(sd, 0x0d, data, 2);
c109f816 381 if (err < 0)
051781b3 382 return err;
c109f816
EA
383
384 /* FIXME: This is not sane, we need to figure out the composition
385 of these registers */
ac3d5bfe
LK
386 data[0] = val >> 3; /* gain, high 5 bits */
387 data[1] = val >> 1; /* gain, high 7 bits */
388 err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
c109f816 389
7b2cd079 390 return err;
c109f816
EA
391}
392
cf811d50 393static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
c109f816 394{
c109f816 395 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 396 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 397
ac3d5bfe
LK
398 *val = sens_priv->settings[BRIGHTNESS_IDX];
399 return 0;
c109f816
EA
400}
401
cf811d50 402static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
c109f816
EA
403{
404 int err;
405 u8 data[1];
406 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 407 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 408
ac3d5bfe 409 sens_priv->settings[BRIGHTNESS_IDX] = val;
c109f816 410 data[0] = val;
ac3d5bfe 411 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
7b2cd079 412 return err;
c109f816
EA
413}
414
cf811d50 415static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
c109f816 416{
c109f816 417 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 418 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 419
ac3d5bfe
LK
420 *val = sens_priv->settings[EXPOSURE_IDX];
421 return 0;
c109f816
EA
422}
423
cf811d50 424static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
c109f816 425{
18f8fae1 426 int err;
c109f816
EA
427 u8 data[2];
428 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 429 struct s5k83a_priv *sens_priv = sd->sensor_priv;
c109f816 430
ac3d5bfe 431 sens_priv->settings[EXPOSURE_IDX] = val;
c109f816
EA
432 data[0] = 0;
433 data[1] = val;
ac3d5bfe 434 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
7b2cd079 435 return err;
c109f816 436}
18f8fae1 437
cf811d50 438static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
18f8fae1 439{
18f8fae1 440 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 441 struct s5k83a_priv *sens_priv = sd->sensor_priv;
18f8fae1 442
ac3d5bfe
LK
443 *val = sens_priv->settings[VFLIP_IDX];
444 return 0;
18f8fae1
EA
445}
446
57851d0c
EA
447static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
448 __s32 vflip, __s32 hflip)
18f8fae1
EA
449{
450 int err;
451 u8 data[1];
452 struct sd *sd = (struct sd *) gspca_dev;
453
454 data[0] = 0x05;
6dc4cff0 455 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
18f8fae1 456 if (err < 0)
051781b3 457 return err;
18f8fae1 458
ac3d5bfe
LK
459 /* six bit is vflip, seven is hflip */
460 data[0] = S5K83A_FLIP_MASK;
461 data[0] = (vflip) ? data[0] | 0x40 : data[0];
462 data[0] = (hflip) ? data[0] | 0x80 : data[0];
18f8fae1 463
6dc4cff0 464 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
18f8fae1 465 if (err < 0)
051781b3 466 return err;
18f8fae1 467
ac3d5bfe 468 data[0] = (vflip) ? 0x0b : 0x0a;
6dc4cff0 469 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
ac3d5bfe
LK
470 if (err < 0)
471 return err;
18f8fae1 472
ac3d5bfe
LK
473 data[0] = (hflip) ? 0x0a : 0x0b;
474 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
7b2cd079 475 return err;
18f8fae1
EA
476}
477
cf811d50 478static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
18f8fae1
EA
479{
480 int err;
ac3d5bfe
LK
481 u8 reg;
482 __s32 hflip;
18f8fae1 483 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 484 struct s5k83a_priv *sens_priv = sd->sensor_priv;
18f8fae1 485
ac3d5bfe
LK
486 sens_priv->settings[VFLIP_IDX] = val;
487
488 s5k83a_get_hflip(gspca_dev, &hflip);
489
490 err = s5k83a_get_rotation(sd, &reg);
18f8fae1 491 if (err < 0)
051781b3 492 return err;
ac3d5bfe
LK
493 if (reg) {
494 val = !val;
495 hflip = !hflip;
496 }
18f8fae1 497
ac3d5bfe 498 err = s5k83a_set_flip_real(gspca_dev, val, hflip);
7b2cd079 499 return err;
18f8fae1
EA
500}
501
cf811d50 502static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
ac3d5bfe
LK
503{
504 struct sd *sd = (struct sd *) gspca_dev;
505 struct s5k83a_priv *sens_priv = sd->sensor_priv;
506
507 *val = sens_priv->settings[HFLIP_IDX];
508 return 0;
509}
510
cf811d50 511static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
18f8fae1
EA
512{
513 int err;
ac3d5bfe
LK
514 u8 reg;
515 __s32 vflip;
18f8fae1 516 struct sd *sd = (struct sd *) gspca_dev;
ac3d5bfe 517 struct s5k83a_priv *sens_priv = sd->sensor_priv;
18f8fae1 518
ac3d5bfe 519 sens_priv->settings[HFLIP_IDX] = val;
18f8fae1 520
ac3d5bfe 521 s5k83a_get_vflip(gspca_dev, &vflip);
18f8fae1 522
ac3d5bfe 523 err = s5k83a_get_rotation(sd, &reg);
18f8fae1 524 if (err < 0)
051781b3 525 return err;
ac3d5bfe
LK
526 if (reg) {
527 val = !val;
528 vflip = !vflip;
529 }
18f8fae1 530
ac3d5bfe 531 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
7b2cd079 532 return err;
18f8fae1 533}
4a7581f0 534
ac3d5bfe 535static int s5k83a_set_led_indication(struct sd *sd, u8 val)
4a7581f0
LK
536{
537 int err = 0;
538 u8 data[1];
539
540 err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
541 if (err < 0)
542 return err;
543
544 if (val)
545 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
546 else
547 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
548
549 err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
550
57851d0c 551 return err;
4a7581f0 552}
ac3d5bfe
LK
553
554/* Get camera rotation on Acer notebooks */
555static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
556{
557 int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
558 *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
559 return err;
560}
561
562static void s5k83a_dump_registers(struct sd *sd)
563{
564 int address;
565 u8 page, old_page;
566 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
567
568 for (page = 0; page < 16; page++) {
569 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
570 info("Dumping the s5k83a register state for page 0x%x", page);
571 for (address = 0; address <= 0xff; address++) {
572 u8 val = 0;
573 m5602_read_sensor(sd, address, &val, 1);
574 info("register 0x%x contains 0x%x",
575 address, val);
576 }
577 }
578 info("s5k83a register state dump complete");
579
580 for (page = 0; page < 16; page++) {
581 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
582 info("Probing for which registers that are read/write "
583 "for page 0x%x", page);
584 for (address = 0; address <= 0xff; address++) {
585 u8 old_val, ctrl_val, test_val = 0xff;
586
587 m5602_read_sensor(sd, address, &old_val, 1);
588 m5602_write_sensor(sd, address, &test_val, 1);
589 m5602_read_sensor(sd, address, &ctrl_val, 1);
590
591 if (ctrl_val == test_val)
592 info("register 0x%x is writeable", address);
593 else
594 info("register 0x%x is read only", address);
595
596 /* Restore original val */
597 m5602_write_sensor(sd, address, &old_val, 1);
598 }
599 }
600 info("Read/write register probing complete");
601 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
602}