• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/gspca/m5602/
1/*
2 * Driver for the po1030 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_po1030.h"
20
21static 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);
29static 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);
31static 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);
39static 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);
43
44static struct v4l2_pix_format po1030_modes[] = {
45	{
46		640,
47		480,
48		V4L2_PIX_FMT_SBGGR8,
49		V4L2_FIELD_NONE,
50		.sizeimage = 640 * 480,
51		.bytesperline = 640,
52		.colorspace = V4L2_COLORSPACE_SRGB,
53		.priv = 2
54	}
55};
56
57static const struct ctrl po1030_ctrls[] = {
58#define GAIN_IDX 0
59	{
60		{
61			.id 		= V4L2_CID_GAIN,
62			.type 		= V4L2_CTRL_TYPE_INTEGER,
63			.name 		= "gain",
64			.minimum 	= 0x00,
65			.maximum 	= 0x4f,
66			.step 		= 0x1,
67			.default_value 	= PO1030_GLOBAL_GAIN_DEFAULT,
68			.flags         	= V4L2_CTRL_FLAG_SLIDER
69		},
70		.set = po1030_set_gain,
71		.get = po1030_get_gain
72	},
73#define EXPOSURE_IDX 1
74	{
75		{
76			.id 		= V4L2_CID_EXPOSURE,
77			.type 		= V4L2_CTRL_TYPE_INTEGER,
78			.name 		= "exposure",
79			.minimum 	= 0x00,
80			.maximum 	= 0x02ff,
81			.step 		= 0x1,
82			.default_value 	= PO1030_EXPOSURE_DEFAULT,
83			.flags         	= V4L2_CTRL_FLAG_SLIDER
84		},
85		.set = po1030_set_exposure,
86		.get = po1030_get_exposure
87	},
88#define RED_BALANCE_IDX 2
89	{
90		{
91			.id 		= V4L2_CID_RED_BALANCE,
92			.type 		= V4L2_CTRL_TYPE_INTEGER,
93			.name 		= "red balance",
94			.minimum 	= 0x00,
95			.maximum 	= 0xff,
96			.step 		= 0x1,
97			.default_value 	= PO1030_RED_GAIN_DEFAULT,
98			.flags         	= V4L2_CTRL_FLAG_SLIDER
99		},
100		.set = po1030_set_red_balance,
101		.get = po1030_get_red_balance
102	},
103#define BLUE_BALANCE_IDX 3
104	{
105		{
106			.id 		= V4L2_CID_BLUE_BALANCE,
107			.type 		= V4L2_CTRL_TYPE_INTEGER,
108			.name 		= "blue balance",
109			.minimum 	= 0x00,
110			.maximum 	= 0xff,
111			.step 		= 0x1,
112			.default_value 	= PO1030_BLUE_GAIN_DEFAULT,
113			.flags         	= V4L2_CTRL_FLAG_SLIDER
114		},
115		.set = po1030_set_blue_balance,
116		.get = po1030_get_blue_balance
117	},
118#define HFLIP_IDX 4
119	{
120		{
121			.id 		= V4L2_CID_HFLIP,
122			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
123			.name 		= "horizontal flip",
124			.minimum 	= 0,
125			.maximum 	= 1,
126			.step 		= 1,
127			.default_value 	= 0,
128		},
129		.set = po1030_set_hflip,
130		.get = po1030_get_hflip
131	},
132#define VFLIP_IDX 5
133	{
134		{
135			.id 		= V4L2_CID_VFLIP,
136			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
137			.name 		= "vertical flip",
138			.minimum 	= 0,
139			.maximum 	= 1,
140			.step 		= 1,
141			.default_value 	= 0,
142		},
143		.set = po1030_set_vflip,
144		.get = po1030_get_vflip
145	},
146#define AUTO_WHITE_BALANCE_IDX 6
147	{
148		{
149			.id 		= V4L2_CID_AUTO_WHITE_BALANCE,
150			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
151			.name 		= "auto white balance",
152			.minimum 	= 0,
153			.maximum 	= 1,
154			.step 		= 1,
155			.default_value 	= 0,
156		},
157		.set = po1030_set_auto_white_balance,
158		.get = po1030_get_auto_white_balance
159	},
160#define AUTO_EXPOSURE_IDX 7
161	{
162		{
163			.id 		= V4L2_CID_EXPOSURE_AUTO,
164			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
165			.name 		= "auto exposure",
166			.minimum 	= 0,
167			.maximum 	= 1,
168			.step 		= 1,
169			.default_value 	= 0,
170		},
171		.set = po1030_set_auto_exposure,
172		.get = po1030_get_auto_exposure
173	},
174#define GREEN_BALANCE_IDX 8
175	{
176		{
177			.id 		= M5602_V4L2_CID_GREEN_BALANCE,
178			.type 		= V4L2_CTRL_TYPE_INTEGER,
179			.name 		= "green balance",
180			.minimum 	= 0x00,
181			.maximum 	= 0xff,
182			.step 		= 0x1,
183			.default_value 	= PO1030_GREEN_GAIN_DEFAULT,
184			.flags         	= V4L2_CTRL_FLAG_SLIDER
185		},
186		.set = po1030_set_green_balance,
187		.get = po1030_get_green_balance
188	},
189};
190
191static void po1030_dump_registers(struct sd *sd);
192
193int po1030_probe(struct sd *sd)
194{
195	u8 dev_id_h = 0, i;
196	s32 *sensor_settings;
197
198	if (force_sensor) {
199		if (force_sensor == PO1030_SENSOR) {
200			info("Forcing a %s sensor", po1030.name);
201			goto sensor_found;
202		}
203		/* If we want to force another sensor, don't try to probe this
204		 * one */
205		return -ENODEV;
206	}
207
208	PDEBUG(D_PROBE, "Probing for a po1030 sensor");
209
210	/* Run the pre-init to actually probe the unit */
211	for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
212		u8 data = preinit_po1030[i][2];
213		if (preinit_po1030[i][0] == SENSOR)
214			m5602_write_sensor(sd,
215				preinit_po1030[i][1], &data, 1);
216		else
217			m5602_write_bridge(sd, preinit_po1030[i][1], data);
218	}
219
220	if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
221		return -ENODEV;
222
223	if (dev_id_h == 0x30) {
224		info("Detected a po1030 sensor");
225		goto sensor_found;
226	}
227	return -ENODEV;
228
229sensor_found:
230	sensor_settings = kmalloc(
231		ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
232	if (!sensor_settings)
233		return -ENOMEM;
234
235	sd->gspca_dev.cam.cam_mode = po1030_modes;
236	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
237	sd->desc->ctrls = po1030_ctrls;
238	sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
239
240	for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
241		sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
242	sd->sensor_priv = sensor_settings;
243
244	return 0;
245}
246
247int po1030_init(struct sd *sd)
248{
249	s32 *sensor_settings = sd->sensor_priv;
250	int i, err = 0;
251
252	/* Init the sensor */
253	for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
254		u8 data[2] = {0x00, 0x00};
255
256		switch (init_po1030[i][0]) {
257		case BRIDGE:
258			err = m5602_write_bridge(sd,
259				init_po1030[i][1],
260				init_po1030[i][2]);
261			break;
262
263		case SENSOR:
264			data[0] = init_po1030[i][2];
265			err = m5602_write_sensor(sd,
266				init_po1030[i][1], data, 1);
267			break;
268
269		default:
270			info("Invalid stream command, exiting init");
271			return -EINVAL;
272		}
273	}
274	if (err < 0)
275		return err;
276
277	if (dump_sensor)
278		po1030_dump_registers(sd);
279
280	err = po1030_set_exposure(&sd->gspca_dev,
281				   sensor_settings[EXPOSURE_IDX]);
282	if (err < 0)
283		return err;
284
285	err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
286	if (err < 0)
287		return err;
288
289	err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
290	if (err < 0)
291		return err;
292
293	err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
294	if (err < 0)
295		return err;
296
297	err = po1030_set_red_balance(&sd->gspca_dev,
298				      sensor_settings[RED_BALANCE_IDX]);
299	if (err < 0)
300		return err;
301
302	err = po1030_set_blue_balance(&sd->gspca_dev,
303				      sensor_settings[BLUE_BALANCE_IDX]);
304	if (err < 0)
305		return err;
306
307	err = po1030_set_green_balance(&sd->gspca_dev,
308				       sensor_settings[GREEN_BALANCE_IDX]);
309	if (err < 0)
310		return err;
311
312	err = po1030_set_auto_white_balance(&sd->gspca_dev,
313				sensor_settings[AUTO_WHITE_BALANCE_IDX]);
314	if (err < 0)
315		return err;
316
317	err = po1030_set_auto_exposure(&sd->gspca_dev,
318				sensor_settings[AUTO_EXPOSURE_IDX]);
319	return err;
320}
321
322int po1030_start(struct sd *sd)
323{
324	struct cam *cam = &sd->gspca_dev.cam;
325	int i, err = 0;
326	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
327	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
328	int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
329	u8 data;
330
331	switch (width) {
332	case 320:
333		data = PO1030_SUBSAMPLING;
334		err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
335		if (err < 0)
336			return err;
337
338		data = ((width + 3) >> 8) & 0xff;
339		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
340		if (err < 0)
341			return err;
342
343		data = (width + 3) & 0xff;
344		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
345		if (err < 0)
346			return err;
347
348		data = ((height + 1) >> 8) & 0xff;
349		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
350		if (err < 0)
351			return err;
352
353		data = (height + 1) & 0xff;
354		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
355
356		height += 6;
357		width -= 1;
358		break;
359
360	case 640:
361		data = 0;
362		err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
363		if (err < 0)
364			return err;
365
366		data = ((width + 7) >> 8) & 0xff;
367		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
368		if (err < 0)
369			return err;
370
371		data = (width + 7) & 0xff;
372		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
373		if (err < 0)
374			return err;
375
376		data = ((height + 3) >> 8) & 0xff;
377		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
378		if (err < 0)
379			return err;
380
381		data = (height + 3) & 0xff;
382		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
383
384		height += 12;
385		width -= 2;
386		break;
387	}
388	err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
389	if (err < 0)
390		return err;
391
392	err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
393	if (err < 0)
394		return err;
395
396	err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
397	if (err < 0)
398		return err;
399
400	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
401	if (err < 0)
402		return err;
403
404	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
405				 ((ver_offs >> 8) & 0xff));
406	if (err < 0)
407		return err;
408
409	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
410	if (err < 0)
411		return err;
412
413	for (i = 0; i < 2 && !err; i++)
414		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
415	if (err < 0)
416		return err;
417
418	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
419	if (err < 0)
420		return err;
421
422	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
423	if (err < 0)
424		return err;
425
426	for (i = 0; i < 2 && !err; i++)
427		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
428
429	for (i = 0; i < 2 && !err; i++)
430		err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
431
432	for (i = 0; i < 2 && !err; i++)
433		err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
434	if (err < 0)
435		return err;
436
437	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
438	if (err < 0)
439		return err;
440
441	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
442	if (err < 0)
443		return err;
444
445	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
446	return err;
447}
448
449static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
450{
451	struct sd *sd = (struct sd *) gspca_dev;
452	s32 *sensor_settings = sd->sensor_priv;
453
454	*val = sensor_settings[EXPOSURE_IDX];
455	PDEBUG(D_V4L2, "Exposure read as %d", *val);
456	return 0;
457}
458
459static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
460{
461	struct sd *sd = (struct sd *) gspca_dev;
462	s32 *sensor_settings = sd->sensor_priv;
463	u8 i2c_data;
464	int err;
465
466	sensor_settings[EXPOSURE_IDX] = val;
467	PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
468
469	i2c_data = ((val & 0xff00) >> 8);
470	PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
471	       i2c_data);
472
473	err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
474				  &i2c_data, 1);
475	if (err < 0)
476		return err;
477
478	i2c_data = (val & 0xff);
479	PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
480	       i2c_data);
481	err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
482				  &i2c_data, 1);
483
484	return err;
485}
486
487static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
488{
489	struct sd *sd = (struct sd *) gspca_dev;
490	s32 *sensor_settings = sd->sensor_priv;
491
492	*val = sensor_settings[GAIN_IDX];
493	PDEBUG(D_V4L2, "Read global gain %d", *val);
494	return 0;
495}
496
497static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
498{
499	struct sd *sd = (struct sd *) gspca_dev;
500	s32 *sensor_settings = sd->sensor_priv;
501	u8 i2c_data;
502	int err;
503
504	sensor_settings[GAIN_IDX] = val;
505
506	i2c_data = val & 0xff;
507	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
508	err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
509				 &i2c_data, 1);
510	return err;
511}
512
513static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
514{
515	struct sd *sd = (struct sd *) gspca_dev;
516	s32 *sensor_settings = sd->sensor_priv;
517
518	*val = sensor_settings[HFLIP_IDX];
519	PDEBUG(D_V4L2, "Read hflip %d", *val);
520
521	return 0;
522}
523
524static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
525{
526	struct sd *sd = (struct sd *) gspca_dev;
527	s32 *sensor_settings = sd->sensor_priv;
528	u8 i2c_data;
529	int err;
530
531	sensor_settings[HFLIP_IDX] = val;
532
533	PDEBUG(D_V4L2, "Set hflip %d", val);
534	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
535	if (err < 0)
536		return err;
537
538	i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
539
540	err = m5602_write_sensor(sd, PO1030_CONTROL2,
541				 &i2c_data, 1);
542
543	return err;
544}
545
546static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
547{
548	struct sd *sd = (struct sd *) gspca_dev;
549	s32 *sensor_settings = sd->sensor_priv;
550
551	*val = sensor_settings[VFLIP_IDX];
552	PDEBUG(D_V4L2, "Read vflip %d", *val);
553
554	return 0;
555}
556
557static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
558{
559	struct sd *sd = (struct sd *) gspca_dev;
560	s32 *sensor_settings = sd->sensor_priv;
561	u8 i2c_data;
562	int err;
563
564	sensor_settings[VFLIP_IDX] = val;
565
566	PDEBUG(D_V4L2, "Set vflip %d", val);
567	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
568	if (err < 0)
569		return err;
570
571	i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
572
573	err = m5602_write_sensor(sd, PO1030_CONTROL2,
574				 &i2c_data, 1);
575
576	return err;
577}
578
579static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
580{
581	struct sd *sd = (struct sd *) gspca_dev;
582	s32 *sensor_settings = sd->sensor_priv;
583
584	*val = sensor_settings[RED_BALANCE_IDX];
585	PDEBUG(D_V4L2, "Read red gain %d", *val);
586	return 0;
587}
588
589static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
590{
591	struct sd *sd = (struct sd *) gspca_dev;
592	s32 *sensor_settings = sd->sensor_priv;
593	u8 i2c_data;
594	int err;
595
596	sensor_settings[RED_BALANCE_IDX] = val;
597
598	i2c_data = val & 0xff;
599	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
600	err = m5602_write_sensor(sd, PO1030_RED_GAIN,
601				  &i2c_data, 1);
602	return err;
603}
604
605static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
606{
607	struct sd *sd = (struct sd *) gspca_dev;
608	s32 *sensor_settings = sd->sensor_priv;
609
610	*val = sensor_settings[BLUE_BALANCE_IDX];
611	PDEBUG(D_V4L2, "Read blue gain %d", *val);
612
613	return 0;
614}
615
616static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
617{
618	struct sd *sd = (struct sd *) gspca_dev;
619	s32 *sensor_settings = sd->sensor_priv;
620	u8 i2c_data;
621	int err;
622
623	sensor_settings[BLUE_BALANCE_IDX] = val;
624
625	i2c_data = val & 0xff;
626	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
627	err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
628				  &i2c_data, 1);
629
630	return err;
631}
632
633static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
634{
635	struct sd *sd = (struct sd *) gspca_dev;
636	s32 *sensor_settings = sd->sensor_priv;
637
638	*val = sensor_settings[GREEN_BALANCE_IDX];
639	PDEBUG(D_V4L2, "Read green gain %d", *val);
640
641	return 0;
642}
643
644static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
645{
646	struct sd *sd = (struct sd *) gspca_dev;
647	s32 *sensor_settings = sd->sensor_priv;
648	u8 i2c_data;
649	int err;
650
651	sensor_settings[GREEN_BALANCE_IDX] = val;
652	i2c_data = val & 0xff;
653	PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
654
655	err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
656			   &i2c_data, 1);
657	if (err < 0)
658		return err;
659
660	return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
661				 &i2c_data, 1);
662}
663
664static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
665					 __s32 *val)
666{
667	struct sd *sd = (struct sd *) gspca_dev;
668	s32 *sensor_settings = sd->sensor_priv;
669
670	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
671	PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
672
673	return 0;
674}
675
676static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
677					 __s32 val)
678{
679	struct sd *sd = (struct sd *) gspca_dev;
680	s32 *sensor_settings = sd->sensor_priv;
681	u8 i2c_data;
682	int err;
683
684	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
685
686	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
687	if (err < 0)
688		return err;
689
690	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
691	i2c_data = (i2c_data & 0xfe) | (val & 0x01);
692	err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
693	return err;
694}
695
696static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
697				    __s32 *val)
698{
699	struct sd *sd = (struct sd *) gspca_dev;
700	s32 *sensor_settings = sd->sensor_priv;
701
702	*val = sensor_settings[AUTO_EXPOSURE_IDX];
703	PDEBUG(D_V4L2, "Auto exposure is %d", *val);
704	return 0;
705}
706
707static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
708				    __s32 val)
709{
710	struct sd *sd = (struct sd *) gspca_dev;
711	s32 *sensor_settings = sd->sensor_priv;
712	u8 i2c_data;
713	int err;
714
715	sensor_settings[AUTO_EXPOSURE_IDX] = val;
716	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
717	if (err < 0)
718		return err;
719
720	PDEBUG(D_V4L2, "Set auto exposure to %d", val);
721	i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
722	return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
723}
724
725void po1030_disconnect(struct sd *sd)
726{
727	sd->sensor = NULL;
728	kfree(sd->sensor_priv);
729}
730
731static void po1030_dump_registers(struct sd *sd)
732{
733	int address;
734	u8 value = 0;
735
736	info("Dumping the po1030 sensor core registers");
737	for (address = 0; address < 0x7f; address++) {
738		m5602_read_sensor(sd, address, &value, 1);
739		info("register 0x%x contains 0x%x",
740		     address, value);
741	}
742
743	info("po1030 register state dump complete");
744
745	info("Probing for which registers that are read/write");
746	for (address = 0; address < 0xff; address++) {
747		u8 old_value, ctrl_value;
748		u8 test_value[2] = {0xff, 0xff};
749
750		m5602_read_sensor(sd, address, &old_value, 1);
751		m5602_write_sensor(sd, address, test_value, 1);
752		m5602_read_sensor(sd, address, &ctrl_value, 1);
753
754		if (ctrl_value == test_value[0])
755			info("register 0x%x is writeable", address);
756		else
757			info("register 0x%x is read only", address);
758
759		/* Restore original value */
760		m5602_write_sensor(sd, address, &old_value, 1);
761	}
762}
763