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