V4L/DVB (9279): gspca: Correct some copyright headers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / gspca / m5602 / m5602_s5k4aa.c
blob77173b687a171a1a391ea7b476fa1f59977ec0c7
1 /*
2 * Driver for the s5k4aa sensor
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>
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
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.
19 #include "m5602_s5k4aa.h"
21 int s5k4aa_probe(struct sd *sd)
23 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
24 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
25 int i, err = 0;
27 if (force_sensor) {
28 if (force_sensor == S5K4AA_SENSOR) {
29 info("Forcing a %s sensor", s5k4aa.name);
30 goto sensor_found;
32 /* If we want to force another sensor, don't try to probe this
33 * one */
34 return -ENODEV;
37 info("Probing for a s5k4aa sensor");
39 /* Preinit the sensor */
40 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
41 u8 data[2] = {0x00, 0x00};
43 switch (preinit_s5k4aa[i][0]) {
44 case BRIDGE:
45 err = m5602_write_bridge(sd,
46 preinit_s5k4aa[i][1],
47 preinit_s5k4aa[i][2]);
48 break;
50 case SENSOR:
51 data[0] = preinit_s5k4aa[i][2];
52 err = s5k4aa_write_sensor(sd,
53 preinit_s5k4aa[i][1],
54 data, 1);
55 break;
57 case SENSOR_LONG:
58 data[0] = preinit_s5k4aa[i][2];
59 data[1] = preinit_s5k4aa[i][3];
60 err = s5k4aa_write_sensor(sd,
61 preinit_s5k4aa[i][1],
62 data, 2);
63 break;
64 default:
65 info("Invalid stream command, exiting init");
66 return -EINVAL;
70 /* Test some registers, but we don't know their exact meaning yet */
71 if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
72 return -ENODEV;
74 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
75 return -ENODEV;
76 else
77 info("Detected a s5k4aa sensor");
78 sensor_found:
79 sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
80 sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
81 sd->desc->ctrls = s5k4aa.ctrls;
82 sd->desc->nctrls = s5k4aa.nctrls;
84 return 0;
87 int s5k4aa_read_sensor(struct sd *sd, const u8 address,
88 u8 *i2c_data, const u8 len)
90 int err, i;
92 do {
93 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
94 } while ((*i2c_data & I2C_BUSY) && !err);
95 if (err < 0)
96 goto out;
98 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
99 sd->sensor->i2c_slave_id);
100 if (err < 0)
101 goto out;
103 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
104 if (err < 0)
105 goto out;
107 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
108 if (err < 0)
109 goto out;
111 do {
112 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
113 } while ((*i2c_data & I2C_BUSY) && !err);
114 if (err < 0)
115 goto out;
117 for (i = 0; (i < len) & !err; i++) {
118 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
120 PDEBUG(DBG_TRACE, "Reading sensor register "
121 "0x%x containing 0x%x ", address, *i2c_data);
123 out:
124 return (err < 0) ? err : 0;
127 int s5k4aa_write_sensor(struct sd *sd, const u8 address,
128 u8 *i2c_data, const u8 len)
130 int err, i;
131 u8 *p;
132 struct usb_device *udev = sd->gspca_dev.dev;
133 __u8 *buf = sd->gspca_dev.usb_buf;
135 /* No sensor with a data width larger than 16 bits has yet been seen */
136 if (len > 2 || !len)
137 return -EINVAL;
139 memcpy(buf, sensor_urb_skeleton,
140 sizeof(sensor_urb_skeleton));
142 buf[11] = sd->sensor->i2c_slave_id;
143 buf[15] = address;
145 /* Special case larger sensor writes */
146 p = buf + 16;
148 /* Copy a four byte write sequence for each byte to be written to */
149 for (i = 0; i < len; i++) {
150 memcpy(p, sensor_urb_skeleton + 16, 4);
151 p[3] = i2c_data[i];
152 p += 4;
153 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
154 address, i2c_data[i]);
157 /* Copy the tailer */
158 memcpy(p, sensor_urb_skeleton + 20, 4);
160 /* Set the total length */
161 p[3] = 0x10 + len;
163 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
164 0x04, 0x40, 0x19,
165 0x0000, buf,
166 20 + len * 4, M5602_URB_MSG_TIMEOUT);
168 return (err < 0) ? err : 0;
171 int s5k4aa_init(struct sd *sd)
173 int i, err = 0;
175 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
176 u8 data[2] = {0x00, 0x00};
178 switch (init_s5k4aa[i][0]) {
179 case BRIDGE:
180 err = m5602_write_bridge(sd,
181 init_s5k4aa[i][1],
182 init_s5k4aa[i][2]);
183 break;
185 case SENSOR:
186 data[0] = init_s5k4aa[i][2];
187 err = s5k4aa_write_sensor(sd,
188 init_s5k4aa[i][1], data, 1);
189 break;
191 case SENSOR_LONG:
192 data[0] = init_s5k4aa[i][2];
193 data[1] = init_s5k4aa[i][3];
194 err = s5k4aa_write_sensor(sd,
195 init_s5k4aa[i][1], data, 2);
196 break;
197 default:
198 info("Invalid stream command, exiting init");
199 return -EINVAL;
203 if (dump_sensor)
204 s5k4aa_dump_registers(sd);
206 if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
207 u8 data = 0x02;
208 info("vertical flip quirk active");
209 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
210 s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
211 data |= S5K4AA_RM_V_FLIP;
212 data &= ~S5K4AA_RM_H_FLIP;
213 s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
215 /* Decrement COLSTART to preserve color order (BGGR) */
216 s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
217 data--;
218 s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
220 /* Increment ROWSTART to preserve color order (BGGR) */
221 s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
222 data++;
223 s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
226 return (err < 0) ? err : 0;
229 int s5k4aa_power_down(struct sd *sd)
231 return 0;
234 int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
236 struct sd *sd = (struct sd *) gspca_dev;
237 u8 data = S5K4AA_PAGE_MAP_2;
238 int err;
240 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
241 if (err < 0)
242 goto out;
244 err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
245 if (err < 0)
246 goto out;
248 *val = data << 8;
249 err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
250 *val |= data;
251 PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
252 out:
253 return (err < 0) ? err : 0;
256 int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
258 struct sd *sd = (struct sd *) gspca_dev;
259 u8 data = S5K4AA_PAGE_MAP_2;
260 int err;
262 PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val);
263 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
264 if (err < 0)
265 goto out;
266 data = (val >> 8) & 0xff;
267 err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
268 if (err < 0)
269 goto out;
270 data = val & 0xff;
271 err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
272 out:
273 return (err < 0) ? err : 0;
276 int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
278 struct sd *sd = (struct sd *) gspca_dev;
279 u8 data = S5K4AA_PAGE_MAP_2;
280 int err;
282 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
283 if (err < 0)
284 goto out;
286 err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
287 *val = (data & S5K4AA_RM_V_FLIP) >> 7;
288 PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
290 out:
291 return (err < 0) ? err : 0;
294 int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
296 struct sd *sd = (struct sd *) gspca_dev;
297 u8 data = S5K4AA_PAGE_MAP_2;
298 int err;
300 PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
301 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
302 if (err < 0)
303 goto out;
304 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
305 if (err < 0)
306 goto out;
307 data = ((data & ~S5K4AA_RM_V_FLIP)
308 | ((val & 0x01) << 7));
309 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
310 if (err < 0)
311 goto out;
313 if (val) {
314 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
315 if (err < 0)
316 goto out;
318 data++;
319 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
320 } else {
321 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
322 if (err < 0)
323 goto out;
325 data--;
326 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
328 out:
329 return (err < 0) ? err : 0;
332 int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
334 struct sd *sd = (struct sd *) gspca_dev;
335 u8 data = S5K4AA_PAGE_MAP_2;
336 int err;
338 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
339 if (err < 0)
340 goto out;
342 err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
343 *val = (data & S5K4AA_RM_H_FLIP) >> 6;
344 PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
345 out:
346 return (err < 0) ? err : 0;
349 int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
351 struct sd *sd = (struct sd *) gspca_dev;
352 u8 data = S5K4AA_PAGE_MAP_2;
353 int err;
355 PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d",
356 val);
357 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
358 if (err < 0)
359 goto out;
360 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
361 if (err < 0)
362 goto out;
364 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
365 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
366 if (err < 0)
367 goto out;
369 if (val) {
370 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
371 if (err < 0)
372 goto out;
373 data++;
374 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
375 if (err < 0)
376 goto out;
377 } else {
378 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
379 if (err < 0)
380 goto out;
381 data--;
382 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
384 out:
385 return (err < 0) ? err : 0;
388 int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
390 struct sd *sd = (struct sd *) gspca_dev;
391 u8 data = S5K4AA_PAGE_MAP_2;
392 int err;
394 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
395 if (err < 0)
396 goto out;
398 err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
399 *val = data;
400 PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
402 out:
403 return (err < 0) ? err : 0;
406 int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
408 struct sd *sd = (struct sd *) gspca_dev;
409 u8 data = S5K4AA_PAGE_MAP_2;
410 int err;
412 PDEBUG(DBG_V4L2_CID, "Set gain to %d", val);
413 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
414 if (err < 0)
415 goto out;
417 data = val & 0xff;
418 err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
420 out:
421 return (err < 0) ? err : 0;
424 void s5k4aa_dump_registers(struct sd *sd)
426 int address;
427 u8 page, old_page;
428 s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
429 for (page = 0; page < 16; page++) {
430 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
431 info("Dumping the s5k4aa register state for page 0x%x", page);
432 for (address = 0; address <= 0xff; address++) {
433 u8 value = 0;
434 s5k4aa_read_sensor(sd, address, &value, 1);
435 info("register 0x%x contains 0x%x",
436 address, value);
439 info("s5k4aa register state dump complete");
441 for (page = 0; page < 16; page++) {
442 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
443 info("Probing for which registers that are "
444 "read/write for page 0x%x", page);
445 for (address = 0; address <= 0xff; address++) {
446 u8 old_value, ctrl_value, test_value = 0xff;
448 s5k4aa_read_sensor(sd, address, &old_value, 1);
449 s5k4aa_write_sensor(sd, address, &test_value, 1);
450 s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
452 if (ctrl_value == test_value)
453 info("register 0x%x is writeable", address);
454 else
455 info("register 0x%x is read only", address);
457 /* Restore original value */
458 s5k4aa_write_sensor(sd, address, &old_value, 1);
461 info("Read/write register probing complete");
462 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);