]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame_incremental - drivers/media/video/gspca/m5602/m5602_s5k83a.c
V4L/DVB (11631): gspca - m5602: Remove useless error check
[mirror_ubuntu-jammy-kernel.git] / drivers / media / video / gspca / m5602 / m5602_s5k83a.c
... / ...
CommitLineData
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
47const static 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);
127int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip);
128
129int s5k83a_probe(struct sd *sd)
130{
131 struct s5k83a_priv *sens_priv;
132 u8 prod_id = 0, ver_id = 0;
133 int i, err = 0;
134
135 if (force_sensor) {
136 if (force_sensor == S5K83A_SENSOR) {
137 info("Forcing a %s sensor", s5k83a.name);
138 goto sensor_found;
139 }
140 /* If we want to force another sensor, don't try to probe this
141 * one */
142 return -ENODEV;
143 }
144
145 info("Probing for a s5k83a sensor");
146
147 /* Preinit the sensor */
148 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
149 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
150 if (preinit_s5k83a[i][0] == SENSOR)
151 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
152 data, 2);
153 else
154 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
155 data[0]);
156 }
157
158 /* We don't know what register (if any) that contain the product id
159 * Just pick the first addresses that seem to produce the same results
160 * on multiple machines */
161 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
162 return -ENODEV;
163
164 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
165 return -ENODEV;
166
167 if ((prod_id == 0xff) || (ver_id == 0xff))
168 return -ENODEV;
169 else
170 info("Detected a s5k83a sensor");
171
172sensor_found:
173 sens_priv = kmalloc(
174 sizeof(struct s5k83a_priv), GFP_KERNEL);
175 if (!sens_priv)
176 return -ENOMEM;
177
178 sens_priv->settings =
179 kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
180 if (!sens_priv->settings)
181 return -ENOMEM;
182
183 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
184 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
185 sd->desc->ctrls = s5k83a_ctrls;
186 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
187
188 /* null the pointer! thread is't running now */
189 sens_priv->rotation_thread = NULL;
190
191 for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
192 sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
193
194 sd->sensor_priv = sens_priv;
195 return 0;
196}
197
198int s5k83a_init(struct sd *sd)
199{
200 int i, err = 0;
201
202 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
203 u8 data[2] = {0x00, 0x00};
204
205 switch (init_s5k83a[i][0]) {
206 case BRIDGE:
207 err = m5602_write_bridge(sd,
208 init_s5k83a[i][1],
209 init_s5k83a[i][2]);
210 break;
211
212 case SENSOR:
213 data[0] = init_s5k83a[i][2];
214 err = m5602_write_sensor(sd,
215 init_s5k83a[i][1], data, 1);
216 break;
217
218 case SENSOR_LONG:
219 data[0] = init_s5k83a[i][2];
220 data[1] = init_s5k83a[i][3];
221 err = m5602_write_sensor(sd,
222 init_s5k83a[i][1], data, 2);
223 break;
224 default:
225 info("Invalid stream command, exiting init");
226 return -EINVAL;
227 }
228 }
229
230 if (dump_sensor)
231 s5k83a_dump_registers(sd);
232
233 return (err < 0) ? err : 0;
234}
235
236static int rotation_thread_function(void *data)
237{
238 struct sd *sd = (struct sd *) data;
239 struct s5k83a_priv *sens_priv = sd->sensor_priv;
240 u8 reg, previous_rotation = 0;
241 __s32 vflip, hflip;
242
243 set_current_state(TASK_INTERRUPTIBLE);
244 while (!schedule_timeout(100)) {
245 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
246 break;
247
248 s5k83a_get_rotation(sd, &reg);
249 if (previous_rotation != reg) {
250 previous_rotation = reg;
251 info("Camera was flipped");
252
253 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
254 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
255
256 if (reg) {
257 vflip = !vflip;
258 hflip = !hflip;
259 }
260 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
261 }
262
263 mutex_unlock(&sd->gspca_dev.usb_lock);
264 set_current_state(TASK_INTERRUPTIBLE);
265 }
266
267 /* return to "front" flip */
268 if (previous_rotation) {
269 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
270 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
271 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
272 }
273
274 sens_priv->rotation_thread = NULL;
275 return 0;
276}
277
278int s5k83a_start(struct sd *sd)
279{
280 struct s5k83a_priv *sens_priv = sd->sensor_priv;
281
282 /* Create another thread, polling the GPIO ports of the camera to check
283 if it got rotated. This is how the windows driver does it so we have
284 to assume that there is no better way of accomplishing this */
285 sens_priv->rotation_thread = kthread_create(rotation_thread_function, sd, "rotation thread");
286 wake_up_process(sens_priv->rotation_thread);
287
288 return s5k83a_set_led_indication(sd, 1);
289}
290
291int s5k83a_stop(struct sd *sd)
292{
293 struct s5k83a_priv *sens_priv = sd->sensor_priv;
294
295 if (sens_priv->rotation_thread)
296 kthread_stop(sens_priv->rotation_thread);
297
298 return s5k83a_set_led_indication(sd, 0);
299}
300
301void s5k83a_disconnect(struct sd *sd)
302{
303 struct s5k83a_priv *sens_priv = sd->sensor_priv;
304
305 s5k83a_stop(sd);
306
307 sd->sensor = NULL;
308 kfree(sens_priv->settings);
309 kfree(sens_priv);
310}
311
312static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
313{
314 struct sd *sd = (struct sd *) gspca_dev;
315 struct s5k83a_priv *sens_priv = sd->sensor_priv;
316
317 *val = sens_priv->settings[GAIN_IDX];
318 return 0;
319}
320
321static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
322{
323 int err;
324 u8 data[2];
325 struct sd *sd = (struct sd *) gspca_dev;
326 struct s5k83a_priv *sens_priv = sd->sensor_priv;
327
328 sens_priv->settings[GAIN_IDX] = val;
329
330 data[0] = 0x00;
331 data[1] = 0x20;
332 err = m5602_write_sensor(sd, 0x14, data, 2);
333 if (err < 0)
334 return err;
335
336 data[0] = 0x01;
337 data[1] = 0x00;
338 err = m5602_write_sensor(sd, 0x0d, data, 2);
339 if (err < 0)
340 return err;
341
342 /* FIXME: This is not sane, we need to figure out the composition
343 of these registers */
344 data[0] = val >> 3; /* gain, high 5 bits */
345 data[1] = val >> 1; /* gain, high 7 bits */
346 err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
347
348 return err;
349}
350
351static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
352{
353 struct sd *sd = (struct sd *) gspca_dev;
354 struct s5k83a_priv *sens_priv = sd->sensor_priv;
355
356 *val = sens_priv->settings[BRIGHTNESS_IDX];
357 return 0;
358}
359
360static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
361{
362 int err;
363 u8 data[1];
364 struct sd *sd = (struct sd *) gspca_dev;
365 struct s5k83a_priv *sens_priv = sd->sensor_priv;
366
367 sens_priv->settings[BRIGHTNESS_IDX] = val;
368 data[0] = val;
369 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
370 return err;
371}
372
373static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
374{
375 struct sd *sd = (struct sd *) gspca_dev;
376 struct s5k83a_priv *sens_priv = sd->sensor_priv;
377
378 *val = sens_priv->settings[EXPOSURE_IDX];
379 return 0;
380}
381
382static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
383{
384 int err;
385 u8 data[2];
386 struct sd *sd = (struct sd *) gspca_dev;
387 struct s5k83a_priv *sens_priv = sd->sensor_priv;
388
389 sens_priv->settings[EXPOSURE_IDX] = val;
390 data[0] = 0;
391 data[1] = val;
392 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
393 return err;
394}
395
396static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
397{
398 struct sd *sd = (struct sd *) gspca_dev;
399 struct s5k83a_priv *sens_priv = sd->sensor_priv;
400
401 *val = sens_priv->settings[VFLIP_IDX];
402 return 0;
403}
404
405int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip)
406{
407 int err;
408 u8 data[1];
409 struct sd *sd = (struct sd *) gspca_dev;
410
411 data[0] = 0x05;
412 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
413 if (err < 0)
414 return err;
415
416 /* six bit is vflip, seven is hflip */
417 data[0] = S5K83A_FLIP_MASK;
418 data[0] = (vflip) ? data[0] | 0x40 : data[0];
419 data[0] = (hflip) ? data[0] | 0x80 : data[0];
420
421 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
422 if (err < 0)
423 return err;
424
425 data[0] = (vflip) ? 0x0b : 0x0a;
426 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
427 if (err < 0)
428 return err;
429
430 data[0] = (hflip) ? 0x0a : 0x0b;
431 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
432 return err;
433}
434
435static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
436{
437 int err;
438 u8 reg;
439 __s32 hflip;
440 struct sd *sd = (struct sd *) gspca_dev;
441 struct s5k83a_priv *sens_priv = sd->sensor_priv;
442
443 sens_priv->settings[VFLIP_IDX] = val;
444
445 s5k83a_get_hflip(gspca_dev, &hflip);
446
447 err = s5k83a_get_rotation(sd, &reg);
448 if (err < 0)
449 return err;
450 if (reg) {
451 val = !val;
452 hflip = !hflip;
453 }
454
455 err = s5k83a_set_flip_real(gspca_dev, val, hflip);
456 return err;
457}
458
459static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
460{
461 struct sd *sd = (struct sd *) gspca_dev;
462 struct s5k83a_priv *sens_priv = sd->sensor_priv;
463
464 *val = sens_priv->settings[HFLIP_IDX];
465 return 0;
466}
467
468static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
469{
470 int err;
471 u8 reg;
472 __s32 vflip;
473 struct sd *sd = (struct sd *) gspca_dev;
474 struct s5k83a_priv *sens_priv = sd->sensor_priv;
475
476 sens_priv->settings[HFLIP_IDX] = val;
477
478 s5k83a_get_vflip(gspca_dev, &vflip);
479
480 err = s5k83a_get_rotation(sd, &reg);
481 if (err < 0)
482 return err;
483 if (reg) {
484 val = !val;
485 vflip = !vflip;
486 }
487
488 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
489 return err;
490}
491
492static int s5k83a_set_led_indication(struct sd *sd, u8 val)
493{
494 int err = 0;
495 u8 data[1];
496
497 err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
498 if (err < 0)
499 return err;
500
501 if (val)
502 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
503 else
504 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
505
506 err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
507
508 return (err < 0) ? err : 0;
509}
510
511/* Get camera rotation on Acer notebooks */
512static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
513{
514 int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
515 *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
516 return err;
517}
518
519static void s5k83a_dump_registers(struct sd *sd)
520{
521 int address;
522 u8 page, old_page;
523 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
524
525 for (page = 0; page < 16; page++) {
526 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
527 info("Dumping the s5k83a register state for page 0x%x", page);
528 for (address = 0; address <= 0xff; address++) {
529 u8 val = 0;
530 m5602_read_sensor(sd, address, &val, 1);
531 info("register 0x%x contains 0x%x",
532 address, val);
533 }
534 }
535 info("s5k83a register state dump complete");
536
537 for (page = 0; page < 16; page++) {
538 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
539 info("Probing for which registers that are read/write "
540 "for page 0x%x", page);
541 for (address = 0; address <= 0xff; address++) {
542 u8 old_val, ctrl_val, test_val = 0xff;
543
544 m5602_read_sensor(sd, address, &old_val, 1);
545 m5602_write_sensor(sd, address, &test_val, 1);
546 m5602_read_sensor(sd, address, &ctrl_val, 1);
547
548 if (ctrl_val == test_val)
549 info("register 0x%x is writeable", address);
550 else
551 info("register 0x%x is read only", address);
552
553 /* Restore original val */
554 m5602_write_sensor(sd, address, &old_val, 1);
555 }
556 }
557 info("Read/write register probing complete");
558 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
559}