2 * Driver for the po1030 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_po1030.h"
21 static struct v4l2_pix_format po1030_modes[] = {
27 .sizeimage = 640 * 480,
29 .colorspace = V4L2_COLORSPACE_SRGB,
34 const static struct ctrl po1030_ctrls[] = {
38 .type = V4L2_CTRL_TYPE_INTEGER,
43 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
44 .flags = V4L2_CTRL_FLAG_SLIDER
46 .set = po1030_set_gain,
47 .get = po1030_get_gain
50 .id = V4L2_CID_EXPOSURE,
51 .type = V4L2_CTRL_TYPE_INTEGER,
56 .default_value = PO1030_EXPOSURE_DEFAULT,
57 .flags = V4L2_CTRL_FLAG_SLIDER
59 .set = po1030_set_exposure,
60 .get = po1030_get_exposure
63 .id = V4L2_CID_RED_BALANCE,
64 .type = V4L2_CTRL_TYPE_INTEGER,
65 .name = "red balance",
69 .default_value = PO1030_RED_GAIN_DEFAULT,
70 .flags = V4L2_CTRL_FLAG_SLIDER
72 .set = po1030_set_red_balance,
73 .get = po1030_get_red_balance
76 .id = V4L2_CID_BLUE_BALANCE,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "blue balance",
82 .default_value = PO1030_BLUE_GAIN_DEFAULT,
83 .flags = V4L2_CTRL_FLAG_SLIDER
85 .set = po1030_set_blue_balance,
86 .get = po1030_get_blue_balance
90 .type = V4L2_CTRL_TYPE_BOOLEAN,
91 .name = "horizontal flip",
97 .set = po1030_set_hflip,
98 .get = po1030_get_hflip
101 .id = V4L2_CID_VFLIP,
102 .type = V4L2_CTRL_TYPE_BOOLEAN,
103 .name = "vertical flip",
109 .set = po1030_set_vflip,
110 .get = po1030_get_vflip
114 static void po1030_dump_registers(struct sd *sd);
116 int po1030_probe(struct sd *sd)
118 u8 prod_id = 0, ver_id = 0, i;
121 if (force_sensor == PO1030_SENSOR) {
122 info("Forcing a %s sensor", po1030.name);
125 /* If we want to force another sensor, don't try to probe this
130 info("Probing for a po1030 sensor");
132 /* Run the pre-init to actually probe the unit */
133 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
134 u8 data = preinit_po1030[i][2];
135 if (preinit_po1030[i][0] == SENSOR)
136 m5602_write_sensor(sd,
137 preinit_po1030[i][1], &data, 1);
139 m5602_write_bridge(sd, preinit_po1030[i][1], data);
142 if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
145 if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
148 if ((prod_id == 0x02) && (ver_id == 0xef)) {
149 info("Detected a po1030 sensor");
155 sd->gspca_dev.cam.cam_mode = po1030_modes;
156 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
157 sd->desc->ctrls = po1030_ctrls;
158 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
162 int po1030_init(struct sd *sd)
166 /* Init the sensor */
167 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
168 u8 data[2] = {0x00, 0x00};
170 switch (init_po1030[i][0]) {
172 err = m5602_write_bridge(sd,
178 data[0] = init_po1030[i][2];
179 err = m5602_write_sensor(sd,
180 init_po1030[i][1], data, 1);
184 info("Invalid stream command, exiting init");
190 po1030_dump_registers(sd);
195 int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
197 struct sd *sd = (struct sd *) gspca_dev;
201 err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H,
205 *val = (i2c_data << 8);
207 err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M,
211 PDEBUG(D_V4L2, "Exposure read as %d", *val);
216 int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
218 struct sd *sd = (struct sd *) gspca_dev;
222 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
224 i2c_data = ((val & 0xff00) >> 8);
225 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
228 err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H,
233 i2c_data = (val & 0xff);
234 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
236 err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M,
242 int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
244 struct sd *sd = (struct sd *) gspca_dev;
248 err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
251 PDEBUG(D_V4L2, "Read global gain %d", *val);
256 int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
258 struct sd *sd = (struct sd *) gspca_dev;
262 err = m5602_read_sensor(sd, PO1030_REG_CONTROL2,
265 *val = (i2c_data >> 7) & 0x01 ;
267 PDEBUG(D_V4L2, "Read hflip %d", *val);
272 int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
274 struct sd *sd = (struct sd *) gspca_dev;
278 PDEBUG(D_V4L2, "Set hflip %d", val);
279 err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
283 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
285 err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
291 int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
293 struct sd *sd = (struct sd *) gspca_dev;
297 err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
300 *val = (i2c_data >> 6) & 0x01;
302 PDEBUG(D_V4L2, "Read vflip %d", *val);
307 int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
309 struct sd *sd = (struct sd *) gspca_dev;
313 PDEBUG(D_V4L2, "Set vflip %d", val);
314 err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
318 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
320 err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
326 int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
328 struct sd *sd = (struct sd *) gspca_dev;
332 i2c_data = val & 0xff;
333 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
334 err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN,
339 int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
341 struct sd *sd = (struct sd *) gspca_dev;
345 err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN,
348 PDEBUG(D_V4L2, "Read red gain %d", *val);
352 int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
354 struct sd *sd = (struct sd *) gspca_dev;
358 i2c_data = val & 0xff;
359 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
360 err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN,
365 int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
367 struct sd *sd = (struct sd *) gspca_dev;
371 err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN,
374 PDEBUG(D_V4L2, "Read blue gain %d", *val);
379 int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
381 struct sd *sd = (struct sd *) gspca_dev;
384 i2c_data = val & 0xff;
385 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
386 err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN,
392 int po1030_power_down(struct sd *sd)
397 static void po1030_dump_registers(struct sd *sd)
402 info("Dumping the po1030 sensor core registers");
403 for (address = 0; address < 0x7f; address++) {
404 m5602_read_sensor(sd, address, &value, 1);
405 info("register 0x%x contains 0x%x",
409 info("po1030 register state dump complete");
411 info("Probing for which registers that are read/write");
412 for (address = 0; address < 0xff; address++) {
413 u8 old_value, ctrl_value;
414 u8 test_value[2] = {0xff, 0xff};
416 m5602_read_sensor(sd, address, &old_value, 1);
417 m5602_write_sensor(sd, address, test_value, 1);
418 m5602_read_sensor(sd, address, &ctrl_value, 1);
420 if (ctrl_value == test_value[0])
421 info("register 0x%x is writeable", address);
423 info("register 0x%x is read only", address);
425 /* Restore original value */
426 m5602_write_sensor(sd, address, &old_value, 1);