Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
17900 views
1
/*
2
* Driver for the s5k4aa 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 "m5602_s5k4aa.h"
20
21
static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
22
static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
23
static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
24
static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
25
static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26
static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27
static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28
static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29
static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
30
static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
31
static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
32
static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
33
34
static
35
const
36
struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
37
{
38
.ident = "BRUNEINIT",
39
.matches = {
40
DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
41
DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
42
DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
43
}
44
}, {
45
.ident = "Fujitsu-Siemens Amilo Xa 2528",
46
.matches = {
47
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
48
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
49
}
50
}, {
51
.ident = "Fujitsu-Siemens Amilo Xi 2428",
52
.matches = {
53
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
54
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
55
}
56
}, {
57
.ident = "Fujitsu-Siemens Amilo Xi 2528",
58
.matches = {
59
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
60
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
61
}
62
}, {
63
.ident = "Fujitsu-Siemens Amilo Xi 2550",
64
.matches = {
65
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
66
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
67
}
68
}, {
69
.ident = "Fujitsu-Siemens Amilo Pa 2548",
70
.matches = {
71
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
72
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
73
}
74
}, {
75
.ident = "MSI GX700",
76
.matches = {
77
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
78
DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
79
DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
80
}
81
}, {
82
.ident = "MSI GX700",
83
.matches = {
84
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
85
DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
86
DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
87
}
88
}, {
89
.ident = "MSI GX700",
90
.matches = {
91
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
92
DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
93
DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
94
}
95
}, {
96
.ident = "MSI GX700/GX705/EX700",
97
.matches = {
98
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
99
DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
100
}
101
}, {
102
.ident = "MSI L735",
103
.matches = {
104
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
105
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
106
}
107
}, {
108
.ident = "Lenovo Y300",
109
.matches = {
110
DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
111
DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
112
}
113
},
114
{ }
115
};
116
117
static struct v4l2_pix_format s5k4aa_modes[] = {
118
{
119
640,
120
480,
121
V4L2_PIX_FMT_SBGGR8,
122
V4L2_FIELD_NONE,
123
.sizeimage =
124
640 * 480,
125
.bytesperline = 640,
126
.colorspace = V4L2_COLORSPACE_SRGB,
127
.priv = 0
128
},
129
{
130
1280,
131
1024,
132
V4L2_PIX_FMT_SBGGR8,
133
V4L2_FIELD_NONE,
134
.sizeimage =
135
1280 * 1024,
136
.bytesperline = 1280,
137
.colorspace = V4L2_COLORSPACE_SRGB,
138
.priv = 0
139
}
140
};
141
142
static const struct ctrl s5k4aa_ctrls[] = {
143
#define VFLIP_IDX 0
144
{
145
{
146
.id = V4L2_CID_VFLIP,
147
.type = V4L2_CTRL_TYPE_BOOLEAN,
148
.name = "vertical flip",
149
.minimum = 0,
150
.maximum = 1,
151
.step = 1,
152
.default_value = 0
153
},
154
.set = s5k4aa_set_vflip,
155
.get = s5k4aa_get_vflip
156
},
157
#define HFLIP_IDX 1
158
{
159
{
160
.id = V4L2_CID_HFLIP,
161
.type = V4L2_CTRL_TYPE_BOOLEAN,
162
.name = "horizontal flip",
163
.minimum = 0,
164
.maximum = 1,
165
.step = 1,
166
.default_value = 0
167
},
168
.set = s5k4aa_set_hflip,
169
.get = s5k4aa_get_hflip
170
},
171
#define GAIN_IDX 2
172
{
173
{
174
.id = V4L2_CID_GAIN,
175
.type = V4L2_CTRL_TYPE_INTEGER,
176
.name = "Gain",
177
.minimum = 0,
178
.maximum = 127,
179
.step = 1,
180
.default_value = S5K4AA_DEFAULT_GAIN,
181
.flags = V4L2_CTRL_FLAG_SLIDER
182
},
183
.set = s5k4aa_set_gain,
184
.get = s5k4aa_get_gain
185
},
186
#define EXPOSURE_IDX 3
187
{
188
{
189
.id = V4L2_CID_EXPOSURE,
190
.type = V4L2_CTRL_TYPE_INTEGER,
191
.name = "Exposure",
192
.minimum = 13,
193
.maximum = 0xfff,
194
.step = 1,
195
.default_value = 0x100,
196
.flags = V4L2_CTRL_FLAG_SLIDER
197
},
198
.set = s5k4aa_set_exposure,
199
.get = s5k4aa_get_exposure
200
},
201
#define NOISE_SUPP_IDX 4
202
{
203
{
204
.id = V4L2_CID_PRIVATE_BASE,
205
.type = V4L2_CTRL_TYPE_BOOLEAN,
206
.name = "Noise suppression (smoothing)",
207
.minimum = 0,
208
.maximum = 1,
209
.step = 1,
210
.default_value = 1,
211
},
212
.set = s5k4aa_set_noise,
213
.get = s5k4aa_get_noise
214
},
215
#define BRIGHTNESS_IDX 5
216
{
217
{
218
.id = V4L2_CID_BRIGHTNESS,
219
.type = V4L2_CTRL_TYPE_INTEGER,
220
.name = "Brightness",
221
.minimum = 0,
222
.maximum = 0x1f,
223
.step = 1,
224
.default_value = S5K4AA_DEFAULT_BRIGHTNESS,
225
},
226
.set = s5k4aa_set_brightness,
227
.get = s5k4aa_get_brightness
228
},
229
230
};
231
232
static void s5k4aa_dump_registers(struct sd *sd);
233
234
int s5k4aa_probe(struct sd *sd)
235
{
236
u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
237
const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
238
int i, err = 0;
239
s32 *sensor_settings;
240
241
if (force_sensor) {
242
if (force_sensor == S5K4AA_SENSOR) {
243
info("Forcing a %s sensor", s5k4aa.name);
244
goto sensor_found;
245
}
246
/* If we want to force another sensor, don't try to probe this
247
* one */
248
return -ENODEV;
249
}
250
251
PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
252
253
/* Preinit the sensor */
254
for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
255
u8 data[2] = {0x00, 0x00};
256
257
switch (preinit_s5k4aa[i][0]) {
258
case BRIDGE:
259
err = m5602_write_bridge(sd,
260
preinit_s5k4aa[i][1],
261
preinit_s5k4aa[i][2]);
262
break;
263
264
case SENSOR:
265
data[0] = preinit_s5k4aa[i][2];
266
err = m5602_write_sensor(sd,
267
preinit_s5k4aa[i][1],
268
data, 1);
269
break;
270
271
case SENSOR_LONG:
272
data[0] = preinit_s5k4aa[i][2];
273
data[1] = preinit_s5k4aa[i][3];
274
err = m5602_write_sensor(sd,
275
preinit_s5k4aa[i][1],
276
data, 2);
277
break;
278
default:
279
info("Invalid stream command, exiting init");
280
return -EINVAL;
281
}
282
}
283
284
/* Test some registers, but we don't know their exact meaning yet */
285
if (m5602_read_sensor(sd, 0x00, prod_id, 2))
286
return -ENODEV;
287
if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
288
return -ENODEV;
289
if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
290
return -ENODEV;
291
292
if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
293
return -ENODEV;
294
else
295
info("Detected a s5k4aa sensor");
296
297
sensor_found:
298
sensor_settings = kmalloc(
299
ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
300
if (!sensor_settings)
301
return -ENOMEM;
302
303
sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
304
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
305
sd->desc->ctrls = s5k4aa_ctrls;
306
sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
307
308
for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
309
sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
310
sd->sensor_priv = sensor_settings;
311
312
return 0;
313
}
314
315
int s5k4aa_start(struct sd *sd)
316
{
317
int i, err = 0;
318
u8 data[2];
319
struct cam *cam = &sd->gspca_dev.cam;
320
s32 *sensor_settings = sd->sensor_priv;
321
322
switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
323
case 1280:
324
PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
325
326
for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
327
switch (SXGA_s5k4aa[i][0]) {
328
case BRIDGE:
329
err = m5602_write_bridge(sd,
330
SXGA_s5k4aa[i][1],
331
SXGA_s5k4aa[i][2]);
332
break;
333
334
case SENSOR:
335
data[0] = SXGA_s5k4aa[i][2];
336
err = m5602_write_sensor(sd,
337
SXGA_s5k4aa[i][1],
338
data, 1);
339
break;
340
341
case SENSOR_LONG:
342
data[0] = SXGA_s5k4aa[i][2];
343
data[1] = SXGA_s5k4aa[i][3];
344
err = m5602_write_sensor(sd,
345
SXGA_s5k4aa[i][1],
346
data, 2);
347
break;
348
349
default:
350
err("Invalid stream command, exiting init");
351
return -EINVAL;
352
}
353
}
354
err = s5k4aa_set_noise(&sd->gspca_dev, 0);
355
if (err < 0)
356
return err;
357
break;
358
359
case 640:
360
PDEBUG(D_V4L2, "Configuring camera for VGA mode");
361
362
for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
363
switch (VGA_s5k4aa[i][0]) {
364
case BRIDGE:
365
err = m5602_write_bridge(sd,
366
VGA_s5k4aa[i][1],
367
VGA_s5k4aa[i][2]);
368
break;
369
370
case SENSOR:
371
data[0] = VGA_s5k4aa[i][2];
372
err = m5602_write_sensor(sd,
373
VGA_s5k4aa[i][1],
374
data, 1);
375
break;
376
377
case SENSOR_LONG:
378
data[0] = VGA_s5k4aa[i][2];
379
data[1] = VGA_s5k4aa[i][3];
380
err = m5602_write_sensor(sd,
381
VGA_s5k4aa[i][1],
382
data, 2);
383
break;
384
385
default:
386
err("Invalid stream command, exiting init");
387
return -EINVAL;
388
}
389
}
390
err = s5k4aa_set_noise(&sd->gspca_dev, 1);
391
if (err < 0)
392
return err;
393
break;
394
}
395
if (err < 0)
396
return err;
397
398
err = s5k4aa_set_exposure(&sd->gspca_dev,
399
sensor_settings[EXPOSURE_IDX]);
400
if (err < 0)
401
return err;
402
403
err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
404
if (err < 0)
405
return err;
406
407
err = s5k4aa_set_brightness(&sd->gspca_dev,
408
sensor_settings[BRIGHTNESS_IDX]);
409
if (err < 0)
410
return err;
411
412
err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
413
if (err < 0)
414
return err;
415
416
err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
417
if (err < 0)
418
return err;
419
420
return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
421
}
422
423
int s5k4aa_init(struct sd *sd)
424
{
425
int i, err = 0;
426
427
for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
428
u8 data[2] = {0x00, 0x00};
429
430
switch (init_s5k4aa[i][0]) {
431
case BRIDGE:
432
err = m5602_write_bridge(sd,
433
init_s5k4aa[i][1],
434
init_s5k4aa[i][2]);
435
break;
436
437
case SENSOR:
438
data[0] = init_s5k4aa[i][2];
439
err = m5602_write_sensor(sd,
440
init_s5k4aa[i][1], data, 1);
441
break;
442
443
case SENSOR_LONG:
444
data[0] = init_s5k4aa[i][2];
445
data[1] = init_s5k4aa[i][3];
446
err = m5602_write_sensor(sd,
447
init_s5k4aa[i][1], data, 2);
448
break;
449
default:
450
info("Invalid stream command, exiting init");
451
return -EINVAL;
452
}
453
}
454
455
if (dump_sensor)
456
s5k4aa_dump_registers(sd);
457
458
return err;
459
}
460
461
static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
462
{
463
struct sd *sd = (struct sd *) gspca_dev;
464
s32 *sensor_settings = sd->sensor_priv;
465
466
*val = sensor_settings[EXPOSURE_IDX];
467
PDEBUG(D_V4L2, "Read exposure %d", *val);
468
469
return 0;
470
}
471
472
static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
473
{
474
struct sd *sd = (struct sd *) gspca_dev;
475
s32 *sensor_settings = sd->sensor_priv;
476
u8 data = S5K4AA_PAGE_MAP_2;
477
int err;
478
479
sensor_settings[EXPOSURE_IDX] = val;
480
PDEBUG(D_V4L2, "Set exposure to %d", val);
481
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
482
if (err < 0)
483
return err;
484
data = (val >> 8) & 0xff;
485
err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
486
if (err < 0)
487
return err;
488
data = val & 0xff;
489
err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
490
491
return err;
492
}
493
494
static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
495
{
496
struct sd *sd = (struct sd *) gspca_dev;
497
s32 *sensor_settings = sd->sensor_priv;
498
499
*val = sensor_settings[VFLIP_IDX];
500
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
501
502
return 0;
503
}
504
505
static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
506
{
507
struct sd *sd = (struct sd *) gspca_dev;
508
s32 *sensor_settings = sd->sensor_priv;
509
u8 data = S5K4AA_PAGE_MAP_2;
510
int err;
511
512
sensor_settings[VFLIP_IDX] = val;
513
514
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
515
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
516
if (err < 0)
517
return err;
518
519
err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
520
if (err < 0)
521
return err;
522
523
if (dmi_check_system(s5k4aa_vflip_dmi_table))
524
val = !val;
525
526
data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
527
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
528
if (err < 0)
529
return err;
530
531
err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
532
if (err < 0)
533
return err;
534
if (val)
535
data &= 0xfe;
536
else
537
data |= 0x01;
538
err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
539
return err;
540
}
541
542
static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
543
{
544
struct sd *sd = (struct sd *) gspca_dev;
545
s32 *sensor_settings = sd->sensor_priv;
546
547
*val = sensor_settings[HFLIP_IDX];
548
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
549
550
return 0;
551
}
552
553
static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
554
{
555
struct sd *sd = (struct sd *) gspca_dev;
556
s32 *sensor_settings = sd->sensor_priv;
557
u8 data = S5K4AA_PAGE_MAP_2;
558
int err;
559
560
sensor_settings[HFLIP_IDX] = val;
561
562
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
563
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
564
if (err < 0)
565
return err;
566
567
err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
568
if (err < 0)
569
return err;
570
571
if (dmi_check_system(s5k4aa_vflip_dmi_table))
572
val = !val;
573
574
data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
575
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
576
if (err < 0)
577
return err;
578
579
err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
580
if (err < 0)
581
return err;
582
if (val)
583
data &= 0xfe;
584
else
585
data |= 0x01;
586
err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
587
return err;
588
}
589
590
static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
591
{
592
struct sd *sd = (struct sd *) gspca_dev;
593
s32 *sensor_settings = sd->sensor_priv;
594
595
*val = sensor_settings[GAIN_IDX];
596
PDEBUG(D_V4L2, "Read gain %d", *val);
597
return 0;
598
}
599
600
static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
601
{
602
struct sd *sd = (struct sd *) gspca_dev;
603
s32 *sensor_settings = sd->sensor_priv;
604
u8 data = S5K4AA_PAGE_MAP_2;
605
int err;
606
607
sensor_settings[GAIN_IDX] = val;
608
609
PDEBUG(D_V4L2, "Set gain to %d", val);
610
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
611
if (err < 0)
612
return err;
613
614
data = val & 0xff;
615
err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
616
617
return err;
618
}
619
620
static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
621
{
622
struct sd *sd = (struct sd *) gspca_dev;
623
s32 *sensor_settings = sd->sensor_priv;
624
625
*val = sensor_settings[BRIGHTNESS_IDX];
626
PDEBUG(D_V4L2, "Read brightness %d", *val);
627
return 0;
628
}
629
630
static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
631
{
632
struct sd *sd = (struct sd *) gspca_dev;
633
s32 *sensor_settings = sd->sensor_priv;
634
u8 data = S5K4AA_PAGE_MAP_2;
635
int err;
636
637
sensor_settings[BRIGHTNESS_IDX] = val;
638
639
PDEBUG(D_V4L2, "Set brightness to %d", val);
640
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
641
if (err < 0)
642
return err;
643
644
data = val & 0xff;
645
return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
646
}
647
648
static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
649
{
650
struct sd *sd = (struct sd *) gspca_dev;
651
s32 *sensor_settings = sd->sensor_priv;
652
653
*val = sensor_settings[NOISE_SUPP_IDX];
654
PDEBUG(D_V4L2, "Read noise %d", *val);
655
return 0;
656
}
657
658
static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
659
{
660
struct sd *sd = (struct sd *) gspca_dev;
661
s32 *sensor_settings = sd->sensor_priv;
662
u8 data = S5K4AA_PAGE_MAP_2;
663
int err;
664
665
sensor_settings[NOISE_SUPP_IDX] = val;
666
667
PDEBUG(D_V4L2, "Set noise to %d", val);
668
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
669
if (err < 0)
670
return err;
671
672
data = val & 0x01;
673
return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
674
}
675
676
void s5k4aa_disconnect(struct sd *sd)
677
{
678
sd->sensor = NULL;
679
kfree(sd->sensor_priv);
680
}
681
682
static void s5k4aa_dump_registers(struct sd *sd)
683
{
684
int address;
685
u8 page, old_page;
686
m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
687
for (page = 0; page < 16; page++) {
688
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
689
info("Dumping the s5k4aa register state for page 0x%x", page);
690
for (address = 0; address <= 0xff; address++) {
691
u8 value = 0;
692
m5602_read_sensor(sd, address, &value, 1);
693
info("register 0x%x contains 0x%x",
694
address, value);
695
}
696
}
697
info("s5k4aa register state dump complete");
698
699
for (page = 0; page < 16; page++) {
700
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
701
info("Probing for which registers that are "
702
"read/write for page 0x%x", page);
703
for (address = 0; address <= 0xff; address++) {
704
u8 old_value, ctrl_value, test_value = 0xff;
705
706
m5602_read_sensor(sd, address, &old_value, 1);
707
m5602_write_sensor(sd, address, &test_value, 1);
708
m5602_read_sensor(sd, address, &ctrl_value, 1);
709
710
if (ctrl_value == test_value)
711
info("register 0x%x is writeable", address);
712
else
713
info("register 0x%x is read only", address);
714
715
/* Restore original value */
716
m5602_write_sensor(sd, address, &old_value, 1);
717
}
718
}
719
info("Read/write register probing complete");
720
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
721
}
722
723