6 * @brief Common functions and data for Micron sensors.
8 * @note Copyright (C) Comer352l
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/delay.h>
37 static struct micron_init mt9v111_init
[] = {
38 /* 0x0d: Color Correction Register 8 */
40 /* 0x0d: Color Correction Register 8 */
41 {0x0d, 0x0000}, /* ??? */
42 /* 0x02: Color Correction Register 1 */
43 {0x01, 0x0001}, /* select IFP address space */
44 {0x02, 0x0016}, /* ??? */
45 /* 0x03: Color Correction Register 3 */
46 /* 0x04: Color Correction Register 4 */
47 {0x03, 0x01e1}, /* ??? */
48 {0x04, 0x0281}, /* ??? */
49 /* 0x05: Aperture Correction (Sharpening) */
50 {0x05, 0x0004}, /* 100% sharpening,
51 no automatic sharpness reduction at low light: no sharpening */
52 /* 0x07: IFP Soft Reset */
53 /* 0x08: Output Format Control */
54 {0x07, 0x3002}, /* reset */
65 {0x06, 0x301c}, /* stop AWB at the current values,
66 no on-the-fly defect correction, no auto exposure */
67 {0x08, 0x0480}, /* bypass entire image processing,
68 raw 8+2 Bayer data output directly */
69 {0x01, 0x0004}, /* select sensor address space */
70 {0x02, 0x0016}, /* start with column 22 */
71 /* 0x03: Window Height */
72 /* 0x04: Window Width */
73 {0x03, 0x01e6}, /* 486 */
74 {0x04, 0x0286}, /* 646 */
75 /* 0x05: Horizontal Blanking */
76 /* 0x06: Vertical Blanking */
77 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
78 {0x06, 0x0000}, /* 0 rows */
79 /* 0x07: Output Control */
81 {0x07, 0x3002}, /* normal operation + chip enable*/
82 {0x08, 0x0008}, /* row 8 */
83 /* 0x0c: Shutter Delay */
84 /* 0x0d: Reset (Soft) */
85 {0x0c, 0x0000}, /* 0 master clocks */
86 {0x0d, 0x0000}, /* return to normal operation */
91 /* 0x12: 2X Zoom Col Start
92 => 0x1e bit 0 must be set to activate zoom */
93 /* 0x13: 2X Zoom Row Start
94 => 0x1e bit 0 must be set to activate zoom */
95 {0x12, 0x00b0}, /* column 176 */
96 {0x13, 0x007c}, /* row 124 */
110 /* 0x02: Column Start */
111 /* 0x03: Window Height */
112 {0x02, 0x0016}, /* coulmn 22 */
113 {0x03, 0x01e1}, /* 481 */
114 /* 0x04: Window Width */
115 /* 0x05: Horizontal Blanking */
116 {0x04, 0x0281}, /* 641 */
117 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
118 /* 0x06: Vertical Blanking */
119 /* 0x07: Output Control */
120 {0x06, 0x0000}, /* 0 rows */
121 {0x07, 0x3002}, /* normal operation + chip enable */
122 /* 0x06: Vertical Blanking */
123 {0x06, 0x002d}, /* 45 rows */
124 /* 0x05: Horizontal Blanking */
125 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
126 /* 0x09: Shutter Width */
127 {0x09, 0x0064}, /* integration of 100 rows */
128 /* 0x2b: Green 1 Gain */
129 /* 0x2c: Blue Gain */
130 {0x2b, 0x00a0}, /* 32*0.03125*2 = 2 */
131 {0x2c, 0x00a0}, /* 32*0.03125*2 = 2 */
133 /* 0x2e: Green 2 Gain */
134 {0x2d, 0x00a0}, /* 32*0.03125*2 = 2 */
135 {0x2e, 0x00a0}, /* 32*0.03125*2 = 2 */
136 /* 0x02: Column Start */
137 /* 0x03: Window Hight */
138 {0x02, 0x0016}, /* coulmn 22 */
139 {0x03, 0x01e1}, /* 481 */
140 /* 0x04: Window Width */
141 /* 0x05: Horizontal Blanking */
142 {0x04, 0x0281}, /* 641 */
143 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
144 /* 0x06: Vertical Blanking */
145 /* 0x07: Output Control */
146 {0x06, 0x002d}, /* 45 rows */
147 {0x07, 0x3002}, /* RESERVED options */
148 /* Writes to0x0e: UNDOCUMENTED */
150 /* 0x06: Vertical Blanking */
151 {0x06, 0x002d}, /* 45 rows */
152 /* 0x05: Horizontal Blanking */
153 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
156 static struct micron_init mt9v011_init
[] = {
157 /* 0x07: Output Control */
158 {0x07, 0x0002}, /* chip enable, normal operation */
159 /* 0x0d: Soft Reset */
160 {0x0d, 0x0001}, /* reset */
161 /* 0x0d: Soft Reset */
162 {0x0d, 0x0000}, /* resume operation */
163 /* 0x01: Row start */
164 /* 0x02: Column Start */
165 {0x01, 0x0008}, /* start with row 8 */
166 {0x02, 0x0016}, /* start with column 22 */
167 /* 0x03: Window Height */
168 /* 0x04: Window Width */
169 {0x03, 0x01e1}, /* 481 */
170 {0x04, 0x0281}, /* 641 */
171 /* 0x05: Horizontal Blanking */
172 /* 0x06: Vertical Blanking */
173 {0x05, 0x0083}, /* 131 columns (pixel clocks) */
174 {0x06, 0x0006}, /* 6 rows */
175 /* 0x0d: Soft Reset */
176 {0x0d, 0x0002}, /* UNKNOWN */
177 /* 0x0a: Pixel Clock Speed */
178 /* 0x0b: Frame Restart */
179 {0x0a, 0x0000}, /* default */
180 {0x0b, 0x0000}, /* (has no effect/no restart) */
181 /* 0x0c: Shutter Delay */
182 /* 0x0d: Soft Reset */
183 {0x0c, 0x0000}, /* 0 master clocks */
184 {0x0d, 0x0000}, /* resume operation */
189 /* 0x12: 2X Zoom Column Start (from MT9V111 datasheet) */
190 /* 0x13: 2X Zoom Row Start (from MT9V111 datasheet) */
192 /* column 0 => bit0 of reg 0x1e must be set to activate zoom */
194 /* row 0 => bit0 of reg 0x1e must be set to activate zoom */
206 /* 0x20: Read Mode */
207 {0x20, 0x1101}, /* output all frames (including bad frames) */
232 /* 0x0a: Pixel Clock Speed */
233 {0x0a, 0x0000}, /* default */
234 /* 0x06: Vertical Blanking */
235 {0x06, 0x0029}, /* 41 rows */
236 /* 0x05: Horizontal Blanking */
237 {0x05, 0x0009}, /* 9 columns (pixel clocks) */
238 /* 0x20: Read Mode */
239 {0x20, 0x1101}, /* output all frames (including bad ones) */
240 /* 0x20: Read Mode */
241 {0x20, 0x1101}, /* output all frames (including bad ones) */
242 /* 0x09: Shutter Width */
243 {0x09, 0x0064}, /* integration of 100 rows */
244 /* 0x07: Output Control */
246 /* dont update changes until bit0=0, chip enable, normal operation */
247 /* 0x2b: Green 1 Gain */
248 /* 0x2c: Blue Gain */
249 {0x2b, 0x0033}, /* 51*0.03125*1 = 1.59375 */
250 {0x2c, 0x00a0}, /* 32*0.03125*2 = 2 */
252 /* 0x2e: Green 2 Gain */
253 {0x2d, 0x00a0}, /* 32*0.03125*2 = 2 */
254 {0x2e, 0x0033}, /* 51*0.03125*1 = 1.59375 */
255 /* 0x07: Output Control */
256 {0x07, 0x0002}, /* chip enable, normal operation */
257 /* 0x0a: Pixel Clock Speed */
258 {0x06, 0x0000}, /* default */
259 /* 0x06: Vertical Blanking */
260 {0x06, 0x0029}, /* 41 rows */
261 /* 0x05: Horizontal Blanking */
262 {0x05, 0x0009}, /* 9 columns (pixel clocks) */
265 static struct micron_init mt9m111_init
[] = {
270 /* Select Page map 0x01
271 * This means all new writes now have the address prefix 0x1.
272 * Example: 0x3a becomes 0x13a. */
274 /** Select output format:
275 * - output raw bayer (8+2 bit)
276 * FIXME: There are nearly all YUV and RGB variants possible.
277 * Maybe we should use them.
280 /* measure atoexposure through a mix of both possible windows */
282 /* Switch back to Page map 0x00 */
284 /* The following set the resoutiona and window size.
285 * It's a bit more than SXGA.
303 /* Protect settings */
313 /* Blanking (again?) */
319 static struct micron_init mt9m001_init
[] = {
320 {0x07, 0x0000}, {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
321 {0x01, 0x000e}, {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
322 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, {0x09, 0x0000},
323 {0x0a, 0x0000}, {0x0b, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
324 {0x1e, 0x8000}, {0x20, 0x1105}, {0x2b, 0x0008}, {0x2c, 0x0010},
325 {0x2d, 0x0014}, {0x2e, 0x0008}, {0x5f, 0x8904}, {0x60, 0x0000},
326 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, {0x68, 0x0000},
327 {0x20, 0x111d}, {0x06, 0x00f2}, {0x05, 0x0013}, {0x20, 0x111d},
328 {0x20, 0x111d}, {0x07, 0x0003}, {0x2b, 0x0010}, {0x2c, 0x0010},
329 {0x2d, 0x0010}, {0x2e, 0x0010}, {0x07, 0x0002}, {0x07, 0x0003},
330 {0x2c, 0x001d}, {0x2d, 0x001d}, {0x07, 0x0002}, {0x06, 0x00f2},
331 {0x05, 0x0013}, {0x09, 0x0387}, {0x07, 0x0003}, {0x2b, 0x0028},
332 {0x2c, 0x003f}, {0x2d, 0x003f}, {0x2e, 0x0028}, {0x07, 0x0002},
333 {0x09, 0x04f1}, {0x07, 0x0003}, {0x2b, 0x0024}, {0x2c, 0x0039},
334 {0x2d, 0x0039}, {0x2e, 0x0024}, {0x07, 0x0002},
338 * @brief Initialize micron sensors
340 * @param dev Pointer to device structure
342 * @return 0 or negative error code
345 int micron_initialize(struct usb_microdia
*dev
)
351 switch (dev
->camera
.sensor
->id
) {
353 mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_IFP
);
354 for (i
= 0; i
< ARRAY_SIZE(mt9v111_init
); i
++) {
355 ret
= sn9c20x_write_i2c_data16(dev
, 1,
356 mt9v111_init
[i
].address
,
357 &(mt9v111_init
[i
].value
));
364 sn9c20x_write_i2c_data16(dev
, 2, 0xf0, &value
);
365 for (i
= 0; i
< ARRAY_SIZE(mt9m111_init
); i
++) {
366 ret
= sn9c20x_write_i2c_data16(dev
, 1,
367 mt9m111_init
[i
].address
,
368 &(mt9m111_init
[i
].value
));
374 for (i
= 0; i
< ARRAY_SIZE(mt9v011_init
); i
++) {
375 ret
= sn9c20x_write_i2c_data16(dev
, 1,
376 mt9v011_init
[i
].address
,
377 &(mt9v011_init
[i
].value
));
383 for (i
= 0; i
< ARRAY_SIZE(mt9m001_init
); i
++) {
384 ret
= sn9c20x_write_i2c_data16(dev
, 1,
385 mt9m001_init
[i
].address
,
386 &(mt9m001_init
[i
].value
));
398 UDIA_ERROR("Sensor Init failed (%d)! - line %d\n", ret
, i
);
402 int mt9v111_select_address_space(struct usb_microdia
*dev
, __u8 address_space
)
408 /* check if selection is valid: */
409 if ((address_space
!= MT9V111_ADDRESSSPACE_IFP
) &&
410 (address_space
!= MT9V111_ADDRESSSPACE_SENSOR
)) {
411 UDIA_WARNING("invalid register address space "
412 "selection for sensor MT9V111/MI0360SOC !\n");
415 /* read address space slection register: */
418 while ((k
< 3) && (retI2C
!= 0)) {
419 retI2C
= sn9c20x_read_i2c_data(dev
, 2, 0x01, buf
);
420 if (retI2C
!= 0 && k
< 2)
425 UDIA_ERROR("MT9V111/MI0360SOC (I2C-slave 0x5c): "
426 "read of reg0x01 (address space selection) failed !\n");
429 /* check current address space: */
430 if ((buf
[0] != 0x00) || (buf
[1] != address_space
)) {
433 while ((k
< 3) && (retI2C
!= 0)) {
434 /* switch address space: */
435 buf
[0] = 0x00; buf
[1] = address_space
;
436 retI2C
= sn9c20x_write_i2c_data(dev
, 2, 0x01, buf
);
437 if (retI2C
!= 0 && k
< 2)
442 if (address_space
== MT9V111_ADDRESSSPACE_IFP
)
443 UDIA_ERROR("MT9V111/MI0360SOC "
444 "(I2C-slave 0x5c): switch to IFP "
445 "address space failed !\n");
447 UDIA_ERROR("MT9V111/MI0360SOC "
448 "(I2C-slave 0x5c): switch to sensor "
449 "core address space failed !\n");
456 int micron_probe(struct usb_microdia
*dev
)
460 static struct sensor_info dummy
;
462 /* This is necessary to allow I2C/SCCB operation */
463 dev
->camera
.sensor
= &dummy
;
464 dev
->camera
.sensor
->address
= 0x5d;
465 sn9c20x_i2c_initialize(dev
);
467 /* MT9V011 goes first */
468 ret
= sn9c20x_read_i2c_data16(dev
, 2, 0xff, &buf
);
469 if ((ret
== 0) || (buf
== 0x8243))
470 return MT9V011_SENSOR
;
472 /* MT9V111 has a different address */
473 dev
->camera
.sensor
->address
= 0x5c;
475 /* Store old address-space */
476 ret
= sn9c20x_read_i2c_data16(dev
, 2, 0x01, &old
);
480 /* Select address-space: sensor */
481 buf
= MT9V111_ADDRESSSPACE_SENSOR
& 0x00ff;
482 ret
= sn9c20x_write_i2c_data16(dev
, 2, 0x01, &buf
);
486 ret
= sn9c20x_read_i2c_data16(dev
, 2, 0xff, &buf
);
487 if ((ret
== 0) || (buf
== 0x823a)) {
488 sn9c20x_write_i2c_data16(dev
, 2, 0x01, &old
);
489 return MT9V111_SENSOR
;
495 int mt9m111_set_raw(struct usb_microdia
*dev
)
499 /* select address-space: IFP */
501 sn9c20x_write_i2c_data16(dev
, 1, 0xf0, &buf
);
503 sn9c20x_read_i2c_data16(dev
, 1, 0x3a, &buf
);
504 buf
= (buf
& 0xfaff) + 0x0500;
505 sn9c20x_write_i2c_data16(dev
, 1, 0x3a, &buf
);
507 sn9c20x_read_i2c_data16(dev
, 1, 0x9b, &buf
);
508 buf
= (buf
& 0xfaff) + 0x0500;
509 sn9c20x_write_i2c_data16(dev
, 1, 0x9b, &buf
);
511 sn9c20x_set_raw(dev
);
516 int mt9m111_set_yuv422(struct usb_microdia
*dev
)
520 /* select address-space: IFP */
522 sn9c20x_write_i2c_data16(dev
, 1, 0xf0, &buf
);
524 sn9c20x_read_i2c_data16(dev
, 1, 0x3a, &buf
);
526 sn9c20x_write_i2c_data16(dev
, 1, 0x3a, &buf
);
528 sn9c20x_read_i2c_data16(dev
, 1, 0x9b, &buf
);
530 sn9c20x_write_i2c_data16(dev
, 1, 0x9b, &buf
);
532 sn9c20x_set_raw(dev
);
537 int mt9v011_set_exposure(struct usb_microdia
*dev
)
542 buf
[0] = (dev
->vsettings
.exposure
>> 12);
544 ret
|= sn9c20x_write_i2c_data(dev
, 2, 0x09, buf
);
545 /* Maybe we have to disable AE/AWB/flicker avoidence (currently not
546 * used) for MT9V111 sensor, because IFP controls this register if
547 * one of them is enabled. */
551 int mt9v111_set_exposure(struct usb_microdia
*dev
)
557 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_SENSOR
);
560 return -11; /* -EAGAIN */
562 buf
[0] = (dev
->vsettings
.exposure
>> 12);
564 ret
|= sn9c20x_write_i2c_data(dev
, 2, 0x09, buf
);
565 /* Maybe we have to disable AE/AWB/flicker avoidence (currently not
566 * used) for MT9V111 sensor, because IFP controls this register if
567 * one of them is enabled. */
571 int mt9v011_set_hvflip(struct usb_microdia
*dev
)
576 if ((dev
->vsettings
.hflip
> 1) || (dev
->vsettings
.hflip
< 0))
578 if ((dev
->vsettings
.vflip
> 1) || (dev
->vsettings
.vflip
< 0))
581 ret
= sn9c20x_read_i2c_data(dev
, 2, 0x20, buf
);
585 if (dev
->vsettings
.hflip
) {
587 /* (MSB) set bit 15: read out from
588 * bottom to top (upside down) */
590 /* (LSB) set bit 7: readout starting 1 row later */
592 buf
[0] &= 0x7f; /* (MSB) unset bit 15: normal readout */
593 buf
[1] &= 0x7f; /* (LSB) unset bit 7: normal readout */
595 if (dev
->vsettings
.vflip
) {
597 /* (MSB) set bit 14: read out from right to left (mirrored) */
599 /* (LSB) set bit 5: readout starting 1 column later */
601 buf
[0] &= 0xbf; /* (MSB) unset bit 14: normal readout */
602 buf
[1] &= 0xdf; /* (LSB) unset bit 5: normal readout */
605 ret
= sn9c20x_write_i2c_data(dev
, 2, 0x20, buf
);
609 int mt9v111_set_hvflip(struct usb_microdia
*dev
)
614 if ((dev
->vsettings
.hflip
> 1) || (dev
->vsettings
.hflip
< 0))
616 if ((dev
->vsettings
.vflip
> 1) || (dev
->vsettings
.vflip
< 0))
620 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_SENSOR
);
622 return -11; /* -EAGAIN */
624 ret
= sn9c20x_read_i2c_data(dev
, 2, 0x20, buf
);
628 if (dev
->vsettings
.hflip
) {
630 /* (MSB) set bit 15: read out from
631 * bottom to top (upside down) */
633 /* (LSB) set bit 7: readout starting 1 row later */
635 buf
[0] &= 0x7f; /* (MSB) unset bit 15: normal readout */
636 buf
[1] &= 0x7f; /* (LSB) unset bit 7: normal readout */
638 if (dev
->vsettings
.vflip
) {
640 /* (MSB) set bit 14: read out from right to left (mirrored) */
642 /* (LSB) set bit 5: readout starting 1 column later */
644 buf
[0] &= 0xbf; /* (MSB) unset bit 14: normal readout */
645 buf
[1] &= 0xdf; /* (LSB) unset bit 5: normal readout */
648 ret
= sn9c20x_write_i2c_data(dev
, 2, 0x20, buf
);
652 int mt9v111_set_autoexposure(struct usb_microdia
*dev
)
657 /* Switch to IFP-register address space: */
658 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_IFP
);
660 return -11; /* -EAGAIN */
661 /* Read current value of IFP-register 0x06: */
662 ret
= sn9c20x_read_i2c_data16(dev
, 1, MT9V111_IFPREG_OPMODECTL
, buf
);
664 UDIA_ERROR("Error: setting of auto exposure failed: "
665 "error while reading from IFP-register 0x06\n");
669 /* Set new value for register 0x06: */
670 switch (dev
->vsettings
.auto_exposure
) {
671 case V4L2_EXPOSURE_AUTO
:
672 buf
[0] |= MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
674 case V4L2_EXPOSURE_MANUAL
:
675 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
677 case V4L2_EXPOSURE_SHUTTER_PRIORITY
:
678 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
680 case V4L2_EXPOSURE_APERTURE_PRIORITY
:
681 buf
[0] |= MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
686 /* Write new value to IFP-register 0x06: */
687 ret
= sn9c20x_write_i2c_data16(dev
, 1, MT9V111_IFPREG_OPMODECTL
, buf
);
689 UDIA_ERROR("Error: setting of auto exposure failed: "
690 "error while writing to IFP-register 0x06\n");
696 int mt9v111_set_autowhitebalance(struct usb_microdia
*dev
)
701 /* Switch to IFP-register address space: */
702 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_IFP
);
704 return -11; /* -EAGAIN */
705 /* Read current value of IFP-register 0x06: */
706 ret
= sn9c20x_read_i2c_data16(dev
, 1,
707 MT9V111_IFPREG_OPMODECTL
, buf
);
709 UDIA_ERROR("Error: setting of auto whitebalance failed: "
710 "error while reading from IFP-register 0x06\n");
713 /* Set new value for register 0x06: */
714 if (dev
->vsettings
.auto_whitebalance
== 1) {
715 /* Enable automatic exposure: */
716 buf
[0] |= MT9V111_IFP_OPMODE_AUTOWHITEBALANCE
;
717 } else if (dev
->vsettings
.auto_whitebalance
== 0) {
718 /* Disable automatic exposure: */
719 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOWHITEBALANCE
;
722 /* Write new value to IFP-register 0x06:*/
723 ret
= sn9c20x_write_i2c_data16(dev
, 1,
724 MT9V111_IFPREG_OPMODECTL
, buf
);
726 UDIA_ERROR("Error: setting of auto whitebalance failed: "
727 "error while writing to IFP-register 0x06\n");