]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/video/gspca/m5602/m5602_s5k83a.c
V4L/DVB (10008): gspca - m5602: Checkpatch.pl fixes on m5602_ov9650.c
[mirror_ubuntu-jammy-kernel.git] / drivers / media / video / gspca / m5602 / m5602_s5k83a.c
CommitLineData
c109f816
EA
1/*
2 * Driver for the s5k83a sensor
3 *
0c505e68 4 * Copyright (C) 2008 Erik Andrén
c109f816
EA
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 "m5602_s5k83a.h"
20
21int s5k83a_probe(struct sd *sd)
22{
23 u8 prod_id = 0, ver_id = 0;
24 int i, err = 0;
25
26 if (force_sensor) {
27 if (force_sensor == S5K83A_SENSOR) {
28 info("Forcing a %s sensor", s5k83a.name);
29 goto sensor_found;
30 }
31 /* If we want to force another sensor, don't try to probe this
32 * one */
33 return -ENODEV;
34 }
35
36 info("Probing for a s5k83a sensor");
37
38 /* Preinit the sensor */
39 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
40 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
41 if (preinit_s5k83a[i][0] == SENSOR)
42 err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1],
43 data, 2);
44 else
45 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
46 data[0]);
47 }
48
49 /* We don't know what register (if any) that contain the product id
50 * Just pick the first addresses that seem to produce the same results
51 * on multiple machines */
52 if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1))
53 return -ENODEV;
54
55 if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1))
56 return -ENODEV;
57
58 if ((prod_id == 0xff) || (ver_id == 0xff))
59 return -ENODEV;
60 else
61 info("Detected a s5k83a sensor");
62
63sensor_found:
64 sd->gspca_dev.cam.cam_mode = s5k83a.modes;
65 sd->gspca_dev.cam.nmodes = s5k83a.nmodes;
d2d7e9ae
EA
66 sd->desc->ctrls = s5k83a.ctrls;
67 sd->desc->nctrls = s5k83a.nctrls;
c109f816
EA
68 return 0;
69}
70
71int s5k83a_read_sensor(struct sd *sd, const u8 address,
bac79f37 72 u8 *i2c_data, const u8 len)
c109f816
EA
73{
74 int err, i;
75
76 do {
77 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
78 } while ((*i2c_data & I2C_BUSY) && !err);
79 if (err < 0)
80 goto out;
81
82 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
83 sd->sensor->i2c_slave_id);
84 if (err < 0)
85 goto out;
86
87 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
88 if (err < 0)
89 goto out;
90
91 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
c109f816
EA
92
93 do {
94 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
95 } while ((*i2c_data & I2C_BUSY) && !err);
96
c109f816
EA
97 for (i = 0; i < len && !len; i++) {
98 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
99
17ea88ae 100 PDEBUG(D_CONF, "Reading sensor register "
c109f816
EA
101 "0x%x containing 0x%x ", address, *i2c_data);
102 }
103
104out:
bac79f37 105 return err;
c109f816
EA
106}
107
108int s5k83a_write_sensor(struct sd *sd, const u8 address,
bac79f37 109 u8 *i2c_data, const u8 len)
c109f816
EA
110{
111 int err, i;
112 u8 *p;
113 struct usb_device *udev = sd->gspca_dev.dev;
114 __u8 *buf = sd->gspca_dev.usb_buf;
115
116 /* No sensor with a data width larger than 16 bits has yet been seen */
117 if (len > 2 || !len)
118 return -EINVAL;
119
120 memcpy(buf, sensor_urb_skeleton,
121 sizeof(sensor_urb_skeleton));
122
123 buf[11] = sd->sensor->i2c_slave_id;
124 buf[15] = address;
125
126 /* Special case larger sensor writes */
127 p = buf + 16;
128
129 /* Copy a four byte write sequence for each byte to be written to */
130 for (i = 0; i < len; i++) {
131 memcpy(p, sensor_urb_skeleton + 16, 4);
132 p[3] = i2c_data[i];
133 p += 4;
17ea88ae 134 PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
c109f816
EA
135 address, i2c_data[i]);
136 }
137
138 /* Copy the tailer */
139 memcpy(p, sensor_urb_skeleton + 20, 4);
140
141 /* Set the total length */
142 p[3] = 0x10 + len;
143
144 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
145 0x04, 0x40, 0x19,
146 0x0000, buf,
147 20 + len * 4, M5602_URB_MSG_TIMEOUT);
148
149 return (err < 0) ? err : 0;
150}
151
152int s5k83a_init(struct sd *sd)
153{
154 int i, err = 0;
155
156 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
157 u8 data[2] = {0x00, 0x00};
158
159 switch (init_s5k83a[i][0]) {
160 case BRIDGE:
161 err = m5602_write_bridge(sd,
162 init_s5k83a[i][1],
163 init_s5k83a[i][2]);
164 break;
165
166 case SENSOR:
167 data[0] = init_s5k83a[i][2];
168 err = s5k83a_write_sensor(sd,
169 init_s5k83a[i][1], data, 1);
170 break;
171
172 case SENSOR_LONG:
173 data[0] = init_s5k83a[i][2];
174 data[1] = init_s5k83a[i][3];
175 err = s5k83a_write_sensor(sd,
176 init_s5k83a[i][1], data, 2);
177 break;
178 default:
179 info("Invalid stream command, exiting init");
180 return -EINVAL;
181 }
182 }
183
184 if (dump_sensor)
185 s5k83a_dump_registers(sd);
186
187 return (err < 0) ? err : 0;
188}
189
190int s5k83a_power_down(struct sd *sd)
191{
192 return 0;
193}
194
195void s5k83a_dump_registers(struct sd *sd)
196{
197 int address;
198 u8 page, old_page;
199 s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
200
201 for (page = 0; page < 16; page++) {
202 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
203 info("Dumping the s5k83a register state for page 0x%x", page);
204 for (address = 0; address <= 0xff; address++) {
205 u8 val = 0;
206 s5k83a_read_sensor(sd, address, &val, 1);
207 info("register 0x%x contains 0x%x",
208 address, val);
209 }
210 }
211 info("s5k83a register state dump complete");
212
213 for (page = 0; page < 16; page++) {
214 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
215 info("Probing for which registers that are read/write "
216 "for page 0x%x", page);
217 for (address = 0; address <= 0xff; address++) {
218 u8 old_val, ctrl_val, test_val = 0xff;
219
220 s5k83a_read_sensor(sd, address, &old_val, 1);
221 s5k83a_write_sensor(sd, address, &test_val, 1);
222 s5k83a_read_sensor(sd, address, &ctrl_val, 1);
223
224 if (ctrl_val == test_val)
225 info("register 0x%x is writeable", address);
226 else
227 info("register 0x%x is read only", address);
228
229 /* Restore original val */
230 s5k83a_write_sensor(sd, address, &old_val, 1);
231 }
232 }
233 info("Read/write register probing complete");
234 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
235}
236
237int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
238{
239 int err;
240 u8 data[2];
241 struct sd *sd = (struct sd *) gspca_dev;
242
243 err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
7b2cd079
EA
244 if (err < 0)
245 goto out;
246
c109f816
EA
247 data[1] = data[1] << 1;
248 *val = data[1];
249
7b2cd079
EA
250out:
251 return err;
c109f816
EA
252}
253
254int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
255{
256 int err;
257 u8 data[2];
258 struct sd *sd = (struct sd *) gspca_dev;
259
260 data[0] = 0x00;
261 data[1] = 0x20;
262 err = s5k83a_write_sensor(sd, 0x14, data, 2);
263 if (err < 0)
7b2cd079 264 goto out;
c109f816
EA
265
266 data[0] = 0x01;
267 data[1] = 0x00;
268 err = s5k83a_write_sensor(sd, 0x0d, data, 2);
269 if (err < 0)
7b2cd079 270 goto out;
c109f816
EA
271
272 /* FIXME: This is not sane, we need to figure out the composition
273 of these registers */
274 data[0] = val >> 3; /* brightness, high 5 bits */
275 data[1] = val >> 1; /* brightness, high 7 bits */
276 err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
277
7b2cd079
EA
278out:
279 return err;
c109f816
EA
280}
281
282int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
283{
284 int err;
285 u8 data;
286 struct sd *sd = (struct sd *) gspca_dev;
287
288 err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
7b2cd079
EA
289 if (err < 0)
290 goto out;
c109f816
EA
291
292 *val = data;
7b2cd079
EA
293
294out:
295 return err;
c109f816
EA
296}
297
298int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
299{
300 int err;
301 u8 data[1];
302 struct sd *sd = (struct sd *) gspca_dev;
303
304 data[0] = val;
305 err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1);
306
7b2cd079 307 return err;
c109f816
EA
308}
309
310int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
311{
312 int err;
313 u8 data[2];
314 struct sd *sd = (struct sd *) gspca_dev;
315
316 err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2);
7b2cd079
EA
317 if (err < 0)
318 goto out;
c109f816
EA
319
320 data[1] = data[1] & 0x3f;
321 if (data[1] > S5K83A_MAXIMUM_GAIN)
322 data[1] = S5K83A_MAXIMUM_GAIN;
323
324 *val = data[1];
325
7b2cd079
EA
326out:
327 return err;
c109f816
EA
328}
329
330int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
331{
18f8fae1 332 int err;
c109f816
EA
333 u8 data[2];
334 struct sd *sd = (struct sd *) gspca_dev;
335
336 data[0] = 0;
337 data[1] = val;
338 err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2);
7b2cd079 339 return err;
c109f816 340}
18f8fae1
EA
341
342int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
343{
344 int err;
345 u8 data[1];
346 struct sd *sd = (struct sd *) gspca_dev;
347
348 data[0] = 0x05;
349 err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
350 if (err < 0)
7b2cd079 351 goto out;
18f8fae1
EA
352
353 err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
354 *val = (data[0] | 0x40) ? 1 : 0;
355
7b2cd079
EA
356out:
357 return err;
18f8fae1
EA
358}
359
360int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
361{
362 int err;
363 u8 data[1];
364 struct sd *sd = (struct sd *) gspca_dev;
365
366 data[0] = 0x05;
367 err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
368 if (err < 0)
7b2cd079 369 goto out;
18f8fae1
EA
370
371 err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
372 if (err < 0)
7b2cd079 373 goto out;
18f8fae1
EA
374
375 /* set or zero six bit, seven is hflip */
376 data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
377 : (data[0] & 0x80) | S5K83A_FLIP_MASK;
378 err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
379 if (err < 0)
7b2cd079 380 goto out;
18f8fae1
EA
381
382 data[0] = (val) ? 0x0b : 0x0a;
383 err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
384
7b2cd079
EA
385out:
386 return err;
18f8fae1
EA
387}
388
389int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
390{
391 int err;
392 u8 data[1];
393 struct sd *sd = (struct sd *) gspca_dev;
394
395 data[0] = 0x05;
396 err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
397 if (err < 0)
7b2cd079 398 goto out;
18f8fae1
EA
399
400 err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
401 *val = (data[0] | 0x80) ? 1 : 0;
402
7b2cd079
EA
403out:
404 return err;
18f8fae1
EA
405}
406
407int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
408{
409 int err;
410 u8 data[1];
411 struct sd *sd = (struct sd *) gspca_dev;
412
413 data[0] = 0x05;
414 err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
415 if (err < 0)
7b2cd079 416 goto out;
18f8fae1
EA
417
418 err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
419 if (err < 0)
7b2cd079 420 goto out;
18f8fae1
EA
421
422 /* set or zero seven bit, six is vflip */
423 data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
424 : (data[0] & 0x40) | S5K83A_FLIP_MASK;
425 err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
426 if (err < 0)
7b2cd079 427 goto out;
18f8fae1
EA
428
429 data[0] = (val) ? 0x0a : 0x0b;
430 err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
7b2cd079
EA
431out:
432 return err;
18f8fae1 433}