2 * Driver for the mt9m111 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_mt9m111.h"
21 static int mt9m111_set_vflip(struct gspca_dev
*gspca_dev
, __s32 val
);
22 static int mt9m111_get_vflip(struct gspca_dev
*gspca_dev
, __s32
*val
);
23 static int mt9m111_get_hflip(struct gspca_dev
*gspca_dev
, __s32
*val
);
24 static int mt9m111_set_hflip(struct gspca_dev
*gspca_dev
, __s32 val
);
25 static int mt9m111_get_gain(struct gspca_dev
*gspca_dev
, __s32
*val
);
26 static int mt9m111_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
);
27 static int mt9m111_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
29 static int mt9m111_get_auto_white_balance(struct gspca_dev
*gspca_dev
,
31 static int mt9m111_get_green_balance(struct gspca_dev
*gspca_dev
, __s32
*val
);
32 static int mt9m111_set_green_balance(struct gspca_dev
*gspca_dev
, __s32 val
);
33 static int mt9m111_get_blue_balance(struct gspca_dev
*gspca_dev
, __s32
*val
);
34 static int mt9m111_set_blue_balance(struct gspca_dev
*gspca_dev
, __s32 val
);
35 static int mt9m111_get_red_balance(struct gspca_dev
*gspca_dev
, __s32
*val
);
36 static int mt9m111_set_red_balance(struct gspca_dev
*gspca_dev
, __s32 val
);
38 static struct v4l2_pix_format mt9m111_modes
[] = {
44 .sizeimage
= 320 * 240,
46 .colorspace
= V4L2_COLORSPACE_SRGB
,
53 .sizeimage
= 640 * 480,
55 .colorspace
= V4L2_COLORSPACE_SRGB
,
60 const static struct ctrl mt9m111_ctrls
[] = {
65 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
66 .name
= "vertical flip",
72 .set
= mt9m111_set_vflip
,
73 .get
= mt9m111_get_vflip
79 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
80 .name
= "horizontal flip",
86 .set
= mt9m111_set_hflip
,
87 .get
= mt9m111_get_hflip
93 .type
= V4L2_CTRL_TYPE_INTEGER
,
96 .maximum
= (INITIAL_MAX_GAIN
- 1) * 2 * 2 * 2,
98 .default_value
= DEFAULT_GAIN
,
99 .flags
= V4L2_CTRL_FLAG_SLIDER
101 .set
= mt9m111_set_gain
,
102 .get
= mt9m111_get_gain
104 #define AUTO_WHITE_BALANCE_IDX 3
107 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
108 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
109 .name
= "auto white balance",
115 .set
= mt9m111_set_auto_white_balance
,
116 .get
= mt9m111_get_auto_white_balance
118 #define GREEN_BALANCE_IDX 4
121 .id
= M5602_V4L2_CID_GREEN_BALANCE
,
122 .type
= V4L2_CTRL_TYPE_INTEGER
,
123 .name
= "green balance",
127 .default_value
= MT9M111_GREEN_GAIN_DEFAULT
,
128 .flags
= V4L2_CTRL_FLAG_SLIDER
130 .set
= mt9m111_set_green_balance
,
131 .get
= mt9m111_get_green_balance
133 #define BLUE_BALANCE_IDX 5
136 .id
= V4L2_CID_BLUE_BALANCE
,
137 .type
= V4L2_CTRL_TYPE_INTEGER
,
138 .name
= "blue balance",
142 .default_value
= MT9M111_BLUE_GAIN_DEFAULT
,
143 .flags
= V4L2_CTRL_FLAG_SLIDER
145 .set
= mt9m111_set_blue_balance
,
146 .get
= mt9m111_get_blue_balance
148 #define RED_BALANCE_IDX 5
151 .id
= V4L2_CID_RED_BALANCE
,
152 .type
= V4L2_CTRL_TYPE_INTEGER
,
153 .name
= "red balance",
157 .default_value
= MT9M111_RED_GAIN_DEFAULT
,
158 .flags
= V4L2_CTRL_FLAG_SLIDER
160 .set
= mt9m111_set_red_balance
,
161 .get
= mt9m111_get_red_balance
165 static void mt9m111_dump_registers(struct sd
*sd
);
167 int mt9m111_probe(struct sd
*sd
)
169 u8 data
[2] = {0x00, 0x00};
171 s32
*sensor_settings
;
174 if (force_sensor
== MT9M111_SENSOR
) {
175 info("Forcing a %s sensor", mt9m111
.name
);
178 /* If we want to force another sensor, don't try to probe this
183 info("Probing for a mt9m111 sensor");
186 for (i
= 0; i
< ARRAY_SIZE(preinit_mt9m111
); i
++) {
187 if (preinit_mt9m111
[i
][0] == BRIDGE
) {
188 m5602_write_bridge(sd
,
189 preinit_mt9m111
[i
][1],
190 preinit_mt9m111
[i
][2]);
192 data
[0] = preinit_mt9m111
[i
][2];
193 data
[1] = preinit_mt9m111
[i
][3];
194 m5602_write_sensor(sd
,
195 preinit_mt9m111
[i
][1], data
, 2);
199 if (m5602_read_sensor(sd
, MT9M111_SC_CHIPVER
, data
, 2))
202 if ((data
[0] == 0x14) && (data
[1] == 0x3a)) {
203 info("Detected a mt9m111 sensor");
210 sensor_settings
= kmalloc(ARRAY_SIZE(mt9m111_ctrls
) * sizeof(s32
),
212 if (!sensor_settings
)
215 sd
->gspca_dev
.cam
.cam_mode
= mt9m111_modes
;
216 sd
->gspca_dev
.cam
.nmodes
= ARRAY_SIZE(mt9m111_modes
);
217 sd
->desc
->ctrls
= mt9m111_ctrls
;
218 sd
->desc
->nctrls
= ARRAY_SIZE(mt9m111_ctrls
);
220 for (i
= 0; i
< ARRAY_SIZE(mt9m111_ctrls
); i
++)
221 sensor_settings
[i
] = mt9m111_ctrls
[i
].qctrl
.default_value
;
222 sd
->sensor_priv
= sensor_settings
;
227 int mt9m111_init(struct sd
*sd
)
230 s32
*sensor_settings
= sd
->sensor_priv
;
232 /* Init the sensor */
233 for (i
= 0; i
< ARRAY_SIZE(init_mt9m111
) && !err
; i
++) {
236 if (init_mt9m111
[i
][0] == BRIDGE
) {
237 err
= m5602_write_bridge(sd
,
241 data
[0] = init_mt9m111
[i
][2];
242 data
[1] = init_mt9m111
[i
][3];
243 err
= m5602_write_sensor(sd
,
244 init_mt9m111
[i
][1], data
, 2);
249 mt9m111_dump_registers(sd
);
251 err
= mt9m111_set_vflip(&sd
->gspca_dev
, sensor_settings
[VFLIP_IDX
]);
255 err
= mt9m111_set_hflip(&sd
->gspca_dev
, sensor_settings
[HFLIP_IDX
]);
259 err
= mt9m111_set_green_balance(&sd
->gspca_dev
,
260 sensor_settings
[GREEN_BALANCE_IDX
]);
264 err
= mt9m111_set_blue_balance(&sd
->gspca_dev
,
265 sensor_settings
[BLUE_BALANCE_IDX
]);
269 err
= mt9m111_set_red_balance(&sd
->gspca_dev
,
270 sensor_settings
[RED_BALANCE_IDX
]);
274 return mt9m111_set_gain(&sd
->gspca_dev
, sensor_settings
[GAIN_IDX
]);
277 int mt9m111_start(struct sd
*sd
)
281 struct cam
*cam
= &sd
->gspca_dev
.cam
;
282 s32
*sensor_settings
= sd
->sensor_priv
;
284 int width
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].width
- 1;
285 int height
= cam
->cam_mode
[sd
->gspca_dev
.curr_mode
].height
;
287 for (i
= 0; i
< ARRAY_SIZE(start_mt9m111
) && !err
; i
++) {
288 if (start_mt9m111
[i
][0] == BRIDGE
) {
289 err
= m5602_write_bridge(sd
,
291 start_mt9m111
[i
][2]);
293 data
[0] = start_mt9m111
[i
][2];
294 data
[1] = start_mt9m111
[i
][3];
295 err
= m5602_write_sensor(sd
,
296 start_mt9m111
[i
][1], data
, 2);
302 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
>> 8) & 0xff);
306 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, (height
& 0xff));
310 for (i
= 0; i
< 2 && !err
; i
++)
311 err
= m5602_write_bridge(sd
, M5602_XB_VSYNC_PARA
, 0);
315 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 0);
319 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 2);
323 for (i
= 0; i
< 2 && !err
; i
++)
324 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
, 0);
328 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
,
329 (width
>> 8) & 0xff);
333 err
= m5602_write_bridge(sd
, M5602_XB_HSYNC_PARA
, width
& 0xff);
337 err
= m5602_write_bridge(sd
, M5602_XB_SIG_INI
, 0);
343 PDEBUG(D_V4L2
, "Configuring camera for VGA mode");
344 data
[0] = MT9M111_RMB_OVER_SIZED
;
345 data
[1] = MT9M111_RMB_ROW_SKIP_2X
|
346 MT9M111_RMB_COLUMN_SKIP_2X
|
347 (sensor_settings
[VFLIP_IDX
] << 0) |
348 (sensor_settings
[HFLIP_IDX
] << 1);
350 err
= m5602_write_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
, data
, 2);
354 PDEBUG(D_V4L2
, "Configuring camera for QVGA mode");
355 data
[0] = MT9M111_RMB_OVER_SIZED
;
356 data
[1] = MT9M111_RMB_ROW_SKIP_4X
|
357 MT9M111_RMB_COLUMN_SKIP_4X
|
358 (sensor_settings
[VFLIP_IDX
] << 0) |
359 (sensor_settings
[HFLIP_IDX
] << 1);
360 err
= m5602_write_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
, data
, 2);
366 void mt9m111_disconnect(struct sd
*sd
)
369 kfree(sd
->sensor_priv
);
372 static int mt9m111_get_vflip(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
[VFLIP_IDX
];
378 PDEBUG(D_V4L2
, "Read vertical flip %d", *val
);
383 static int mt9m111_set_vflip(struct gspca_dev
*gspca_dev
, __s32 val
)
386 u8 data
[2] = {0x00, 0x00};
387 struct sd
*sd
= (struct sd
*) gspca_dev
;
388 s32
*sensor_settings
= sd
->sensor_priv
;
390 PDEBUG(D_V4L2
, "Set vertical flip to %d", val
);
392 sensor_settings
[VFLIP_IDX
] = val
;
394 /* Set the correct page map */
395 err
= m5602_write_sensor(sd
, MT9M111_PAGE_MAP
, data
, 2);
399 err
= m5602_read_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
, data
, 2);
403 data
[0] = (data
[0] & 0xfe) | val
;
404 err
= m5602_write_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
,
409 static int mt9m111_get_hflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
411 struct sd
*sd
= (struct sd
*) gspca_dev
;
412 s32
*sensor_settings
= sd
->sensor_priv
;
414 *val
= sensor_settings
[HFLIP_IDX
];
415 PDEBUG(D_V4L2
, "Read horizontal flip %d", *val
);
420 static int mt9m111_set_hflip(struct gspca_dev
*gspca_dev
, __s32 val
)
423 u8 data
[2] = {0x00, 0x00};
424 struct sd
*sd
= (struct sd
*) gspca_dev
;
425 s32
*sensor_settings
= sd
->sensor_priv
;
427 PDEBUG(D_V4L2
, "Set horizontal flip to %d", val
);
429 sensor_settings
[HFLIP_IDX
] = val
;
430 /* Set the correct page map */
431 err
= m5602_write_sensor(sd
, MT9M111_PAGE_MAP
, data
, 2);
435 err
= m5602_read_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
, data
, 2);
439 data
[0] = (data
[0] & 0xfd) | ((val
<< 1) & 0x02);
440 err
= m5602_write_sensor(sd
, MT9M111_SC_R_MODE_CONTEXT_B
,
445 static int mt9m111_get_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
447 struct sd
*sd
= (struct sd
*) gspca_dev
;
448 s32
*sensor_settings
= sd
->sensor_priv
;
450 *val
= sensor_settings
[GAIN_IDX
];
451 PDEBUG(D_V4L2
, "Read gain %d", *val
);
456 static int mt9m111_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
459 struct sd
*sd
= (struct sd
*) gspca_dev
;
460 s32
*sensor_settings
= sd
->sensor_priv
;
464 err
= m5602_read_sensor(sd
, MT9M111_CP_OPERATING_MODE_CTL
, data
, 2);
468 sensor_settings
[AUTO_WHITE_BALANCE_IDX
] = val
& 0x01;
469 data
[0] = ((data
[0] & 0xfd) | ((val
& 0x01) << 1));
471 err
= m5602_write_sensor(sd
, MT9M111_CP_OPERATING_MODE_CTL
, data
, 2);
473 PDEBUG(D_V4L2
, "Set auto white balance %d", val
);
477 static int mt9m111_get_auto_white_balance(struct gspca_dev
*gspca_dev
,
479 struct sd
*sd
= (struct sd
*) gspca_dev
;
480 s32
*sensor_settings
= sd
->sensor_priv
;
482 *val
= sensor_settings
[AUTO_WHITE_BALANCE_IDX
];
483 PDEBUG(D_V4L2
, "Read auto white balance %d", *val
);
487 static int mt9m111_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
490 u8 data
[2] = {0x00, 0x00};
491 struct sd
*sd
= (struct sd
*) gspca_dev
;
492 s32
*sensor_settings
= sd
->sensor_priv
;
494 sensor_settings
[GAIN_IDX
] = val
;
496 /* Set the correct page map */
497 err
= m5602_write_sensor(sd
, MT9M111_PAGE_MAP
, data
, 2);
501 if (val
>= INITIAL_MAX_GAIN
* 2 * 2 * 2)
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);
517 data
[1] = (tmp
& 0xff00) >> 8;
518 data
[0] = (tmp
& 0xff);
519 PDEBUG(D_V4L2
, "tmp=%d, data[1]=%d, data[0]=%d", tmp
,
522 err
= m5602_write_sensor(sd
, MT9M111_SC_GLOBAL_GAIN
,
528 static int mt9m111_set_green_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
532 struct sd
*sd
= (struct sd
*) gspca_dev
;
533 s32
*sensor_settings
= sd
->sensor_priv
;
535 sensor_settings
[GREEN_BALANCE_IDX
] = val
;
536 data
[0] = (val
& 0xff);
537 data
[1] = (val
& 0xff00) >> 8;
539 PDEBUG(D_V4L2
, "Set green balance %d", val
);
540 err
= m5602_write_sensor(sd
, MT9M111_SC_GREEN_1_GAIN
,
545 return m5602_write_sensor(sd
, MT9M111_SC_GREEN_2_GAIN
,
549 static int mt9m111_get_green_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
551 struct sd
*sd
= (struct sd
*) gspca_dev
;
552 s32
*sensor_settings
= sd
->sensor_priv
;
554 *val
= sensor_settings
[GREEN_BALANCE_IDX
];
555 PDEBUG(D_V4L2
, "Read green balance %d", *val
);
559 static int mt9m111_set_blue_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
562 struct sd
*sd
= (struct sd
*) gspca_dev
;
563 s32
*sensor_settings
= sd
->sensor_priv
;
565 sensor_settings
[BLUE_BALANCE_IDX
] = val
;
566 data
[0] = (val
& 0xff);
567 data
[1] = (val
& 0xff00) >> 8;
569 PDEBUG(D_V4L2
, "Set blue balance %d", val
);
571 return m5602_write_sensor(sd
, MT9M111_SC_BLUE_GAIN
,
575 static int mt9m111_get_blue_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
577 struct sd
*sd
= (struct sd
*) gspca_dev
;
578 s32
*sensor_settings
= sd
->sensor_priv
;
580 *val
= sensor_settings
[BLUE_BALANCE_IDX
];
581 PDEBUG(D_V4L2
, "Read blue balance %d", *val
);
585 static int mt9m111_set_red_balance(struct gspca_dev
*gspca_dev
, __s32 val
)
588 struct sd
*sd
= (struct sd
*) gspca_dev
;
589 s32
*sensor_settings
= sd
->sensor_priv
;
591 sensor_settings
[RED_BALANCE_IDX
] = val
;
592 data
[0] = (val
& 0xff);
593 data
[1] = (val
& 0xff00) >> 8;
595 PDEBUG(D_V4L2
, "Set red balance %d", val
);
597 return m5602_write_sensor(sd
, MT9M111_SC_RED_GAIN
,
601 static int mt9m111_get_red_balance(struct gspca_dev
*gspca_dev
, __s32
*val
)
603 struct sd
*sd
= (struct sd
*) gspca_dev
;
604 s32
*sensor_settings
= sd
->sensor_priv
;
606 *val
= sensor_settings
[RED_BALANCE_IDX
];
607 PDEBUG(D_V4L2
, "Read red balance %d", *val
);
611 static void mt9m111_dump_registers(struct sd
*sd
)
613 u8 address
, value
[2] = {0x00, 0x00};
615 info("Dumping the mt9m111 register state");
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]);
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]);
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]);
644 info("mt9m111 register state dump complete");