V4L/DVB (10009): gspca - m5602: Convert some functions to be static
[linux-2.6] / drivers / media / video / gspca / m5602 / m5602_s5k4aa.c
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 <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_s5k4aa.h"
20
21 static
22     const
23         struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
24         {
25                 .ident = "Fujitsu-Siemens Amilo Xa 2528",
26                 .matches = {
27                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
28                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
29                 }
30         }, {
31                 .ident = "Fujitsu-Siemens Amilo Xi 2550",
32                 .matches = {
33                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
34                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
35                 }
36         }, {
37                 .ident = "MSI GX700",
38                 .matches = {
39                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
40                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
41                         DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
42                 }
43         }, {
44                 .ident = "MSI GX700/GX705/EX700",
45                 .matches = {
46                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
47                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
48                 }
49         },
50         { }
51 };
52
53 static void s5k4aa_dump_registers(struct sd *sd);
54
55 int s5k4aa_probe(struct sd *sd)
56 {
57         u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
58         const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
59         int i, err = 0;
60
61         if (force_sensor) {
62                 if (force_sensor == S5K4AA_SENSOR) {
63                         info("Forcing a %s sensor", s5k4aa.name);
64                         goto sensor_found;
65                 }
66                 /* If we want to force another sensor, don't try to probe this
67                  * one */
68                 return -ENODEV;
69         }
70
71         info("Probing for a s5k4aa sensor");
72
73         /* Preinit the sensor */
74         for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
75                 u8 data[2] = {0x00, 0x00};
76
77                 switch (preinit_s5k4aa[i][0]) {
78                 case BRIDGE:
79                         err = m5602_write_bridge(sd,
80                                                  preinit_s5k4aa[i][1],
81                                                  preinit_s5k4aa[i][2]);
82                         break;
83
84                 case SENSOR:
85                         data[0] = preinit_s5k4aa[i][2];
86                         err = s5k4aa_write_sensor(sd,
87                                                   preinit_s5k4aa[i][1],
88                                                   data, 1);
89                         break;
90
91                 case SENSOR_LONG:
92                         data[0] = preinit_s5k4aa[i][2];
93                         data[1] = preinit_s5k4aa[i][3];
94                         err = s5k4aa_write_sensor(sd,
95                                                   preinit_s5k4aa[i][1],
96                                                   data, 2);
97                         break;
98                 default:
99                         info("Invalid stream command, exiting init");
100                         return -EINVAL;
101                 }
102         }
103
104         /* Test some registers, but we don't know their exact meaning yet */
105         if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
106                 return -ENODEV;
107
108         if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
109                 return -ENODEV;
110         else
111                 info("Detected a s5k4aa sensor");
112
113 sensor_found:
114         sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
115         sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
116         sd->desc->ctrls = s5k4aa.ctrls;
117         sd->desc->nctrls = s5k4aa.nctrls;
118
119         return 0;
120 }
121
122 int s5k4aa_read_sensor(struct sd *sd, const u8 address,
123                        u8 *i2c_data, const u8 len)
124 {
125         int err, i;
126
127         do {
128                 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
129         } while ((*i2c_data & I2C_BUSY) && !err);
130         if (err < 0)
131                 goto out;
132
133         err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
134                                  sd->sensor->i2c_slave_id);
135         if (err < 0)
136                 goto out;
137
138         err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
139         if (err < 0)
140                 goto out;
141
142         err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
143         if (err < 0)
144                 goto out;
145
146         do {
147                 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
148         } while ((*i2c_data & I2C_BUSY) && !err);
149         if (err < 0)
150                 goto out;
151
152         for (i = 0; (i < len) && !err; i++) {
153                 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
154
155                 PDEBUG(D_CONF, "Reading sensor register "
156                                   "0x%x containing 0x%x ", address, *i2c_data);
157         }
158 out:
159         return err;
160 }
161
162 int s5k4aa_write_sensor(struct sd *sd, const u8 address,
163                         u8 *i2c_data, const u8 len)
164 {
165         int err, i;
166         u8 *p;
167         struct usb_device *udev = sd->gspca_dev.dev;
168         __u8 *buf = sd->gspca_dev.usb_buf;
169
170         /* No sensor with a data width larger than 16 bits has yet been seen */
171         if (len > 2 || !len)
172                 return -EINVAL;
173
174         memcpy(buf, sensor_urb_skeleton,
175                sizeof(sensor_urb_skeleton));
176
177         buf[11] = sd->sensor->i2c_slave_id;
178         buf[15] = address;
179
180         /* Special case larger sensor writes */
181         p = buf + 16;
182
183         /* Copy a four byte write sequence for each byte to be written to */
184         for (i = 0; i < len; i++) {
185                 memcpy(p, sensor_urb_skeleton + 16, 4);
186                 p[3] = i2c_data[i];
187                 p += 4;
188                 PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
189                        address, i2c_data[i]);
190         }
191
192         /* Copy the tailer */
193         memcpy(p, sensor_urb_skeleton + 20, 4);
194
195         /* Set the total length */
196         p[3] = 0x10 + len;
197
198         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
199                               0x04, 0x40, 0x19,
200                               0x0000, buf,
201                               20 + len * 4, M5602_URB_MSG_TIMEOUT);
202
203         return (err < 0) ? err : 0;
204 }
205
206 int s5k4aa_init(struct sd *sd)
207 {
208         int i, err = 0;
209
210         for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
211                 u8 data[2] = {0x00, 0x00};
212
213                 switch (init_s5k4aa[i][0]) {
214                 case BRIDGE:
215                         err = m5602_write_bridge(sd,
216                                 init_s5k4aa[i][1],
217                                 init_s5k4aa[i][2]);
218                         break;
219
220                 case SENSOR:
221                         data[0] = init_s5k4aa[i][2];
222                         err = s5k4aa_write_sensor(sd,
223                                 init_s5k4aa[i][1], data, 1);
224                         break;
225
226                 case SENSOR_LONG:
227                         data[0] = init_s5k4aa[i][2];
228                         data[1] = init_s5k4aa[i][3];
229                         err = s5k4aa_write_sensor(sd,
230                                 init_s5k4aa[i][1], data, 2);
231                         break;
232                 default:
233                         info("Invalid stream command, exiting init");
234                         return -EINVAL;
235                 }
236         }
237
238         if (dump_sensor)
239                 s5k4aa_dump_registers(sd);
240
241         if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
242                 u8 data = 0x02;
243                 info("vertical flip quirk active");
244                 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
245                 s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
246                 data |= S5K4AA_RM_V_FLIP;
247                 data &= ~S5K4AA_RM_H_FLIP;
248                 s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
249
250                 /* Decrement COLSTART to preserve color order (BGGR) */
251                 s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
252                 data--;
253                 s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
254
255                 /* Increment ROWSTART to preserve color order (BGGR) */
256                 s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
257                 data++;
258                 s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
259         }
260
261         return (err < 0) ? err : 0;
262 }
263
264 int s5k4aa_power_down(struct sd *sd)
265 {
266         return 0;
267 }
268
269 int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
270 {
271         struct sd *sd = (struct sd *) gspca_dev;
272         u8 data = S5K4AA_PAGE_MAP_2;
273         int err;
274
275         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
276         if (err < 0)
277                 goto out;
278
279         err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
280         if (err < 0)
281                 goto out;
282
283         *val = data << 8;
284         err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
285         *val |= data;
286         PDEBUG(D_V4L2, "Read exposure %d", *val);
287 out:
288         return err;
289 }
290
291 int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
292 {
293         struct sd *sd = (struct sd *) gspca_dev;
294         u8 data = S5K4AA_PAGE_MAP_2;
295         int err;
296
297         PDEBUG(D_V4L2, "Set exposure to %d", val);
298         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
299         if (err < 0)
300                 goto out;
301         data = (val >> 8) & 0xff;
302         err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
303         if (err < 0)
304                 goto out;
305         data = val & 0xff;
306         err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
307 out:
308         return err;
309 }
310
311 int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
312 {
313         struct sd *sd = (struct sd *) gspca_dev;
314         u8 data = S5K4AA_PAGE_MAP_2;
315         int err;
316
317         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
318         if (err < 0)
319                 goto out;
320
321         err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
322         *val = (data & S5K4AA_RM_V_FLIP) >> 7;
323         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
324
325 out:
326         return err;
327 }
328
329 int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
330 {
331         struct sd *sd = (struct sd *) gspca_dev;
332         u8 data = S5K4AA_PAGE_MAP_2;
333         int err;
334
335         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
336         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
337         if (err < 0)
338                 goto out;
339         err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
340         if (err < 0)
341                 goto out;
342         data = ((data & ~S5K4AA_RM_V_FLIP)
343                         | ((val & 0x01) << 7));
344         err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
345         if (err < 0)
346                 goto out;
347
348         if (val) {
349                 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
350                 if (err < 0)
351                         goto out;
352
353                 data++;
354                 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
355         } else {
356                 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
357                 if (err < 0)
358                         goto out;
359
360                 data--;
361                 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
362         }
363 out:
364         return err;
365 }
366
367 int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
368 {
369         struct sd *sd = (struct sd *) gspca_dev;
370         u8 data = S5K4AA_PAGE_MAP_2;
371         int err;
372
373         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
374         if (err < 0)
375                 goto out;
376
377         err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
378         *val = (data & S5K4AA_RM_H_FLIP) >> 6;
379         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
380 out:
381         return err;
382 }
383
384 int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
385 {
386         struct sd *sd = (struct sd *) gspca_dev;
387         u8 data = S5K4AA_PAGE_MAP_2;
388         int err;
389
390         PDEBUG(D_V4L2, "Set horizontal flip to %d",
391                val);
392         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
393         if (err < 0)
394                 goto out;
395         err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
396         if (err < 0)
397                 goto out;
398
399         data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
400         err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
401         if (err < 0)
402                 goto out;
403
404         if (val) {
405                 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
406                 if (err < 0)
407                         goto out;
408                 data++;
409                 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
410                 if (err < 0)
411                         goto out;
412         } else {
413                 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
414                 if (err < 0)
415                         goto out;
416                 data--;
417                 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
418         }
419 out:
420         return err;
421 }
422
423 int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
424 {
425         struct sd *sd = (struct sd *) gspca_dev;
426         u8 data = S5K4AA_PAGE_MAP_2;
427         int err;
428
429         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
430         if (err < 0)
431                 goto out;
432
433         err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
434         *val = data;
435         PDEBUG(D_V4L2, "Read gain %d", *val);
436
437 out:
438         return err;
439 }
440
441 int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
442 {
443         struct sd *sd = (struct sd *) gspca_dev;
444         u8 data = S5K4AA_PAGE_MAP_2;
445         int err;
446
447         PDEBUG(D_V4L2, "Set gain to %d", val);
448         err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
449         if (err < 0)
450                 goto out;
451
452         data = val & 0xff;
453         err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
454
455 out:
456         return err;
457 }
458
459 static void s5k4aa_dump_registers(struct sd *sd)
460 {
461         int address;
462         u8 page, old_page;
463         s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
464         for (page = 0; page < 16; page++) {
465                 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
466                 info("Dumping the s5k4aa register state for page 0x%x", page);
467                 for (address = 0; address <= 0xff; address++) {
468                         u8 value = 0;
469                         s5k4aa_read_sensor(sd, address, &value, 1);
470                         info("register 0x%x contains 0x%x",
471                              address, value);
472                 }
473         }
474         info("s5k4aa register state dump complete");
475
476         for (page = 0; page < 16; page++) {
477                 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
478                 info("Probing for which registers that are "
479                      "read/write for page 0x%x", page);
480                 for (address = 0; address <= 0xff; address++) {
481                         u8 old_value, ctrl_value, test_value = 0xff;
482
483                         s5k4aa_read_sensor(sd, address, &old_value, 1);
484                         s5k4aa_write_sensor(sd, address, &test_value, 1);
485                         s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
486
487                         if (ctrl_value == test_value)
488                                 info("register 0x%x is writeable", address);
489                         else
490                                 info("register 0x%x is read only", address);
491
492                         /* Restore original value */
493                         s5k4aa_write_sensor(sd, address, &old_value, 1);
494                 }
495         }
496         info("Read/write register probing complete");
497         s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
498 }