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