blob: 9e9eed89ea637d3b84320a08b948155f463f16d1 [file] [log] [blame]
Erik Andrenc109f812008-10-01 04:51:53 -03001/*
2 * Driver for the po1030 sensor
3 *
Erik Andren0c505e682008-10-16 16:43:16 -03004 * Copyright (c) 2008 Erik Andrén
Erik Andrenc109f812008-10-01 04:51:53 -03005 * 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_po1030.h"
20
Erik Andr?ncf811d52009-04-03 02:49:10 -030021static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
22static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
23static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
26static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
27static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
Erik Andr?nb933d582009-01-13 13:55:52 -030029static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
Erik Andr?ncf811d52009-04-03 02:49:10 -030031static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
36 __s32 val);
37static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 *val);
Erik Andr?ndd9ce842009-01-13 13:43:46 -030039static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
40 __s32 val);
41static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
42 __s32 *val);
Erik Andr?ncf811d52009-04-03 02:49:10 -030043
Erik Andr?n74cadfe2008-12-30 16:48:42 -030044static struct v4l2_pix_format po1030_modes[] = {
45 {
Erik Andr?n931a1c82009-01-15 14:18:36 -030046 320,
47 240,
48 V4L2_PIX_FMT_SBGGR8,
49 V4L2_FIELD_NONE,
50 .sizeimage = 320 * 240,
51 .bytesperline = 320,
52 .colorspace = V4L2_COLORSPACE_SRGB,
53 .priv = 2
54 }, {
Erik Andr?n74cadfe2008-12-30 16:48:42 -030055 640,
56 480,
57 V4L2_PIX_FMT_SBGGR8,
58 V4L2_FIELD_NONE,
59 .sizeimage = 640 * 480,
60 .bytesperline = 640,
61 .colorspace = V4L2_COLORSPACE_SRGB,
Erik Andr?n9536a572009-01-15 14:05:35 -030062 .priv = 2
Erik Andr?n74cadfe2008-12-30 16:48:42 -030063 }
64};
65
Erik Andr?ne17cc082008-12-30 17:06:55 -030066const static struct ctrl po1030_ctrls[] = {
Erik Andr?n05d7d9c2009-01-06 06:39:11 -030067#define GAIN_IDX 0
Erik Andr?ne17cc082008-12-30 17:06:55 -030068 {
69 {
70 .id = V4L2_CID_GAIN,
71 .type = V4L2_CTRL_TYPE_INTEGER,
72 .name = "gain",
73 .minimum = 0x00,
74 .maximum = 0x4f,
75 .step = 0x1,
76 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
77 .flags = V4L2_CTRL_FLAG_SLIDER
78 },
79 .set = po1030_set_gain,
80 .get = po1030_get_gain
Erik Andr?n05d7d9c2009-01-06 06:39:11 -030081 },
82#define EXPOSURE_IDX 1
83 {
Erik Andr?ne17cc082008-12-30 17:06:55 -030084 {
85 .id = V4L2_CID_EXPOSURE,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "exposure",
88 .minimum = 0x00,
89 .maximum = 0x02ff,
90 .step = 0x1,
91 .default_value = PO1030_EXPOSURE_DEFAULT,
92 .flags = V4L2_CTRL_FLAG_SLIDER
93 },
94 .set = po1030_set_exposure,
95 .get = po1030_get_exposure
Erik Andr?n05d7d9c2009-01-06 06:39:11 -030096 },
97#define RED_BALANCE_IDX 2
98 {
Erik Andr?ne17cc082008-12-30 17:06:55 -030099 {
100 .id = V4L2_CID_RED_BALANCE,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "red balance",
103 .minimum = 0x00,
104 .maximum = 0xff,
105 .step = 0x1,
106 .default_value = PO1030_RED_GAIN_DEFAULT,
107 .flags = V4L2_CTRL_FLAG_SLIDER
108 },
109 .set = po1030_set_red_balance,
110 .get = po1030_get_red_balance
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300111 },
112#define BLUE_BALANCE_IDX 3
113 {
Erik Andr?ne17cc082008-12-30 17:06:55 -0300114 {
115 .id = V4L2_CID_BLUE_BALANCE,
116 .type = V4L2_CTRL_TYPE_INTEGER,
117 .name = "blue balance",
118 .minimum = 0x00,
119 .maximum = 0xff,
120 .step = 0x1,
121 .default_value = PO1030_BLUE_GAIN_DEFAULT,
122 .flags = V4L2_CTRL_FLAG_SLIDER
123 },
124 .set = po1030_set_blue_balance,
125 .get = po1030_get_blue_balance
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300126 },
127#define HFLIP_IDX 4
128 {
Erik Andr?ne17cc082008-12-30 17:06:55 -0300129 {
130 .id = V4L2_CID_HFLIP,
131 .type = V4L2_CTRL_TYPE_BOOLEAN,
132 .name = "horizontal flip",
133 .minimum = 0,
134 .maximum = 1,
135 .step = 1,
136 .default_value = 0,
137 },
138 .set = po1030_set_hflip,
139 .get = po1030_get_hflip
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300140 },
141#define VFLIP_IDX 5
142 {
Erik Andr?ne17cc082008-12-30 17:06:55 -0300143 {
144 .id = V4L2_CID_VFLIP,
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .name = "vertical flip",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
150 .default_value = 0,
151 },
152 .set = po1030_set_vflip,
153 .get = po1030_get_vflip
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300154 },
155#define AUTO_WHITE_BALANCE_IDX 6
156 {
157 {
158 .id = V4L2_CID_AUTO_WHITE_BALANCE,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "auto white balance",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164 .default_value = 0,
165 },
166 .set = po1030_set_auto_white_balance,
167 .get = po1030_get_auto_white_balance
Erik Andr?ndd9ce842009-01-13 13:43:46 -0300168 },
169#define AUTO_EXPOSURE_IDX 7
170 {
171 {
172 .id = V4L2_CID_EXPOSURE_AUTO,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "auto exposure",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178 .default_value = 0,
179 },
180 .set = po1030_set_auto_exposure,
181 .get = po1030_get_auto_exposure
182 },
Erik Andr?nb933d582009-01-13 13:55:52 -0300183#define GREEN_BALANCE_IDX 8
184 {
185 {
186 .id = M5602_V4L2_CID_GREEN_BALANCE,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "green balance",
189 .minimum = 0x00,
190 .maximum = 0xff,
191 .step = 0x1,
192 .default_value = PO1030_GREEN_GAIN_DEFAULT,
193 .flags = V4L2_CTRL_FLAG_SLIDER
194 },
195 .set = po1030_set_green_balance,
196 .get = po1030_get_green_balance
197 },
Erik Andr?ne17cc082008-12-30 17:06:55 -0300198};
199
Erik Andrén658efb62008-11-24 14:21:29 -0300200static void po1030_dump_registers(struct sd *sd);
201
Erik Andrenc109f812008-10-01 04:51:53 -0300202int po1030_probe(struct sd *sd)
203{
Erik Andr?n3e5cbad2009-01-11 12:52:10 -0300204 u8 dev_id_h = 0, i;
Erik Andr?ncb29e692009-01-07 18:05:08 -0300205 s32 *sensor_settings;
Erik Andrenc109f812008-10-01 04:51:53 -0300206
207 if (force_sensor) {
208 if (force_sensor == PO1030_SENSOR) {
209 info("Forcing a %s sensor", po1030.name);
210 goto sensor_found;
211 }
212 /* If we want to force another sensor, don't try to probe this
213 * one */
214 return -ENODEV;
215 }
216
217 info("Probing for a po1030 sensor");
218
219 /* Run the pre-init to actually probe the unit */
220 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
221 u8 data = preinit_po1030[i][2];
222 if (preinit_po1030[i][0] == SENSOR)
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300223 m5602_write_sensor(sd,
Erik Andrenc109f812008-10-01 04:51:53 -0300224 preinit_po1030[i][1], &data, 1);
225 else
226 m5602_write_bridge(sd, preinit_po1030[i][1], data);
227 }
228
Erik Andr?nfcb98102009-01-08 04:04:19 -0300229 if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
Erik Andrenc109f812008-10-01 04:51:53 -0300230 return -ENODEV;
231
Erik Andr?n3e5cbad2009-01-11 12:52:10 -0300232 if (dev_id_h == 0x30) {
Erik Andrenc109f812008-10-01 04:51:53 -0300233 info("Detected a po1030 sensor");
234 goto sensor_found;
235 }
236 return -ENODEV;
237
238sensor_found:
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300239 sensor_settings = kmalloc(
240 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
241 if (!sensor_settings)
242 return -ENOMEM;
243
Erik Andr?n74cadfe2008-12-30 16:48:42 -0300244 sd->gspca_dev.cam.cam_mode = po1030_modes;
245 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
Erik Andr?ne17cc082008-12-30 17:06:55 -0300246 sd->desc->ctrls = po1030_ctrls;
Erik Andr?ne4cc4fc2008-12-30 15:27:17 -0300247 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300248
249 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
250 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
251 sd->sensor_priv = sensor_settings;
Erik Andr?ncb29e692009-01-07 18:05:08 -0300252
Erik Andrenc109f812008-10-01 04:51:53 -0300253 return 0;
254}
255
Erik Andrenc109f812008-10-01 04:51:53 -0300256int po1030_init(struct sd *sd)
257{
Erik Andr?ncb29e692009-01-07 18:05:08 -0300258 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300259 int i, err = 0;
260
261 /* Init the sensor */
Erik Andrén7b9f2462008-11-20 03:59:02 -0300262 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
Erik Andrenc109f812008-10-01 04:51:53 -0300263 u8 data[2] = {0x00, 0x00};
264
265 switch (init_po1030[i][0]) {
266 case BRIDGE:
267 err = m5602_write_bridge(sd,
268 init_po1030[i][1],
269 init_po1030[i][2]);
270 break;
271
272 case SENSOR:
273 data[0] = init_po1030[i][2];
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300274 err = m5602_write_sensor(sd,
Erik Andrenc109f812008-10-01 04:51:53 -0300275 init_po1030[i][1], data, 1);
276 break;
277
Erik Andrenc109f812008-10-01 04:51:53 -0300278 default:
279 info("Invalid stream command, exiting init");
280 return -EINVAL;
281 }
282 }
Erik Andr?ncb29e692009-01-07 18:05:08 -0300283 if (err < 0)
284 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300285
Erik Andr?n36e756c2009-01-09 13:35:00 -0300286 if (dump_sensor)
287 po1030_dump_registers(sd);
288
Erik Andr?ncb29e692009-01-07 18:05:08 -0300289 err = po1030_set_exposure(&sd->gspca_dev,
290 sensor_settings[EXPOSURE_IDX]);
291 if (err < 0)
292 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300293
Erik Andr?ncb29e692009-01-07 18:05:08 -0300294 err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
295 if (err < 0)
296 return err;
297
298 err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
299 if (err < 0)
300 return err;
301
302 err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
303 if (err < 0)
304 return err;
305
306 err = po1030_set_red_balance(&sd->gspca_dev,
307 sensor_settings[RED_BALANCE_IDX]);
308 if (err < 0)
309 return err;
310
Erik Andr?n926d5032009-01-11 15:23:46 -0300311 err = po1030_set_blue_balance(&sd->gspca_dev,
Erik Andr?ncb29e692009-01-07 18:05:08 -0300312 sensor_settings[BLUE_BALANCE_IDX]);
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300313 if (err < 0)
314 return err;
315
Erik Andr?nb933d582009-01-13 13:55:52 -0300316 err = po1030_set_green_balance(&sd->gspca_dev,
317 sensor_settings[GREEN_BALANCE_IDX]);
318 if (err < 0)
319 return err;
320
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300321 err = po1030_set_auto_white_balance(&sd->gspca_dev,
Erik Andr?ndd9ce842009-01-13 13:43:46 -0300322 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
323 if (err < 0)
324 return err;
325
326 err = po1030_set_auto_exposure(&sd->gspca_dev,
327 sensor_settings[AUTO_EXPOSURE_IDX]);
Erik Andrén7b9f2462008-11-20 03:59:02 -0300328 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300329}
330
Erik Andr?nc996b362009-01-08 14:15:06 -0300331int po1030_start(struct sd *sd)
332{
Erik Andr?ne807f202009-01-15 13:39:39 -0300333 struct cam *cam = &sd->gspca_dev.cam;
Erik Andr?nc996b362009-01-08 14:15:06 -0300334 int i, err = 0;
Erik Andr?ne807f202009-01-15 13:39:39 -0300335 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
336 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
Erik Andr?n9536a572009-01-15 14:05:35 -0300337 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
Erik Andr?ne807f202009-01-15 13:39:39 -0300338 u8 data;
339
340 switch (width) {
Erik Andr?n931a1c82009-01-15 14:18:36 -0300341 case 320:
342 data = PO1030_SUBSAMPLING;
343 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
344 if (err < 0)
345 return err;
346
347 data = ((width + 3) >> 8) & 0xff;
348 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
349 if (err < 0)
350 return err;
351
352 data = (width + 3) & 0xff;
353 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
354 if (err < 0)
355 return err;
356
357 data = ((height + 1) >> 8) & 0xff;
358 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
359 if (err < 0)
360 return err;
361
362 data = (height + 1) & 0xff;
363 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
364
365 height += 6;
366 width -= 1;
367 break;
368
Erik Andr?ne807f202009-01-15 13:39:39 -0300369 case 640:
Erik Andr?n931a1c82009-01-15 14:18:36 -0300370 data = 0;
371 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
372 if (err < 0)
373 return err;
374
Erik Andr?ne807f202009-01-15 13:39:39 -0300375 data = ((width + 7) >> 8) & 0xff;
376 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
377 if (err < 0)
378 return err;
379
380 data = (width + 7) & 0xff;
381 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
382 if (err < 0)
383 return err;
384
385 data = ((height + 3) >> 8) & 0xff;
386 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
387 if (err < 0)
388 return err;
389
390 data = (height + 3) & 0xff;
391 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
Erik Andr?n9536a572009-01-15 14:05:35 -0300392
393 height += 12;
394 width -= 2;
Erik Andr?ne807f202009-01-15 13:39:39 -0300395 break;
396 }
397
Erik Andr?n9536a572009-01-15 14:05:35 -0300398 err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
399 if (err < 0)
400 return err;
401
402 err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
403 if (err < 0)
404 return err;
405
406 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
407 ((ver_offs >> 8) & 0xff));
408 if (err < 0)
409 return err;
410
411 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
412 if (err < 0)
413 return err;
414
415 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
416 if (err < 0)
417 return err;
418
419 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
420 if (err < 0)
421 return err;
422
423 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
424 if (err < 0)
425 return err;
426
427 for (i = 0; i < 2 && !err; i++)
428 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
429
430 for (i = 0; i < 2 && !err; i++)
431 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
432 if (err < 0)
433 return err;
434
435 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
436 if (err < 0)
437 return err;
438
439 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
Erik Andr?nc996b362009-01-08 14:15:06 -0300440 return err;
441}
442
Erik Andr?ncf811d52009-04-03 02:49:10 -0300443static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrenc109f812008-10-01 04:51:53 -0300444{
445 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300446 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300447
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300448 *val = sensor_settings[EXPOSURE_IDX];
Erik Andren17ea88a2008-10-16 16:46:07 -0300449 PDEBUG(D_V4L2, "Exposure read as %d", *val);
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300450 return 0;
Erik Andrenc109f812008-10-01 04:51:53 -0300451}
452
Erik Andr?ncf811d52009-04-03 02:49:10 -0300453static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
Erik Andrenc109f812008-10-01 04:51:53 -0300454{
455 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300456 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300457 u8 i2c_data;
458 int err;
459
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300460 sensor_settings[EXPOSURE_IDX] = val;
Erik Andren17ea88a2008-10-16 16:46:07 -0300461 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
Erik Andrenc109f812008-10-01 04:51:53 -0300462
463 i2c_data = ((val & 0xff00) >> 8);
Erik Andren17ea88a2008-10-16 16:46:07 -0300464 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
Erik Andrenc109f812008-10-01 04:51:53 -0300465 i2c_data);
466
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300467 err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
Erik Andrenc109f812008-10-01 04:51:53 -0300468 &i2c_data, 1);
469 if (err < 0)
Erik Andr?n051781b2008-12-27 12:28:00 -0300470 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300471
472 i2c_data = (val & 0xff);
Erik Andren17ea88a2008-10-16 16:46:07 -0300473 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
Erik Andrenc109f812008-10-01 04:51:53 -0300474 i2c_data);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300475 err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
Erik Andrenc109f812008-10-01 04:51:53 -0300476 &i2c_data, 1);
477
Erik Andrén7b9f2462008-11-20 03:59:02 -0300478 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300479}
480
Erik Andr?ncf811d52009-04-03 02:49:10 -0300481static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrenc109f812008-10-01 04:51:53 -0300482{
483 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300484 s32 *sensor_settings = sd->sensor_priv;
485
486 *val = sensor_settings[GAIN_IDX];
487 PDEBUG(D_V4L2, "Read global gain %d", *val);
488 return 0;
489}
490
Erik Andr?ncf811d52009-04-03 02:49:10 -0300491static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300492{
493 struct sd *sd = (struct sd *) gspca_dev;
494 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300495 u8 i2c_data;
496 int err;
497
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300498 sensor_settings[GAIN_IDX] = val;
Erik Andrenc109f812008-10-01 04:51:53 -0300499
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300500 i2c_data = val & 0xff;
501 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300502 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300503 &i2c_data, 1);
Erik Andrén7b9f2462008-11-20 03:59:02 -0300504 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300505}
506
Erik Andr?ncf811d52009-04-03 02:49:10 -0300507static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrene2c97492008-10-16 16:49:17 -0300508{
509 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300510 s32 *sensor_settings = sd->sensor_priv;
Erik Andrene2c97492008-10-16 16:49:17 -0300511
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300512 *val = sensor_settings[HFLIP_IDX];
Erik Andrene2c97492008-10-16 16:49:17 -0300513 PDEBUG(D_V4L2, "Read hflip %d", *val);
514
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300515 return 0;
Erik Andrene2c97492008-10-16 16:49:17 -0300516}
517
Erik Andr?ncf811d52009-04-03 02:49:10 -0300518static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
Erik Andrene2c97492008-10-16 16:49:17 -0300519{
520 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300521 s32 *sensor_settings = sd->sensor_priv;
Erik Andrene2c97492008-10-16 16:49:17 -0300522 u8 i2c_data;
523 int err;
524
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300525 sensor_settings[HFLIP_IDX] = val;
526
Erik Andrene2c97492008-10-16 16:49:17 -0300527 PDEBUG(D_V4L2, "Set hflip %d", val);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300528 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300529 if (err < 0)
Erik Andr?n051781b2008-12-27 12:28:00 -0300530 return err;
Erik Andrene2c97492008-10-16 16:49:17 -0300531
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300532 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
Erik Andrene2c97492008-10-16 16:49:17 -0300533
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300534 err = m5602_write_sensor(sd, PO1030_CONTROL2,
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300535 &i2c_data, 1);
Erik Andrene2c97492008-10-16 16:49:17 -0300536
Erik Andrén7b9f2462008-11-20 03:59:02 -0300537 return err;
Erik Andrene2c97492008-10-16 16:49:17 -0300538}
539
Erik Andr?ncf811d52009-04-03 02:49:10 -0300540static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrene2c97492008-10-16 16:49:17 -0300541{
542 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300543 s32 *sensor_settings = sd->sensor_priv;
Erik Andrene2c97492008-10-16 16:49:17 -0300544
Erik Andr?n27429082009-01-07 17:41:47 -0300545 *val = sensor_settings[VFLIP_IDX];
Erik Andrene2c97492008-10-16 16:49:17 -0300546 PDEBUG(D_V4L2, "Read vflip %d", *val);
547
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300548 return 0;
Erik Andrene2c97492008-10-16 16:49:17 -0300549}
550
Erik Andr?ncf811d52009-04-03 02:49:10 -0300551static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
Erik Andrene2c97492008-10-16 16:49:17 -0300552{
553 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300554 s32 *sensor_settings = sd->sensor_priv;
Erik Andrene2c97492008-10-16 16:49:17 -0300555 u8 i2c_data;
556 int err;
557
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300558 sensor_settings[VFLIP_IDX] = val;
559
Erik Andrene2c97492008-10-16 16:49:17 -0300560 PDEBUG(D_V4L2, "Set vflip %d", val);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300561 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300562 if (err < 0)
Erik Andr?n051781b2008-12-27 12:28:00 -0300563 return err;
Erik Andrene2c97492008-10-16 16:49:17 -0300564
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300565 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
Erik Andrene2c97492008-10-16 16:49:17 -0300566
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300567 err = m5602_write_sensor(sd, PO1030_CONTROL2,
Erik Andrén1d07b6f2008-11-27 14:07:24 -0300568 &i2c_data, 1);
Erik Andrene2c97492008-10-16 16:49:17 -0300569
Erik Andrén7b9f2462008-11-20 03:59:02 -0300570 return err;
Erik Andrene2c97492008-10-16 16:49:17 -0300571}
572
Erik Andr?ncf811d52009-04-03 02:49:10 -0300573static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrenc109f812008-10-01 04:51:53 -0300574{
575 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300576 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300577
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300578 *val = sensor_settings[RED_BALANCE_IDX];
Erik Andren17ea88a2008-10-16 16:46:07 -0300579 PDEBUG(D_V4L2, "Read red gain %d", *val);
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300580 return 0;
Erik Andrenc109f812008-10-01 04:51:53 -0300581}
582
Erik Andr?ncf811d52009-04-03 02:49:10 -0300583static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
Erik Andrenc109f812008-10-01 04:51:53 -0300584{
585 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300586 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300587 u8 i2c_data;
588 int err;
589
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300590 sensor_settings[RED_BALANCE_IDX] = val;
591
Erik Andrenc109f812008-10-01 04:51:53 -0300592 i2c_data = val & 0xff;
Erik Andren17ea88a2008-10-16 16:46:07 -0300593 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300594 err = m5602_write_sensor(sd, PO1030_RED_GAIN,
Erik Andrenc109f812008-10-01 04:51:53 -0300595 &i2c_data, 1);
Erik Andrén7b9f2462008-11-20 03:59:02 -0300596 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300597}
598
Erik Andr?ncf811d52009-04-03 02:49:10 -0300599static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
Erik Andrenc109f812008-10-01 04:51:53 -0300600{
601 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300602 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300603
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300604 *val = sensor_settings[BLUE_BALANCE_IDX];
Erik Andren17ea88a2008-10-16 16:46:07 -0300605 PDEBUG(D_V4L2, "Read blue gain %d", *val);
Erik Andrenc109f812008-10-01 04:51:53 -0300606
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300607 return 0;
Erik Andrenc109f812008-10-01 04:51:53 -0300608}
609
Erik Andr?ncf811d52009-04-03 02:49:10 -0300610static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
Erik Andrenc109f812008-10-01 04:51:53 -0300611{
612 struct sd *sd = (struct sd *) gspca_dev;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300613 s32 *sensor_settings = sd->sensor_priv;
Erik Andrenc109f812008-10-01 04:51:53 -0300614 u8 i2c_data;
615 int err;
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300616
617 sensor_settings[BLUE_BALANCE_IDX] = val;
618
Erik Andrenc109f812008-10-01 04:51:53 -0300619 i2c_data = val & 0xff;
Erik Andren17ea88a2008-10-16 16:46:07 -0300620 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
Erik Andr?nbb9460e2009-01-07 13:54:13 -0300621 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
Erik Andrenc109f812008-10-01 04:51:53 -0300622 &i2c_data, 1);
623
Erik Andrén7b9f2462008-11-20 03:59:02 -0300624 return err;
Erik Andrenc109f812008-10-01 04:51:53 -0300625}
626
Erik Andr?nb933d582009-01-13 13:55:52 -0300627static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
628{
629 struct sd *sd = (struct sd *) gspca_dev;
630 s32 *sensor_settings = sd->sensor_priv;
631
632 *val = sensor_settings[GREEN_BALANCE_IDX];
633 PDEBUG(D_V4L2, "Read green gain %d", *val);
634
635 return 0;
636}
637
638static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
639{
640 struct sd *sd = (struct sd *) gspca_dev;
641 s32 *sensor_settings = sd->sensor_priv;
642 u8 i2c_data;
643 int err;
644
645 sensor_settings[GREEN_BALANCE_IDX] = val;
646 i2c_data = val & 0xff;
647 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
648
649 err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
650 &i2c_data, 1);
651 if (err < 0)
652 return err;
653
654 return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
655 &i2c_data, 1);
656}
657
Erik Andr?ncf811d52009-04-03 02:49:10 -0300658static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
659 __s32 *val)
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300660{
661 struct sd *sd = (struct sd *) gspca_dev;
662 s32 *sensor_settings = sd->sensor_priv;
663
664 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
665 PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
666
667 return 0;
668}
669
Erik Andr?ncf811d52009-04-03 02:49:10 -0300670static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
671 __s32 val)
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300672{
673 struct sd *sd = (struct sd *) gspca_dev;
674 s32 *sensor_settings = sd->sensor_priv;
675 u8 i2c_data;
676 int err;
677
678 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
679
680 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
681 if (err < 0)
682 return err;
683
Erik Andr?ndd9ce842009-01-13 13:43:46 -0300684 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
Erik Andr?n3b9ae652009-01-08 03:53:50 -0300685 i2c_data = (i2c_data & 0xfe) | (val & 0x01);
686 err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
687 return err;
688}
689
Erik Andr?ndd9ce842009-01-13 13:43:46 -0300690static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
691 __s32 *val)
692{
693 struct sd *sd = (struct sd *) gspca_dev;
694 s32 *sensor_settings = sd->sensor_priv;
695
696 *val = sensor_settings[AUTO_EXPOSURE_IDX];
697 PDEBUG(D_V4L2, "Auto exposure is %d", *val);
698 return 0;
699}
700
701static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
702 __s32 val)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705 s32 *sensor_settings = sd->sensor_priv;
706 u8 i2c_data;
707 int err;
708
709 sensor_settings[AUTO_EXPOSURE_IDX] = val;
710 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
711 if (err < 0)
712 return err;
713
714 PDEBUG(D_V4L2, "Set auto exposure to %d", val);
715 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
716 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
717}
718
Erik Andr?n05d7d9c2009-01-06 06:39:11 -0300719void po1030_disconnect(struct sd *sd)
720{
721 sd->sensor = NULL;
722 kfree(sd->sensor_priv);
723}
724
Erik Andrén658efb62008-11-24 14:21:29 -0300725static void po1030_dump_registers(struct sd *sd)
Erik Andrenc109f812008-10-01 04:51:53 -0300726{
727 int address;
728 u8 value = 0;
729
730 info("Dumping the po1030 sensor core registers");
731 for (address = 0; address < 0x7f; address++) {
Erik Andrénc061c972008-11-27 13:46:39 -0300732 m5602_read_sensor(sd, address, &value, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300733 info("register 0x%x contains 0x%x",
734 address, value);
735 }
736
737 info("po1030 register state dump complete");
738
739 info("Probing for which registers that are read/write");
740 for (address = 0; address < 0xff; address++) {
741 u8 old_value, ctrl_value;
742 u8 test_value[2] = {0xff, 0xff};
743
Erik Andrénc061c972008-11-27 13:46:39 -0300744 m5602_read_sensor(sd, address, &old_value, 1);
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300745 m5602_write_sensor(sd, address, test_value, 1);
Erik Andrénc061c972008-11-27 13:46:39 -0300746 m5602_read_sensor(sd, address, &ctrl_value, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300747
748 if (ctrl_value == test_value[0])
749 info("register 0x%x is writeable", address);
750 else
751 info("register 0x%x is read only", address);
752
753 /* Restore original value */
Erik Andrén6dc4cff2008-11-26 04:08:10 -0300754 m5602_write_sensor(sd, address, &old_value, 1);
Erik Andrenc109f812008-10-01 04:51:53 -0300755 }
756}