1 /*
2  * Driver for the mt9m111 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 
21 #include "m5602_mt9m111.h"
22 
23 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
24 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
25 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
30 					 __s32 val);
31 static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
32 					  __s32 *val);
33 static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
34 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
35 static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
36 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
37 static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
38 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
39 
40 static struct v4l2_pix_format mt9m111_modes[] = {
41 	{
42 		640,
43 		480,
44 		V4L2_PIX_FMT_SBGGR8,
45 		V4L2_FIELD_NONE,
46 		.sizeimage = 640 * 480,
47 		.bytesperline = 640,
48 		.colorspace = V4L2_COLORSPACE_SRGB,
49 		.priv = 0
50 	}
51 };
52 
53 static const struct ctrl mt9m111_ctrls[] = {
54 #define VFLIP_IDX 0
55 	{
56 		{
57 			.id		= V4L2_CID_VFLIP,
58 			.type           = V4L2_CTRL_TYPE_BOOLEAN,
59 			.name           = "vertical flip",
60 			.minimum        = 0,
61 			.maximum        = 1,
62 			.step           = 1,
63 			.default_value  = 0
64 		},
65 		.set = mt9m111_set_vflip,
66 		.get = mt9m111_get_vflip
67 	},
68 #define HFLIP_IDX 1
69 	{
70 		{
71 			.id             = V4L2_CID_HFLIP,
72 			.type           = V4L2_CTRL_TYPE_BOOLEAN,
73 			.name           = "horizontal flip",
74 			.minimum        = 0,
75 			.maximum        = 1,
76 			.step           = 1,
77 			.default_value  = 0
78 		},
79 		.set = mt9m111_set_hflip,
80 		.get = mt9m111_get_hflip
81 	},
82 #define GAIN_IDX 2
83 	{
84 		{
85 			.id             = V4L2_CID_GAIN,
86 			.type           = V4L2_CTRL_TYPE_INTEGER,
87 			.name           = "gain",
88 			.minimum        = 0,
89 			.maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
90 			.step           = 1,
91 			.default_value  = MT9M111_DEFAULT_GAIN,
92 			.flags          = V4L2_CTRL_FLAG_SLIDER
93 		},
94 		.set = mt9m111_set_gain,
95 		.get = mt9m111_get_gain
96 	},
97 #define AUTO_WHITE_BALANCE_IDX 3
98 	{
99 		{
100 			.id             = V4L2_CID_AUTO_WHITE_BALANCE,
101 			.type           = V4L2_CTRL_TYPE_BOOLEAN,
102 			.name           = "auto white balance",
103 			.minimum        = 0,
104 			.maximum        = 1,
105 			.step           = 1,
106 			.default_value  = 0,
107 		},
108 		.set = mt9m111_set_auto_white_balance,
109 		.get = mt9m111_get_auto_white_balance
110 	},
111 #define GREEN_BALANCE_IDX 4
112 	{
113 		{
114 			.id		= M5602_V4L2_CID_GREEN_BALANCE,
115 			.type		= V4L2_CTRL_TYPE_INTEGER,
116 			.name		= "green balance",
117 			.minimum	= 0x00,
118 			.maximum	= 0x7ff,
119 			.step		= 0x1,
120 			.default_value	= MT9M111_GREEN_GAIN_DEFAULT,
121 			.flags		= V4L2_CTRL_FLAG_SLIDER
122 		},
123 		.set = mt9m111_set_green_balance,
124 		.get = mt9m111_get_green_balance
125 	},
126 #define BLUE_BALANCE_IDX 5
127 	{
128 		{
129 			.id		= V4L2_CID_BLUE_BALANCE,
130 			.type		= V4L2_CTRL_TYPE_INTEGER,
131 			.name		= "blue balance",
132 			.minimum	= 0x00,
133 			.maximum	= 0x7ff,
134 			.step		= 0x1,
135 			.default_value	= MT9M111_BLUE_GAIN_DEFAULT,
136 			.flags		= V4L2_CTRL_FLAG_SLIDER
137 		},
138 		.set = mt9m111_set_blue_balance,
139 		.get = mt9m111_get_blue_balance
140 	},
141 #define RED_BALANCE_IDX 5
142 	{
143 		{
144 			.id		= V4L2_CID_RED_BALANCE,
145 			.type		= V4L2_CTRL_TYPE_INTEGER,
146 			.name		= "red balance",
147 			.minimum	= 0x00,
148 			.maximum	= 0x7ff,
149 			.step		= 0x1,
150 			.default_value	= MT9M111_RED_GAIN_DEFAULT,
151 			.flags		= V4L2_CTRL_FLAG_SLIDER
152 		},
153 		.set = mt9m111_set_red_balance,
154 		.get = mt9m111_get_red_balance
155 	},
156 };
157 
158 static void mt9m111_dump_registers(struct sd *sd);
159 
160 int mt9m111_probe(struct sd *sd)
161 {
162 	u8 data[2] = {0x00, 0x00};
163 	int i;
164 	s32 *sensor_settings;
165 
166 	if (force_sensor) {
167 		if (force_sensor == MT9M111_SENSOR) {
168 			pr_info("Forcing a %s sensor\n", mt9m111.name);
169 			goto sensor_found;
170 		}
171 		/* If we want to force another sensor, don't try to probe this
172 		 * one */
173 		return -ENODEV;
174 	}
175 
176 	PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
177 
178 	/* Do the preinit */
179 	for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
180 		if (preinit_mt9m111[i][0] == BRIDGE) {
181 			m5602_write_bridge(sd,
182 				preinit_mt9m111[i][1],
183 				preinit_mt9m111[i][2]);
184 		} else {
185 			data[0] = preinit_mt9m111[i][2];
186 			data[1] = preinit_mt9m111[i][3];
187 			m5602_write_sensor(sd,
188 				preinit_mt9m111[i][1], data, 2);
189 		}
190 	}
191 
192 	if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
193 		return -ENODEV;
194 
195 	if ((data[0] == 0x14) && (data[1] == 0x3a)) {
196 		pr_info("Detected a mt9m111 sensor\n");
197 		goto sensor_found;
198 	}
199 
200 	return -ENODEV;
201 
202 sensor_found:
203 	sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
204 				  GFP_KERNEL);
205 	if (!sensor_settings)
206 		return -ENOMEM;
207 
208 	sd->gspca_dev.cam.cam_mode = mt9m111_modes;
209 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
210 	sd->desc->ctrls = mt9m111_ctrls;
211 	sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
212 
213 	for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
214 		sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
215 	sd->sensor_priv = sensor_settings;
216 
217 	return 0;
218 }
219 
220 int mt9m111_init(struct sd *sd)
221 {
222 	int i, err = 0;
223 	s32 *sensor_settings = sd->sensor_priv;
224 
225 	/* Init the sensor */
226 	for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
227 		u8 data[2];
228 
229 		if (init_mt9m111[i][0] == BRIDGE) {
230 			err = m5602_write_bridge(sd,
231 				init_mt9m111[i][1],
232 				init_mt9m111[i][2]);
233 		} else {
234 			data[0] = init_mt9m111[i][2];
235 			data[1] = init_mt9m111[i][3];
236 			err = m5602_write_sensor(sd,
237 				init_mt9m111[i][1], data, 2);
238 		}
239 	}
240 
241 	if (dump_sensor)
242 		mt9m111_dump_registers(sd);
243 
244 	err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
245 	if (err < 0)
246 		return err;
247 
248 	err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
249 	if (err < 0)
250 		return err;
251 
252 	err = mt9m111_set_green_balance(&sd->gspca_dev,
253 					 sensor_settings[GREEN_BALANCE_IDX]);
254 	if (err < 0)
255 		return err;
256 
257 	err = mt9m111_set_blue_balance(&sd->gspca_dev,
258 					 sensor_settings[BLUE_BALANCE_IDX]);
259 	if (err < 0)
260 		return err;
261 
262 	err = mt9m111_set_red_balance(&sd->gspca_dev,
263 					sensor_settings[RED_BALANCE_IDX]);
264 	if (err < 0)
265 		return err;
266 
267 	return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
268 }
269 
270 int mt9m111_start(struct sd *sd)
271 {
272 	int i, err = 0;
273 	u8 data[2];
274 	struct cam *cam = &sd->gspca_dev.cam;
275 	s32 *sensor_settings = sd->sensor_priv;
276 
277 	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
278 	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
279 
280 	for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
281 		if (start_mt9m111[i][0] == BRIDGE) {
282 			err = m5602_write_bridge(sd,
283 				start_mt9m111[i][1],
284 				start_mt9m111[i][2]);
285 		} else {
286 			data[0] = start_mt9m111[i][2];
287 			data[1] = start_mt9m111[i][3];
288 			err = m5602_write_sensor(sd,
289 				start_mt9m111[i][1], data, 2);
290 		}
291 	}
292 	if (err < 0)
293 		return err;
294 
295 	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
296 	if (err < 0)
297 		return err;
298 
299 	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
300 	if (err < 0)
301 		return err;
302 
303 	for (i = 0; i < 2 && !err; i++)
304 		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
305 	if (err < 0)
306 		return err;
307 
308 	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
309 	if (err < 0)
310 		return err;
311 
312 	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
313 	if (err < 0)
314 		return err;
315 
316 	for (i = 0; i < 2 && !err; i++)
317 		err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
318 	if (err < 0)
319 		return err;
320 
321 	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
322 				 (width >> 8) & 0xff);
323 	if (err < 0)
324 		return err;
325 
326 	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
327 	if (err < 0)
328 		return err;
329 
330 	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
331 	if (err < 0)
332 		return err;
333 
334 	switch (width) {
335 	case 640:
336 		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
337 		data[0] = MT9M111_RMB_OVER_SIZED;
338 		data[1] = MT9M111_RMB_ROW_SKIP_2X |
339 			  MT9M111_RMB_COLUMN_SKIP_2X |
340 			  (sensor_settings[VFLIP_IDX] << 0) |
341 			  (sensor_settings[HFLIP_IDX] << 1);
342 
343 		err = m5602_write_sensor(sd,
344 					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
345 		break;
346 
347 	case 320:
348 		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
349 		data[0] = MT9M111_RMB_OVER_SIZED;
350 		data[1] = MT9M111_RMB_ROW_SKIP_4X |
351 				MT9M111_RMB_COLUMN_SKIP_4X |
352 				(sensor_settings[VFLIP_IDX] << 0) |
353 				(sensor_settings[HFLIP_IDX] << 1);
354 		err = m5602_write_sensor(sd,
355 					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
356 		break;
357 	}
358 	return err;
359 }
360 
361 void mt9m111_disconnect(struct sd *sd)
362 {
363 	sd->sensor = NULL;
364 	kfree(sd->sensor_priv);
365 }
366 
367 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
368 {
369 	struct sd *sd = (struct sd *) gspca_dev;
370 	s32 *sensor_settings = sd->sensor_priv;
371 
372 	*val = sensor_settings[VFLIP_IDX];
373 	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
374 
375 	return 0;
376 }
377 
378 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
379 {
380 	int err;
381 	u8 data[2] = {0x00, 0x00};
382 	struct sd *sd = (struct sd *) gspca_dev;
383 	s32 *sensor_settings = sd->sensor_priv;
384 
385 	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
386 
387 	sensor_settings[VFLIP_IDX] = val;
388 
389 	/* The mt9m111 is flipped by default */
390 	val = !val;
391 
392 	/* Set the correct page map */
393 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
394 	if (err < 0)
395 		return err;
396 
397 	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
398 	if (err < 0)
399 		return err;
400 
401 	data[1] = (data[1] & 0xfe) | val;
402 	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
403 				   data, 2);
404 	return err;
405 }
406 
407 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
408 {
409 	struct sd *sd = (struct sd *) gspca_dev;
410 	s32 *sensor_settings = sd->sensor_priv;
411 
412 	*val = sensor_settings[HFLIP_IDX];
413 	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
414 
415 	return 0;
416 }
417 
418 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
419 {
420 	int err;
421 	u8 data[2] = {0x00, 0x00};
422 	struct sd *sd = (struct sd *) gspca_dev;
423 	s32 *sensor_settings = sd->sensor_priv;
424 
425 	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
426 
427 	sensor_settings[HFLIP_IDX] = val;
428 
429 	/* The mt9m111 is flipped by default */
430 	val = !val;
431 
432 	/* Set the correct page map */
433 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
434 	if (err < 0)
435 		return err;
436 
437 	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
438 	if (err < 0)
439 		return err;
440 
441 	data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
442 	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
443 					data, 2);
444 	return err;
445 }
446 
447 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
448 {
449 	struct sd *sd = (struct sd *) gspca_dev;
450 	s32 *sensor_settings = sd->sensor_priv;
451 
452 	*val = sensor_settings[GAIN_IDX];
453 	PDEBUG(D_V4L2, "Read gain %d", *val);
454 
455 	return 0;
456 }
457 
458 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
459 					  __s32 val)
460 {
461 	struct sd *sd = (struct sd *) gspca_dev;
462 	s32 *sensor_settings = sd->sensor_priv;
463 	int err;
464 	u8 data[2];
465 
466 	err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
467 	if (err < 0)
468 		return err;
469 
470 	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
471 	data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
472 
473 	err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
474 
475 	PDEBUG(D_V4L2, "Set auto white balance %d", val);
476 	return err;
477 }
478 
479 static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
480 					  __s32 *val) {
481 	struct sd *sd = (struct sd *) gspca_dev;
482 	s32 *sensor_settings = sd->sensor_priv;
483 
484 	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
485 	PDEBUG(D_V4L2, "Read auto white balance %d", *val);
486 	return 0;
487 }
488 
489 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
490 {
491 	int err, tmp;
492 	u8 data[2] = {0x00, 0x00};
493 	struct sd *sd = (struct sd *) gspca_dev;
494 	s32 *sensor_settings = sd->sensor_priv;
495 
496 	sensor_settings[GAIN_IDX] = val;
497 
498 	/* Set the correct page map */
499 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
500 	if (err < 0)
501 		return err;
502 
503 	if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
504 		return -EINVAL;
505 
506 	if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
507 	    (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
508 		tmp = (1 << 10) | (val << 9) |
509 				(val << 8) | (val / 8);
510 	else if ((val >= INITIAL_MAX_GAIN * 2) &&
511 		 (val <  INITIAL_MAX_GAIN * 2 * 2))
512 		tmp = (1 << 9) | (1 << 8) | (val / 4);
513 	else if ((val >= INITIAL_MAX_GAIN) &&
514 		 (val < INITIAL_MAX_GAIN * 2))
515 		tmp = (1 << 8) | (val / 2);
516 	else
517 		tmp = val;
518 
519 	data[1] = (tmp & 0xff);
520 	data[0] = (tmp & 0xff00) >> 8;
521 	PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
522 	       data[1], data[0]);
523 
524 	err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
525 				   data, 2);
526 
527 	return err;
528 }
529 
530 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
531 {
532 	int err;
533 	u8 data[2];
534 	struct sd *sd = (struct sd *) gspca_dev;
535 	s32 *sensor_settings = sd->sensor_priv;
536 
537 	sensor_settings[GREEN_BALANCE_IDX] = val;
538 	data[1] = (val & 0xff);
539 	data[0] = (val & 0xff00) >> 8;
540 
541 	PDEBUG(D_V4L2, "Set green balance %d", val);
542 	err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
543 				 data, 2);
544 	if (err < 0)
545 		return err;
546 
547 	return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
548 				  data, 2);
549 }
550 
551 static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
552 {
553 	struct sd *sd = (struct sd *) gspca_dev;
554 	s32 *sensor_settings = sd->sensor_priv;
555 
556 	*val = sensor_settings[GREEN_BALANCE_IDX];
557 	PDEBUG(D_V4L2, "Read green balance %d", *val);
558 	return 0;
559 }
560 
561 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
562 {
563 	u8 data[2];
564 	struct sd *sd = (struct sd *) gspca_dev;
565 	s32 *sensor_settings = sd->sensor_priv;
566 
567 	sensor_settings[BLUE_BALANCE_IDX] = val;
568 	data[1] = (val & 0xff);
569 	data[0] = (val & 0xff00) >> 8;
570 
571 	PDEBUG(D_V4L2, "Set blue balance %d", val);
572 
573 	return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
574 				  data, 2);
575 }
576 
577 static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
578 {
579 	struct sd *sd = (struct sd *) gspca_dev;
580 	s32 *sensor_settings = sd->sensor_priv;
581 
582 	*val = sensor_settings[BLUE_BALANCE_IDX];
583 	PDEBUG(D_V4L2, "Read blue balance %d", *val);
584 	return 0;
585 }
586 
587 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
588 {
589 	u8 data[2];
590 	struct sd *sd = (struct sd *) gspca_dev;
591 	s32 *sensor_settings = sd->sensor_priv;
592 
593 	sensor_settings[RED_BALANCE_IDX] = val;
594 	data[1] = (val & 0xff);
595 	data[0] = (val & 0xff00) >> 8;
596 
597 	PDEBUG(D_V4L2, "Set red balance %d", val);
598 
599 	return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
600 				  data, 2);
601 }
602 
603 static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
604 {
605 	struct sd *sd = (struct sd *) gspca_dev;
606 	s32 *sensor_settings = sd->sensor_priv;
607 
608 	*val = sensor_settings[RED_BALANCE_IDX];
609 	PDEBUG(D_V4L2, "Read red balance %d", *val);
610 	return 0;
611 }
612 
613 static void mt9m111_dump_registers(struct sd *sd)
614 {
615 	u8 address, value[2] = {0x00, 0x00};
616 
617 	pr_info("Dumping the mt9m111 register state\n");
618 
619 	pr_info("Dumping the mt9m111 sensor core registers\n");
620 	value[1] = MT9M111_SENSOR_CORE;
621 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
622 	for (address = 0; address < 0xff; address++) {
623 		m5602_read_sensor(sd, address, value, 2);
624 		pr_info("register 0x%x contains 0x%x%x\n",
625 			address, value[0], value[1]);
626 	}
627 
628 	pr_info("Dumping the mt9m111 color pipeline registers\n");
629 	value[1] = MT9M111_COLORPIPE;
630 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
631 	for (address = 0; address < 0xff; address++) {
632 		m5602_read_sensor(sd, address, value, 2);
633 		pr_info("register 0x%x contains 0x%x%x\n",
634 			address, value[0], value[1]);
635 	}
636 
637 	pr_info("Dumping the mt9m111 camera control registers\n");
638 	value[1] = MT9M111_CAMERA_CONTROL;
639 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
640 	for (address = 0; address < 0xff; address++) {
641 		m5602_read_sensor(sd, address, value, 2);
642 		pr_info("register 0x%x contains 0x%x%x\n",
643 			address, value[0], value[1]);
644 	}
645 
646 	pr_info("mt9m111 register state dump complete\n");
647 }
648