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[] = {
39 .type = V4L2_CTRL_TYPE_INTEGER,
44 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
45 .flags = V4L2_CTRL_FLAG_SLIDER
47 .set = po1030_set_gain,
48 .get = po1030_get_gain
50 #define EXPOSURE_IDX 1
53 .id = V4L2_CID_EXPOSURE,
54 .type = V4L2_CTRL_TYPE_INTEGER,
59 .default_value = PO1030_EXPOSURE_DEFAULT,
60 .flags = V4L2_CTRL_FLAG_SLIDER
62 .set = po1030_set_exposure,
63 .get = po1030_get_exposure
65 #define RED_BALANCE_IDX 2
68 .id = V4L2_CID_RED_BALANCE,
69 .type = V4L2_CTRL_TYPE_INTEGER,
70 .name = "red balance",
74 .default_value = PO1030_RED_GAIN_DEFAULT,
75 .flags = V4L2_CTRL_FLAG_SLIDER
77 .set = po1030_set_red_balance,
78 .get = po1030_get_red_balance
80 #define BLUE_BALANCE_IDX 3
83 .id = V4L2_CID_BLUE_BALANCE,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "blue balance",
89 .default_value = PO1030_BLUE_GAIN_DEFAULT,
90 .flags = V4L2_CTRL_FLAG_SLIDER
92 .set = po1030_set_blue_balance,
93 .get = po1030_get_blue_balance
99 .type = V4L2_CTRL_TYPE_BOOLEAN,
100 .name = "horizontal flip",
106 .set = po1030_set_hflip,
107 .get = po1030_get_hflip
112 .id = V4L2_CID_VFLIP,
113 .type = V4L2_CTRL_TYPE_BOOLEAN,
114 .name = "vertical flip",
120 .set = po1030_set_vflip,
121 .get = po1030_get_vflip
125 static void po1030_dump_registers(struct sd *sd);
127 int po1030_probe(struct sd *sd)
129 u8 prod_id = 0, ver_id = 0, i;
130 s32 *sensor_settings = sd->sensor_priv;
133 if (force_sensor == PO1030_SENSOR) {
134 info("Forcing a %s sensor", po1030.name);
137 /* If we want to force another sensor, don't try to probe this
142 info("Probing for a po1030 sensor");
144 /* Run the pre-init to actually probe the unit */
145 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
146 u8 data = preinit_po1030[i][2];
147 if (preinit_po1030[i][0] == SENSOR)
148 m5602_write_sensor(sd,
149 preinit_po1030[i][1], &data, 1);
151 m5602_write_bridge(sd, preinit_po1030[i][1], data);
154 if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
157 if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
160 if ((prod_id == 0x02) && (ver_id == 0xef)) {
161 info("Detected a po1030 sensor");
167 sensor_settings = kmalloc(
168 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
169 if (!sensor_settings)
172 sd->gspca_dev.cam.cam_mode = po1030_modes;
173 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
174 sd->desc->ctrls = po1030_ctrls;
175 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
177 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
178 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
179 sd->sensor_priv = sensor_settings;
183 int po1030_init(struct sd *sd)
187 /* Init the sensor */
188 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
189 u8 data[2] = {0x00, 0x00};
191 switch (init_po1030[i][0]) {
193 err = m5602_write_bridge(sd,
199 data[0] = init_po1030[i][2];
200 err = m5602_write_sensor(sd,
201 init_po1030[i][1], data, 1);
205 info("Invalid stream command, exiting init");
211 po1030_dump_registers(sd);
216 int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
218 struct sd *sd = (struct sd *) gspca_dev;
219 s32 *sensor_settings = sd->sensor_priv;
221 *val = sensor_settings[EXPOSURE_IDX];
222 PDEBUG(D_V4L2, "Exposure read as %d", *val);
226 int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
228 struct sd *sd = (struct sd *) gspca_dev;
229 s32 *sensor_settings = sd->sensor_priv;
233 sensor_settings[EXPOSURE_IDX] = val;
234 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
236 i2c_data = ((val & 0xff00) >> 8);
237 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
240 err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
245 i2c_data = (val & 0xff);
246 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
248 err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
254 int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
256 struct sd *sd = (struct sd *) gspca_dev;
257 s32 *sensor_settings = sd->sensor_priv;
259 *val = sensor_settings[GAIN_IDX];
260 PDEBUG(D_V4L2, "Read global gain %d", *val);
264 int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
266 struct sd *sd = (struct sd *) gspca_dev;
267 s32 *sensor_settings = sd->sensor_priv;
271 sensor_settings[GAIN_IDX] = val;
273 i2c_data = val & 0xff;
274 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
275 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
280 int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
282 struct sd *sd = (struct sd *) gspca_dev;
283 s32 *sensor_settings = sd->sensor_priv;
285 *val = sensor_settings[HFLIP_IDX];
286 PDEBUG(D_V4L2, "Read hflip %d", *val);
291 int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
293 struct sd *sd = (struct sd *) gspca_dev;
294 s32 *sensor_settings = sd->sensor_priv;
298 sensor_settings[HFLIP_IDX] = val;
300 PDEBUG(D_V4L2, "Set hflip %d", val);
301 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
305 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
307 err = m5602_write_sensor(sd, PO1030_CONTROL2,
313 int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
315 struct sd *sd = (struct sd *) gspca_dev;
316 s32 *sensor_settings = sd->sensor_priv;
318 *val= sensor_settings[VFLIP_IDX];
319 PDEBUG(D_V4L2, "Read vflip %d", *val);
324 int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
326 struct sd *sd = (struct sd *) gspca_dev;
327 s32 *sensor_settings = sd->sensor_priv;
331 sensor_settings[VFLIP_IDX] = val;
333 PDEBUG(D_V4L2, "Set vflip %d", val);
334 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
338 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
340 err = m5602_write_sensor(sd, PO1030_CONTROL2,
346 int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
348 struct sd *sd = (struct sd *) gspca_dev;
349 s32 *sensor_settings = sd->sensor_priv;
351 *val = sensor_settings[RED_BALANCE_IDX];
352 PDEBUG(D_V4L2, "Read red gain %d", *val);
356 int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
358 struct sd *sd = (struct sd *) gspca_dev;
359 s32 *sensor_settings = sd->sensor_priv;
363 sensor_settings[RED_BALANCE_IDX] = val;
365 i2c_data = val & 0xff;
366 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
367 err = m5602_write_sensor(sd, PO1030_RED_GAIN,
372 int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
374 struct sd *sd = (struct sd *) gspca_dev;
375 s32 *sensor_settings = sd->sensor_priv;
377 *val = sensor_settings[BLUE_BALANCE_IDX];
378 PDEBUG(D_V4L2, "Read blue gain %d", *val);
383 int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
385 struct sd *sd = (struct sd *) gspca_dev;
386 s32 *sensor_settings = sd->sensor_priv;
390 sensor_settings[BLUE_BALANCE_IDX] = val;
392 i2c_data = val & 0xff;
393 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
394 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
400 void po1030_disconnect(struct sd *sd)
403 kfree(sd->sensor_priv);
406 static void po1030_dump_registers(struct sd *sd)
411 info("Dumping the po1030 sensor core registers");
412 for (address = 0; address < 0x7f; address++) {
413 m5602_read_sensor(sd, address, &value, 1);
414 info("register 0x%x contains 0x%x",
418 info("po1030 register state dump complete");
420 info("Probing for which registers that are read/write");
421 for (address = 0; address < 0xff; address++) {
422 u8 old_value, ctrl_value;
423 u8 test_value[2] = {0xff, 0xff};
425 m5602_read_sensor(sd, address, &old_value, 1);
426 m5602_write_sensor(sd, address, test_value, 1);
427 m5602_read_sensor(sd, address, &ctrl_value, 1);
429 if (ctrl_value == test_value[0])
430 info("register 0x%x is writeable", address);
432 info("register 0x%x is read only", address);
434 /* Restore original value */
435 m5602_write_sensor(sd, address, &old_value, 1);