GNU Linux-libre 4.9-gnu1
[releases.git] / drivers / media / usb / gspca / m5602 / m5602_s5k83a.c
1 /*
2  * Driver for the s5k83a sensor
3  *
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>
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21 #include <linux/kthread.h>
22 #include "m5602_s5k83a.h"
23
24 static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
25
26 static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
27         .s_ctrl = s5k83a_s_ctrl,
28 };
29
30 static struct v4l2_pix_format s5k83a_modes[] = {
31         {
32                 640,
33                 480,
34                 V4L2_PIX_FMT_SBGGR8,
35                 V4L2_FIELD_NONE,
36                 .sizeimage =
37                         640 * 480,
38                 .bytesperline = 640,
39                 .colorspace = V4L2_COLORSPACE_SRGB,
40                 .priv = 0
41         }
42 };
43
44 static const unsigned char preinit_s5k83a[][4] = {
45         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
46         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
47         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
48         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
49         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
50         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
51         {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
52
53         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
54         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
55         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
56         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
57         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
58         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
59         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
60         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
61         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
62         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
63         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
64         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
65         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
66         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
67         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
68         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
69         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
70         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
71         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
72         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
73         {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
74         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
75         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
76         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
77         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
78         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
79 };
80
81 /* This could probably be considerably shortened.
82    I don't have the hardware to experiment with it, patches welcome
83 */
84 static const unsigned char init_s5k83a[][4] = {
85         /* The following sequence is useless after a clean boot
86            but is necessary after resume from suspend */
87         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
88         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
89         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
90         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
91         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
92         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
93         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
94         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
95         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
96         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
97         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
98         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
99         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
100         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
101         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
102         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
103         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
104         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
105         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
106         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
107         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
108         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
109         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
110         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
111         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
112
113         {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
114         {SENSOR, 0xaf, 0x01, 0x00},
115         {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
116         {SENSOR, 0x7b, 0xff, 0x00},
117         {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
118         {SENSOR, 0x01, 0x50, 0x00},
119         {SENSOR, 0x12, 0x20, 0x00},
120         {SENSOR, 0x17, 0x40, 0x00},
121         {SENSOR, 0x1c, 0x00, 0x00},
122         {SENSOR, 0x02, 0x70, 0x00},
123         {SENSOR, 0x03, 0x0b, 0x00},
124         {SENSOR, 0x04, 0xf0, 0x00},
125         {SENSOR, 0x05, 0x0b, 0x00},
126         {SENSOR, 0x06, 0x71, 0x00},
127         {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
128         {SENSOR, 0x08, 0x02, 0x00},
129         {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
130         {SENSOR, 0x14, 0x00, 0x00},
131         {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
132         {SENSOR, 0x19, 0x00, 0x00},
133         {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
134         {SENSOR, 0x0f, 0x02, 0x00},
135         {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
136         /* normal colors
137         (this is value after boot, but after tries can be different) */
138         {SENSOR, 0x00, 0x06, 0x00},
139 };
140
141 static const unsigned char start_s5k83a[][4] = {
142         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
143         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
144         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
145         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
146         {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
147         {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
148         {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
149         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
150         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
151         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
152         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
153         {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
154         {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
155         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
156         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
157         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
158         {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
159         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
160         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
161         {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
162         {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
163         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
164         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
165         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
166 };
167
168 static void s5k83a_dump_registers(struct sd *sd);
169 static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
170 static int s5k83a_set_led_indication(struct sd *sd, u8 val);
171 static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
172                                 __s32 vflip, __s32 hflip);
173
174 int s5k83a_probe(struct sd *sd)
175 {
176         u8 prod_id = 0, ver_id = 0;
177         int i, err = 0;
178         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
179
180         if (force_sensor) {
181                 if (force_sensor == S5K83A_SENSOR) {
182                         pr_info("Forcing a %s sensor\n", s5k83a.name);
183                         goto sensor_found;
184                 }
185                 /* If we want to force another sensor, don't try to probe this
186                  * one */
187                 return -ENODEV;
188         }
189
190         PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
191
192         /* Preinit the sensor */
193         for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
194                 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
195                 if (preinit_s5k83a[i][0] == SENSOR)
196                         err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
197                                 data, 2);
198                 else
199                         err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
200                                 data[0]);
201         }
202
203         /* We don't know what register (if any) that contain the product id
204          * Just pick the first addresses that seem to produce the same results
205          * on multiple machines */
206         if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
207                 return -ENODEV;
208
209         if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
210                 return -ENODEV;
211
212         if ((prod_id == 0xff) || (ver_id == 0xff))
213                 return -ENODEV;
214         else
215                 pr_info("Detected a s5k83a sensor\n");
216
217 sensor_found:
218         sd->gspca_dev.cam.cam_mode = s5k83a_modes;
219         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
220
221         /* null the pointer! thread is't running now */
222         sd->rotation_thread = NULL;
223
224         return 0;
225 }
226
227 int s5k83a_init(struct sd *sd)
228 {
229         int i, err = 0;
230
231         for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
232                 u8 data[2] = {0x00, 0x00};
233
234                 switch (init_s5k83a[i][0]) {
235                 case BRIDGE:
236                         err = m5602_write_bridge(sd,
237                                         init_s5k83a[i][1],
238                                         init_s5k83a[i][2]);
239                         break;
240
241                 case SENSOR:
242                         data[0] = init_s5k83a[i][2];
243                         err = m5602_write_sensor(sd,
244                                 init_s5k83a[i][1], data, 1);
245                         break;
246
247                 case SENSOR_LONG:
248                         data[0] = init_s5k83a[i][2];
249                         data[1] = init_s5k83a[i][3];
250                         err = m5602_write_sensor(sd,
251                                 init_s5k83a[i][1], data, 2);
252                         break;
253                 default:
254                         pr_info("Invalid stream command, exiting init\n");
255                         return -EINVAL;
256                 }
257         }
258
259         if (dump_sensor)
260                 s5k83a_dump_registers(sd);
261
262         return err;
263 }
264
265 int s5k83a_init_controls(struct sd *sd)
266 {
267         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
268
269         sd->gspca_dev.vdev.ctrl_handler = hdl;
270         v4l2_ctrl_handler_init(hdl, 6);
271
272         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
273                           0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
274
275         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
276                           0, S5K83A_MAXIMUM_EXPOSURE, 1,
277                           S5K83A_DEFAULT_EXPOSURE);
278
279         v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
280                           0, 255, 1, S5K83A_DEFAULT_GAIN);
281
282         sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
283                                       0, 1, 1, 0);
284         sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
285                                       0, 1, 1, 0);
286
287         if (hdl->error) {
288                 pr_err("Could not initialize controls\n");
289                 return hdl->error;
290         }
291
292         v4l2_ctrl_cluster(2, &sd->hflip);
293
294         return 0;
295 }
296
297 static int rotation_thread_function(void *data)
298 {
299         struct sd *sd = (struct sd *) data;
300         u8 reg, previous_rotation = 0;
301         __s32 vflip, hflip;
302
303         set_current_state(TASK_INTERRUPTIBLE);
304         while (!schedule_timeout(msecs_to_jiffies(100))) {
305                 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
306                         break;
307
308                 s5k83a_get_rotation(sd, &reg);
309                 if (previous_rotation != reg) {
310                         previous_rotation = reg;
311                         pr_info("Camera was flipped\n");
312
313                         hflip = sd->hflip->val;
314                         vflip = sd->vflip->val;
315
316                         if (reg) {
317                                 vflip = !vflip;
318                                 hflip = !hflip;
319                         }
320                         s5k83a_set_flip_real((struct gspca_dev *) sd,
321                                               vflip, hflip);
322                 }
323
324                 mutex_unlock(&sd->gspca_dev.usb_lock);
325                 set_current_state(TASK_INTERRUPTIBLE);
326         }
327
328         /* return to "front" flip */
329         if (previous_rotation) {
330                 hflip = sd->hflip->val;
331                 vflip = sd->vflip->val;
332                 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
333         }
334
335         sd->rotation_thread = NULL;
336         return 0;
337 }
338
339 int s5k83a_start(struct sd *sd)
340 {
341         int i, err = 0;
342
343         /* Create another thread, polling the GPIO ports of the camera to check
344            if it got rotated. This is how the windows driver does it so we have
345            to assume that there is no better way of accomplishing this */
346         sd->rotation_thread = kthread_create(rotation_thread_function,
347                                              sd, "rotation thread");
348         wake_up_process(sd->rotation_thread);
349
350         /* Preinit the sensor */
351         for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
352                 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
353                 if (start_s5k83a[i][0] == SENSOR)
354                         err = m5602_write_sensor(sd, start_s5k83a[i][1],
355                                 data, 2);
356                 else
357                         err = m5602_write_bridge(sd, start_s5k83a[i][1],
358                                 data[0]);
359         }
360         if (err < 0)
361                 return err;
362
363         return s5k83a_set_led_indication(sd, 1);
364 }
365
366 int s5k83a_stop(struct sd *sd)
367 {
368         if (sd->rotation_thread)
369                 kthread_stop(sd->rotation_thread);
370
371         return s5k83a_set_led_indication(sd, 0);
372 }
373
374 void s5k83a_disconnect(struct sd *sd)
375 {
376         s5k83a_stop(sd);
377
378         sd->sensor = NULL;
379 }
380
381 static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
382 {
383         int err;
384         u8 data[2];
385         struct sd *sd = (struct sd *) gspca_dev;
386
387         data[0] = 0x00;
388         data[1] = 0x20;
389         err = m5602_write_sensor(sd, 0x14, data, 2);
390         if (err < 0)
391                 return err;
392
393         data[0] = 0x01;
394         data[1] = 0x00;
395         err = m5602_write_sensor(sd, 0x0d, data, 2);
396         if (err < 0)
397                 return err;
398
399         /* FIXME: This is not sane, we need to figure out the composition
400                   of these registers */
401         data[0] = val >> 3; /* gain, high 5 bits */
402         data[1] = val >> 1; /* gain, high 7 bits */
403         err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
404
405         return err;
406 }
407
408 static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
409 {
410         int err;
411         u8 data[1];
412         struct sd *sd = (struct sd *) gspca_dev;
413
414         data[0] = val;
415         err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
416         return err;
417 }
418
419 static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
420 {
421         int err;
422         u8 data[2];
423         struct sd *sd = (struct sd *) gspca_dev;
424
425         data[0] = 0;
426         data[1] = val;
427         err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
428         return err;
429 }
430
431 static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
432                                 __s32 vflip, __s32 hflip)
433 {
434         int err;
435         u8 data[1];
436         struct sd *sd = (struct sd *) gspca_dev;
437
438         data[0] = 0x05;
439         err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
440         if (err < 0)
441                 return err;
442
443         /* six bit is vflip, seven is hflip */
444         data[0] = S5K83A_FLIP_MASK;
445         data[0] = (vflip) ? data[0] | 0x40 : data[0];
446         data[0] = (hflip) ? data[0] | 0x80 : data[0];
447
448         err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
449         if (err < 0)
450                 return err;
451
452         data[0] = (vflip) ? 0x0b : 0x0a;
453         err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
454         if (err < 0)
455                 return err;
456
457         data[0] = (hflip) ? 0x0a : 0x0b;
458         err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
459         return err;
460 }
461
462 static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
463 {
464         int err;
465         u8 reg;
466         struct sd *sd = (struct sd *) gspca_dev;
467         int hflip = sd->hflip->val;
468         int vflip = sd->vflip->val;
469
470         err = s5k83a_get_rotation(sd, &reg);
471         if (err < 0)
472                 return err;
473         if (reg) {
474                 hflip = !hflip;
475                 vflip = !vflip;
476         }
477
478         err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
479         return err;
480 }
481
482 static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
483 {
484         struct gspca_dev *gspca_dev =
485                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
486         int err;
487
488         if (!gspca_dev->streaming)
489                 return 0;
490
491         switch (ctrl->id) {
492         case V4L2_CID_BRIGHTNESS:
493                 err = s5k83a_set_brightness(gspca_dev, ctrl->val);
494                 break;
495         case V4L2_CID_EXPOSURE:
496                 err = s5k83a_set_exposure(gspca_dev, ctrl->val);
497                 break;
498         case V4L2_CID_GAIN:
499                 err = s5k83a_set_gain(gspca_dev, ctrl->val);
500                 break;
501         case V4L2_CID_HFLIP:
502                 err = s5k83a_set_hvflip(gspca_dev);
503                 break;
504         default:
505                 return -EINVAL;
506         }
507
508         return err;
509 }
510
511 static int s5k83a_set_led_indication(struct sd *sd, u8 val)
512 {
513         int err = 0;
514         u8 data[1];
515
516         err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
517         if (err < 0)
518                 return err;
519
520         if (val)
521                 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
522         else
523                 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
524
525         err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
526
527         return err;
528 }
529
530 /* Get camera rotation on Acer notebooks */
531 static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
532 {
533         int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
534         *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
535         return err;
536 }
537
538 static void s5k83a_dump_registers(struct sd *sd)
539 {
540         int address;
541         u8 page, old_page;
542         m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
543
544         for (page = 0; page < 16; page++) {
545                 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
546                 pr_info("Dumping the s5k83a register state for page 0x%x\n",
547                         page);
548                 for (address = 0; address <= 0xff; address++) {
549                         u8 val = 0;
550                         m5602_read_sensor(sd, address, &val, 1);
551                         pr_info("register 0x%x contains 0x%x\n", address, val);
552                 }
553         }
554         pr_info("s5k83a register state dump complete\n");
555
556         for (page = 0; page < 16; page++) {
557                 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
558                 pr_info("Probing for which registers that are read/write for page 0x%x\n",
559                         page);
560                 for (address = 0; address <= 0xff; address++) {
561                         u8 old_val, ctrl_val, test_val = 0xff;
562
563                         m5602_read_sensor(sd, address, &old_val, 1);
564                         m5602_write_sensor(sd, address, &test_val, 1);
565                         m5602_read_sensor(sd, address, &ctrl_val, 1);
566
567                         if (ctrl_val == test_val)
568                                 pr_info("register 0x%x is writeable\n",
569                                         address);
570                         else
571                                 pr_info("register 0x%x is read only\n",
572                                         address);
573
574                         /* Restore original val */
575                         m5602_write_sensor(sd, address, &old_val, 1);
576                 }
577         }
578         pr_info("Read/write register probing complete\n");
579         m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
580 }