blob: 6b3be4fa2c067be5a9045ea0926f040528608692 [file] [log] [blame]
Erik Andrenc109f812008-10-01 04:51:53 -03001/*
2 * Driver for the s5k83a sensor
3 *
Erik Andren0c505e682008-10-16 16:43:16 -03004 * Copyright (C) 2008 Erik Andrén
Erik Andrenc109f812008-10-01 04:51:53 -03005 * 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
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030019#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Erik Andrenc109f812008-10-01 04:51:53 -030021#include "m5602_s5k83a.h"
22
Erik Andr?ncf811d52009-04-03 02:49:10 -030023static 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
Erik Andr?n74cadfe2008-12-30 16:48:42 -030034static 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
Tobias Klauser2e036692009-04-26 09:30:18 -030048static const struct ctrl s5k83a_ctrls[] = {
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030049#define GAIN_IDX 0
50 {
51 {
52 .id = V4L2_CID_GAIN,
53 .type = V4L2_CTRL_TYPE_INTEGER,
54 .name = "gain",
55 .minimum = 0x00,
56 .maximum = 0xff,
57 .step = 0x01,
58 .default_value = S5K83A_DEFAULT_GAIN,
59 .flags = V4L2_CTRL_FLAG_SLIDER
60 },
61 .set = s5k83a_set_gain,
62 .get = s5k83a_get_gain
63
64 },
65#define BRIGHTNESS_IDX 1
Erik Andr?ne17cc082008-12-30 17:06:55 -030066 {
67 {
68 .id = V4L2_CID_BRIGHTNESS,
69 .type = V4L2_CTRL_TYPE_INTEGER,
70 .name = "brightness",
71 .minimum = 0x00,
72 .maximum = 0xff,
73 .step = 0x01,
74 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
75 .flags = V4L2_CTRL_FLAG_SLIDER
76 },
77 .set = s5k83a_set_brightness,
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030078 .get = s5k83a_get_brightness,
79 },
80#define EXPOSURE_IDX 2
81 {
Erik Andr?ne17cc082008-12-30 17:06:55 -030082 {
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030083 .id = V4L2_CID_EXPOSURE,
Erik Andr?ne17cc082008-12-30 17:06:55 -030084 .type = V4L2_CTRL_TYPE_INTEGER,
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030085 .name = "exposure",
Erik Andr?ne17cc082008-12-30 17:06:55 -030086 .minimum = 0x00,
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030087 .maximum = S5K83A_MAXIMUM_EXPOSURE,
Erik Andr?ne17cc082008-12-30 17:06:55 -030088 .step = 0x01,
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030089 .default_value = S5K83A_DEFAULT_EXPOSURE,
Erik Andr?ne17cc082008-12-30 17:06:55 -030090 .flags = V4L2_CTRL_FLAG_SLIDER
91 },
Luk?? Karasac3d5bf2009-04-03 02:45:56 -030092 .set = s5k83a_set_exposure,
93 .get = s5k83a_get_exposure
94 },
95#define HFLIP_IDX 3
96 {
Erik Andr?ne17cc082008-12-30 17:06:55 -030097 {
Erik Andr?n00e02562009-01-20 14:53:21 -030098 .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
Erik Andr?ne17cc082008-12-30 17:06:55 -0300105 },
106 .set = s5k83a_set_hflip,
107 .get = s5k83a_get_hflip
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300108 },
109#define VFLIP_IDX 4
110 {
Erik Andr?ne17cc082008-12-30 17:06:55 -0300111 {
Erik Andr?n00e02562009-01-20 14:53:21 -0300112 .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
Erik Andr?ne17cc082008-12-30 17:06:55 -0300119 },
120 .set = s5k83a_set_vflip,
121 .get = s5k83a_get_vflip
122 }
123};
124
Erik Andrén658efb62008-11-24 14:21:29 -0300125static void s5k83a_dump_registers(struct sd *sd);
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300126static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
127static int s5k83a_set_led_indication(struct sd *sd, u8 val);
Erik Andrén57851d02009-04-27 15:38:05 -0300128static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
129 __s32 vflip, __s32 hflip);
Erik Andrén658efb62008-11-24 14:21:29 -0300130
Erik Andrenc109f812008-10-01 04:51:53 -0300131int s5k83a_probe(struct sd *sd)
132{
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300133 struct s5k83a_priv *sens_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300134 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
Erik Andrén969cc922009-12-27 05:53:28 -0300147 PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
Erik Andrenc109f812008-10-01 04:51:53 -0300148
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)
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300153 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
Erik Andrenc109f812008-10-01 04:51:53 -0300154 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 */
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300163 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
Erik Andrenc109f812008-10-01 04:51:53 -0300164 return -ENODEV;
165
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300166 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
Erik Andrenc109f812008-10-01 04:51:53 -0300167 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:
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300175 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);
Julia Lawallb807d172009-08-04 22:00:24 -0300182 if (!sens_priv->settings) {
183 kfree(sens_priv);
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300184 return -ENOMEM;
Julia Lawallb807d172009-08-04 22:00:24 -0300185 }
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300186
Erik Andr?n74cadfe2008-12-30 16:48:42 -0300187 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
188 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
Erik Andr?ne17cc082008-12-30 17:06:55 -0300189 sd->desc->ctrls = s5k83a_ctrls;
Erik Andr?ne4cc4fc2008-12-30 15:27:17 -0300190 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300191
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;
Erik Andrenc109f812008-10-01 04:51:53 -0300199 return 0;
200}
201
Erik Andrenc109f812008-10-01 04:51:53 -0300202int s5k83a_init(struct sd *sd)
203{
204 int i, err = 0;
Lukas Karasc41507b2009-01-21 13:14:07 -0300205 s32 *sensor_settings =
206 ((struct s5k83a_priv *) sd->sensor_priv)->settings;
Erik Andrenc109f812008-10-01 04:51:53 -0300207
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];
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300220 err = m5602_write_sensor(sd,
Erik Andrenc109f812008-10-01 04:51:53 -0300221 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];
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300227 err = m5602_write_sensor(sd,
Erik Andrenc109f812008-10-01 04:51:53 -0300228 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
Erik Andrén57851d02009-04-27 15:38:05 -0300239 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;
Erik Andrenc109f812008-10-01 04:51:53 -0300260}
261
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300262static 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 }
Erik Andrén1b844b52009-05-03 15:31:55 -0300286 s5k83a_set_flip_real((struct gspca_dev *) sd,
287 vflip, hflip);
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300288 }
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
Lukas Karas4a7581f2008-12-28 14:09:21 -0300305int s5k83a_start(struct sd *sd)
306{
Erik Andréncde41bb2009-01-21 03:33:14 -0300307 int i, err = 0;
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300308 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 */
Erik Andrén57851d02009-04-27 15:38:05 -0300313 sens_priv->rotation_thread = kthread_create(rotation_thread_function,
Erik Andréncde41bb2009-01-21 03:33:14 -0300314 sd, "rotation thread");
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300315 wake_up_process(sens_priv->rotation_thread);
316
Erik Andréncde41bb2009-01-21 03:33:14 -0300317 /* 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
Lukas Karas4a7581f2008-12-28 14:09:21 -0300330 return s5k83a_set_led_indication(sd, 1);
331}
332
333int s5k83a_stop(struct sd *sd)
334{
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300335 struct s5k83a_priv *sens_priv = sd->sensor_priv;
336
337 if (sens_priv->rotation_thread)
338 kthread_stop(sens_priv->rotation_thread);
339
Lukas Karas4a7581f2008-12-28 14:09:21 -0300340 return s5k83a_set_led_indication(sd, 0);
341}
342
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300343void s5k83a_disconnect(struct sd *sd)
344{
345 struct s5k83a_priv *sens_priv = sd->sensor_priv;
346
347 s5k83a_stop(sd);
348
349 sd->sensor = NULL;
350 kfree(sens_priv->settings);
351 kfree(sens_priv);
352}
353
Erik Andr?ncf811d52009-04-03 02:49:10 -0300354static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300355{
356 struct sd *sd = (struct sd *) gspca_dev;
357 struct s5k83a_priv *sens_priv = sd->sensor_priv;
358
359 *val = sens_priv->settings[GAIN_IDX];
360 return 0;
361}
362
Erik Andr?ncf811d52009-04-03 02:49:10 -0300363static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300364{
365 int err;
366 u8 data[2];
367 struct sd *sd = (struct sd *) gspca_dev;
368 struct s5k83a_priv *sens_priv = sd->sensor_priv;
369
370 sens_priv->settings[GAIN_IDX] = val;
371
372 data[0] = 0x00;
373 data[1] = 0x20;
374 err = m5602_write_sensor(sd, 0x14, data, 2);
375 if (err < 0)
376 return err;
377
378 data[0] = 0x01;
379 data[1] = 0x00;
380 err = m5602_write_sensor(sd, 0x0d, data, 2);
381 if (err < 0)
382 return err;
383
384 /* FIXME: This is not sane, we need to figure out the composition
385 of these registers */
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);
389
390 return err;
391}
392
Erik Andr?ncf811d52009-04-03 02:49:10 -0300393static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300394{
395 struct sd *sd = (struct sd *) gspca_dev;
396 struct s5k83a_priv *sens_priv = sd->sensor_priv;
397
398 *val = sens_priv->settings[BRIGHTNESS_IDX];
399 return 0;
400}
401
Erik Andr?ncf811d52009-04-03 02:49:10 -0300402static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300403{
404 int err;
405 u8 data[1];
406 struct sd *sd = (struct sd *) gspca_dev;
407 struct s5k83a_priv *sens_priv = sd->sensor_priv;
408
409 sens_priv->settings[BRIGHTNESS_IDX] = val;
410 data[0] = val;
411 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
412 return err;
413}
414
Erik Andr?ncf811d52009-04-03 02:49:10 -0300415static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300416{
417 struct sd *sd = (struct sd *) gspca_dev;
418 struct s5k83a_priv *sens_priv = sd->sensor_priv;
419
420 *val = sens_priv->settings[EXPOSURE_IDX];
421 return 0;
422}
423
Erik Andr?ncf811d52009-04-03 02:49:10 -0300424static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300425{
426 int err;
427 u8 data[2];
428 struct sd *sd = (struct sd *) gspca_dev;
429 struct s5k83a_priv *sens_priv = sd->sensor_priv;
430
431 sens_priv->settings[EXPOSURE_IDX] = val;
432 data[0] = 0;
433 data[1] = val;
434 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
435 return err;
436}
437
Erik Andr?ncf811d52009-04-03 02:49:10 -0300438static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300439{
440 struct sd *sd = (struct sd *) gspca_dev;
441 struct s5k83a_priv *sens_priv = sd->sensor_priv;
442
443 *val = sens_priv->settings[VFLIP_IDX];
444 return 0;
445}
446
Erik Andrén57851d02009-04-27 15:38:05 -0300447static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
448 __s32 vflip, __s32 hflip)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300449{
450 int err;
451 u8 data[1];
452 struct sd *sd = (struct sd *) gspca_dev;
453
454 data[0] = 0x05;
455 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
456 if (err < 0)
457 return err;
458
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];
463
464 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
465 if (err < 0)
466 return err;
467
468 data[0] = (vflip) ? 0x0b : 0x0a;
469 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
470 if (err < 0)
471 return err;
472
473 data[0] = (hflip) ? 0x0a : 0x0b;
474 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
475 return err;
476}
477
Erik Andr?ncf811d52009-04-03 02:49:10 -0300478static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300479{
480 int err;
481 u8 reg;
482 __s32 hflip;
483 struct sd *sd = (struct sd *) gspca_dev;
484 struct s5k83a_priv *sens_priv = sd->sensor_priv;
485
486 sens_priv->settings[VFLIP_IDX] = val;
487
488 s5k83a_get_hflip(gspca_dev, &hflip);
489
490 err = s5k83a_get_rotation(sd, &reg);
491 if (err < 0)
492 return err;
493 if (reg) {
494 val = !val;
495 hflip = !hflip;
496 }
497
498 err = s5k83a_set_flip_real(gspca_dev, val, hflip);
499 return err;
500}
501
Erik Andr?ncf811d52009-04-03 02:49:10 -0300502static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300503{
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
Erik Andr?ncf811d52009-04-03 02:49:10 -0300511static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300512{
513 int err;
514 u8 reg;
515 __s32 vflip;
516 struct sd *sd = (struct sd *) gspca_dev;
517 struct s5k83a_priv *sens_priv = sd->sensor_priv;
518
519 sens_priv->settings[HFLIP_IDX] = val;
520
521 s5k83a_get_vflip(gspca_dev, &vflip);
522
523 err = s5k83a_get_rotation(sd, &reg);
524 if (err < 0)
525 return err;
526 if (reg) {
527 val = !val;
528 vflip = !vflip;
529 }
530
531 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
532 return err;
533}
534
535static int s5k83a_set_led_indication(struct sd *sd, u8 val)
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
Erik Andrén57851d02009-04-27 15:38:05 -0300551 return err;
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300552}
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
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -0300562static void s5k83a_dump_registers(struct sd *sd)
Erik Andrenc109f812008-10-01 04:51:53 -0300563{
564 int address;
565 u8 page, old_page;
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300566 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300567
568 for (page = 0; page < 16; page++) {
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300569 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300570 info("Dumping the s5k83a register state for page 0x%x", page);
571 for (address = 0; address <= 0xff; address++) {
572 u8 val = 0;
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300573 m5602_read_sensor(sd, address, &val, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300574 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++) {
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300581 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300582 info("Probing for which registers that are read/write "
Luk?? Karasac3d5bf2009-04-03 02:45:56 -0300583 "for page 0x%x", page);
Erik Andrenc109f812008-10-01 04:51:53 -0300584 for (address = 0; address <= 0xff; address++) {
585 u8 old_val, ctrl_val, test_val = 0xff;
586
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300587 m5602_read_sensor(sd, address, &old_val, 1);
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300588 m5602_write_sensor(sd, address, &test_val, 1);
Erik Andrén6b9c0a22008-11-27 13:54:13 -0300589 m5602_read_sensor(sd, address, &ctrl_val, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300590
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 */
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300597 m5602_write_sensor(sd, address, &old_val, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300598 }
599 }
600 info("Read/write register probing complete");
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300601 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300602}