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
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
#include "m5602_mt9m111.h"
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,
31
static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
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);
40
static struct v4l2_pix_format mt9m111_modes[] = {
46
.sizeimage = 640 * 480,
48
.colorspace = V4L2_COLORSPACE_SRGB,
53
static const struct ctrl mt9m111_ctrls[] = {
58
.type = V4L2_CTRL_TYPE_BOOLEAN,
59
.name = "vertical flip",
65
.set = mt9m111_set_vflip,
66
.get = mt9m111_get_vflip
72
.type = V4L2_CTRL_TYPE_BOOLEAN,
73
.name = "horizontal flip",
79
.set = mt9m111_set_hflip,
80
.get = mt9m111_get_hflip
86
.type = V4L2_CTRL_TYPE_INTEGER,
89
.maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
91
.default_value = MT9M111_DEFAULT_GAIN,
92
.flags = V4L2_CTRL_FLAG_SLIDER
94
.set = mt9m111_set_gain,
95
.get = mt9m111_get_gain
97
#define AUTO_WHITE_BALANCE_IDX 3
100
.id = V4L2_CID_AUTO_WHITE_BALANCE,
101
.type = V4L2_CTRL_TYPE_BOOLEAN,
102
.name = "auto white balance",
108
.set = mt9m111_set_auto_white_balance,
109
.get = mt9m111_get_auto_white_balance
111
#define GREEN_BALANCE_IDX 4
114
.id = M5602_V4L2_CID_GREEN_BALANCE,
115
.type = V4L2_CTRL_TYPE_INTEGER,
116
.name = "green balance",
120
.default_value = MT9M111_GREEN_GAIN_DEFAULT,
121
.flags = V4L2_CTRL_FLAG_SLIDER
123
.set = mt9m111_set_green_balance,
124
.get = mt9m111_get_green_balance
126
#define BLUE_BALANCE_IDX 5
129
.id = V4L2_CID_BLUE_BALANCE,
130
.type = V4L2_CTRL_TYPE_INTEGER,
131
.name = "blue balance",
135
.default_value = MT9M111_BLUE_GAIN_DEFAULT,
136
.flags = V4L2_CTRL_FLAG_SLIDER
138
.set = mt9m111_set_blue_balance,
139
.get = mt9m111_get_blue_balance
141
#define RED_BALANCE_IDX 5
144
.id = V4L2_CID_RED_BALANCE,
145
.type = V4L2_CTRL_TYPE_INTEGER,
146
.name = "red balance",
150
.default_value = MT9M111_RED_GAIN_DEFAULT,
151
.flags = V4L2_CTRL_FLAG_SLIDER
153
.set = mt9m111_set_red_balance,
154
.get = mt9m111_get_red_balance
158
static void mt9m111_dump_registers(struct sd *sd);
160
int mt9m111_probe(struct sd *sd)
162
u8 data[2] = {0x00, 0x00};
164
s32 *sensor_settings;
167
if (force_sensor == MT9M111_SENSOR) {
168
pr_info("Forcing a %s sensor\n", mt9m111.name);
171
/* If we want to force another sensor, don't try to probe this
176
PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
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]);
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);
192
if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
195
if ((data[0] == 0x14) && (data[1] == 0x3a)) {
196
pr_info("Detected a mt9m111 sensor\n");
203
sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
205
if (!sensor_settings)
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);
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;
220
int mt9m111_init(struct sd *sd)
223
s32 *sensor_settings = sd->sensor_priv;
225
/* Init the sensor */
226
for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
229
if (init_mt9m111[i][0] == BRIDGE) {
230
err = m5602_write_bridge(sd,
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);
242
mt9m111_dump_registers(sd);
244
err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
248
err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
252
err = mt9m111_set_green_balance(&sd->gspca_dev,
253
sensor_settings[GREEN_BALANCE_IDX]);
257
err = mt9m111_set_blue_balance(&sd->gspca_dev,
258
sensor_settings[BLUE_BALANCE_IDX]);
262
err = mt9m111_set_red_balance(&sd->gspca_dev,
263
sensor_settings[RED_BALANCE_IDX]);
267
return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
270
int mt9m111_start(struct sd *sd)
274
struct cam *cam = &sd->gspca_dev.cam;
275
s32 *sensor_settings = sd->sensor_priv;
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;
280
for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
281
if (start_mt9m111[i][0] == BRIDGE) {
282
err = m5602_write_bridge(sd,
284
start_mt9m111[i][2]);
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);
295
err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
299
err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
303
for (i = 0; i < 2 && !err; i++)
304
err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
308
err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
312
err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
316
for (i = 0; i < 2 && !err; i++)
317
err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
321
err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
322
(width >> 8) & 0xff);
326
err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
330
err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
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);
343
err = m5602_write_sensor(sd,
344
MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
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);
361
void mt9m111_disconnect(struct sd *sd)
364
kfree(sd->sensor_priv);
367
static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
369
struct sd *sd = (struct sd *) gspca_dev;
370
s32 *sensor_settings = sd->sensor_priv;
372
*val = sensor_settings[VFLIP_IDX];
373
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
378
static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
381
u8 data[2] = {0x00, 0x00};
382
struct sd *sd = (struct sd *) gspca_dev;
383
s32 *sensor_settings = sd->sensor_priv;
385
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
387
sensor_settings[VFLIP_IDX] = val;
389
/* The mt9m111 is flipped by default */
392
/* Set the correct page map */
393
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
397
err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
401
data[1] = (data[1] & 0xfe) | val;
402
err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
407
static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
409
struct sd *sd = (struct sd *) gspca_dev;
410
s32 *sensor_settings = sd->sensor_priv;
412
*val = sensor_settings[HFLIP_IDX];
413
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
418
static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
421
u8 data[2] = {0x00, 0x00};
422
struct sd *sd = (struct sd *) gspca_dev;
423
s32 *sensor_settings = sd->sensor_priv;
425
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
427
sensor_settings[HFLIP_IDX] = val;
429
/* The mt9m111 is flipped by default */
432
/* Set the correct page map */
433
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
437
err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
441
data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
442
err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
447
static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
449
struct sd *sd = (struct sd *) gspca_dev;
450
s32 *sensor_settings = sd->sensor_priv;
452
*val = sensor_settings[GAIN_IDX];
453
PDEBUG(D_V4L2, "Read gain %d", *val);
458
static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
461
struct sd *sd = (struct sd *) gspca_dev;
462
s32 *sensor_settings = sd->sensor_priv;
466
err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
470
sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
471
data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
473
err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
475
PDEBUG(D_V4L2, "Set auto white balance %d", val);
479
static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
481
struct sd *sd = (struct sd *) gspca_dev;
482
s32 *sensor_settings = sd->sensor_priv;
484
*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
485
PDEBUG(D_V4L2, "Read auto white balance %d", *val);
489
static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
492
u8 data[2] = {0x00, 0x00};
493
struct sd *sd = (struct sd *) gspca_dev;
494
s32 *sensor_settings = sd->sensor_priv;
496
sensor_settings[GAIN_IDX] = val;
498
/* Set the correct page map */
499
err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
503
if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
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);
519
data[1] = (tmp & 0xff);
520
data[0] = (tmp & 0xff00) >> 8;
521
PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
524
err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
530
static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
534
struct sd *sd = (struct sd *) gspca_dev;
535
s32 *sensor_settings = sd->sensor_priv;
537
sensor_settings[GREEN_BALANCE_IDX] = val;
538
data[1] = (val & 0xff);
539
data[0] = (val & 0xff00) >> 8;
541
PDEBUG(D_V4L2, "Set green balance %d", val);
542
err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
547
return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
551
static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
553
struct sd *sd = (struct sd *) gspca_dev;
554
s32 *sensor_settings = sd->sensor_priv;
556
*val = sensor_settings[GREEN_BALANCE_IDX];
557
PDEBUG(D_V4L2, "Read green balance %d", *val);
561
static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
564
struct sd *sd = (struct sd *) gspca_dev;
565
s32 *sensor_settings = sd->sensor_priv;
567
sensor_settings[BLUE_BALANCE_IDX] = val;
568
data[1] = (val & 0xff);
569
data[0] = (val & 0xff00) >> 8;
571
PDEBUG(D_V4L2, "Set blue balance %d", val);
573
return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
577
static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
579
struct sd *sd = (struct sd *) gspca_dev;
580
s32 *sensor_settings = sd->sensor_priv;
582
*val = sensor_settings[BLUE_BALANCE_IDX];
583
PDEBUG(D_V4L2, "Read blue balance %d", *val);
587
static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
590
struct sd *sd = (struct sd *) gspca_dev;
591
s32 *sensor_settings = sd->sensor_priv;
593
sensor_settings[RED_BALANCE_IDX] = val;
594
data[1] = (val & 0xff);
595
data[0] = (val & 0xff00) >> 8;
597
PDEBUG(D_V4L2, "Set red balance %d", val);
599
return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
603
static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
605
struct sd *sd = (struct sd *) gspca_dev;
606
s32 *sensor_settings = sd->sensor_priv;
608
*val = sensor_settings[RED_BALANCE_IDX];
609
PDEBUG(D_V4L2, "Read red balance %d", *val);
613
static void mt9m111_dump_registers(struct sd *sd)
615
u8 address, value[2] = {0x00, 0x00};
617
pr_info("Dumping the mt9m111 register state\n");
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]);
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]);
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]);
646
pr_info("mt9m111 register state dump complete\n");