1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
142
143 return -ENODEV;
144 }
145
146 info("Probing for a s5k83a sensor");
147
148
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
160
161
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
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, ®);
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
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
310
311
312 sens_priv->rotation_thread = kthread_create(rotation_thread_function,
313 sd, "rotation thread");
314 wake_up_process(sens_priv->rotation_thread);
315
316
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
384
385 data[0] = val >> 3;
386 data[1] = val >> 1;
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
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, ®);
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, ®);
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
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
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}
602