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