Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/m5602/m5602_s5k83a.c
17902 views
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 <[email protected]>
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
22
static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
23
static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24
static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
25
static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
26
static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
27
static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
28
static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
29
static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
30
static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
31
static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
32
33
static 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
47
static 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
124
static void s5k83a_dump_registers(struct sd *sd);
125
static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
126
static int s5k83a_set_led_indication(struct sd *sd, u8 val);
127
static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
128
__s32 vflip, __s32 hflip);
129
130
int 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
173
sensor_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
201
int 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
261
static 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
304
int 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
332
int 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
342
void 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
353
static 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
362
static 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
392
static 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
401
static 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
414
static 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
423
static 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
437
static 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
446
static 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
477
static 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
501
static 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
510
static 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
534
static 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 */
554
static 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
561
static 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
}
602
603