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>
29 #include "sn9c20x-bridge.h"
32 struct sn9c20x_i2c_regs mt9v112_init
[] = {
33 {0x0d, 0x0021}, {0x0d, 0x0020}, {0xf0, 0x0000},
34 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
35 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
36 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
37 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
38 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
39 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
40 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
41 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
42 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
43 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
44 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
45 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
46 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
47 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
48 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
52 struct sn9c20x_i2c_regs mt9v111_init
[] = {
53 {0x01, 0x0004}, /* select sensor address space */
54 {0x0d, 0x0001}, /* Resets chip */
56 {0x01, 0x0001}, /* select IFP address space */
57 {0x02, 0x0016}, /* ??? */
58 /* 0x03: Color Correction Register 3 */
59 /* 0x04: Color Correction Register 4 */
60 {0x03, 0x01e1}, /* ??? */
61 {0x04, 0x0281}, /* ??? */
62 /* 0x05: Aperture Correction (Sharpening) */
63 {0x05, 0x0004}, /* 100% sharpening,
64 no automatic sharpness reduction at low light: no sharpening */
65 /* 0x07: IFP Soft Reset */
66 /* 0x08: Output Format Control */
67 {0x07, 0x3002}, /* reset */
78 {0x06, 0x301c}, /* stop AWB at the current values,
80 {0x08, 0x0480}, /* bypass entire image processing,
81 raw 8+2 Bayer data output directly */
82 {0x01, 0x0004}, /* select sensor address space */
83 {0x02, 0x0016}, /* start with column 22 */
84 /* 0x03: Window Height */
85 /* 0x04: Window Width */
86 {0x03, 0x01e6}, /* 486 */
87 {0x04, 0x0286}, /* 646 */
88 /* 0x05: Horizontal Blanking */
89 /* 0x06: Vertical Blanking */
90 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
91 {0x06, 0x0000}, /* 0 rows */
92 /* 0x07: Output Control */
94 {0x07, 0x3002}, /* normal operation + chip enable*/
95 {0x08, 0x0008}, /* row 8 */
96 /* 0x0c: Shutter Delay */
97 /* 0x0d: Reset (Soft) */
98 {0x0c, 0x0000}, /* 0 master clocks */
99 {0x0d, 0x0000}, /* return to normal operation */
104 /* 0x12: 2X Zoom Col Start
105 => 0x1e bit 0 must be set to activate zoom */
106 /* 0x13: 2X Zoom Row Start
107 => 0x1e bit 0 must be set to activate zoom */
108 {0x12, 0x00b0}, /* column 176 */
109 {0x13, 0x007c}, /* row 124 */
123 /* 0x02: Column Start */
124 /* 0x03: Window Height */
125 {0x02, 0x0016}, /* coulmn 22 */
126 {0x03, 0x01e1}, /* 481 */
127 /* 0x04: Window Width */
128 /* 0x05: Horizontal Blanking */
129 {0x04, 0x0281}, /* 641 */
130 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
131 /* 0x06: Vertical Blanking */
132 /* 0x07: Output Control */
133 {0x06, 0x0000}, /* 0 rows */
134 {0x07, 0x3002}, /* normal operation + chip enable */
135 /* 0x06: Vertical Blanking */
136 {0x06, 0x002d}, /* 45 rows */
137 /* 0x05: Horizontal Blanking */
138 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
139 /* 0x09: Shutter Width */
140 {0x09, 0x0064}, /* integration of 100 rows */
141 /* 0x2b: Green 1 Gain */
142 /* 0x2c: Blue Gain */
143 {0x2b, 0x00a0}, /* 32*0.03125*2 = 2 */
144 {0x2c, 0x00a0}, /* 32*0.03125*2 = 2 */
146 /* 0x2e: Green 2 Gain */
147 {0x2d, 0x00a0}, /* 32*0.03125*2 = 2 */
148 {0x2e, 0x00a0}, /* 32*0.03125*2 = 2 */
149 /* 0x02: Column Start */
150 /* 0x03: Window Hight */
151 {0x02, 0x0016}, /* coulmn 22 */
152 {0x03, 0x01e1}, /* 481 */
153 /* 0x04: Window Width */
154 /* 0x05: Horizontal Blanking */
155 {0x04, 0x0281}, /* 641 */
156 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
157 /* 0x06: Vertical Blanking */
158 /* 0x07: Output Control */
159 {0x06, 0x002d}, /* 45 rows */
160 {0x07, 0x3002}, /* RESERVED options */
161 /* Writes to0x0e: UNDOCUMENTED */
163 /* 0x06: Vertical Blanking */
164 {0x06, 0x002d}, /* 45 rows */
165 /* 0x05: Horizontal Blanking */
166 {0x05, 0x0004}, /* 4 columns (pixel clocks) */
170 struct sn9c20x_i2c_regs mt9v011_init
[] = {
171 /* 0x07: Output Control */
172 {0x07, 0x0002}, /* chip enable, normal operation */
173 /* 0x0d: Soft Reset */
174 {0x0d, 0x0001}, /* reset */
175 /* 0x0d: Soft Reset */
176 {0x0d, 0x0000}, /* resume operation */
177 /* 0x01: Row start */
178 /* 0x02: Column Start */
179 {0x01, 0x0008}, /* start with row 8 */
180 {0x02, 0x0016}, /* start with column 22 */
181 /* 0x03: Window Height */
182 /* 0x04: Window Width */
183 {0x03, 0x01e1}, /* 481 */
184 {0x04, 0x0281}, /* 641 */
185 /* 0x05: Horizontal Blanking */
186 /* 0x06: Vertical Blanking */
187 {0x05, 0x0083}, /* 131 columns (pixel clocks) */
188 {0x06, 0x0006}, /* 6 rows */
189 /* 0x0d: Soft Reset */
190 {0x0d, 0x0002}, /* UNKNOWN */
191 /* 0x0a: Pixel Clock Speed */
192 /* 0x0b: Frame Restart */
193 {0x0a, 0x0000}, /* default */
194 {0x0b, 0x0000}, /* (has no effect/no restart) */
195 /* 0x0c: Shutter Delay */
196 /* 0x0d: Soft Reset */
197 {0x0c, 0x0000}, /* 0 master clocks */
198 {0x0d, 0x0000}, /* resume operation */
203 /* 0x12: 2X Zoom Column Start (from MT9V111 datasheet) */
204 /* 0x13: 2X Zoom Row Start (from MT9V111 datasheet) */
206 /* column 0 => bit0 of reg 0x1e must be set to activate zoom */
208 /* row 0 => bit0 of reg 0x1e must be set to activate zoom */
220 /* 0x20: Read Mode */
221 {0x20, 0x1101}, /* output all frames (including bad frames) */
246 /* 0x0a: Pixel Clock Speed */
247 {0x0a, 0x0000}, /* default */
248 /* 0x06: Vertical Blanking */
249 {0x06, 0x0029}, /* 41 rows */
250 /* 0x05: Horizontal Blanking */
251 {0x05, 0x0009}, /* 9 columns (pixel clocks) */
252 /* 0x20: Read Mode */
253 {0x20, 0x1101}, /* output all frames (including bad ones) */
254 /* 0x20: Read Mode */
255 {0x20, 0x1101}, /* output all frames (including bad ones) */
256 /* 0x09: Shutter Width */
257 {0x09, 0x0064}, /* integration of 100 rows */
258 /* 0x07: Output Control */
260 /* dont update changes until bit0=0, chip enable, normal operation */
261 /* 0x2b: Green 1 Gain */
262 /* 0x2c: Blue Gain */
263 {0x2b, 0x0033}, /* 51*0.03125*1 = 1.59375 */
264 {0x2c, 0x00a0}, /* 32*0.03125*2 = 2 */
266 /* 0x2e: Green 2 Gain */
267 {0x2d, 0x00a0}, /* 32*0.03125*2 = 2 */
268 {0x2e, 0x0033}, /* 51*0.03125*1 = 1.59375 */
269 /* 0x07: Output Control */
270 {0x07, 0x0002}, /* chip enable, normal operation */
271 /* 0x0a: Pixel Clock Speed */
272 {0x06, 0x0000}, /* default */
273 /* 0x06: Vertical Blanking */
274 {0x06, 0x0029}, /* 41 rows */
275 /* 0x05: Horizontal Blanking */
276 {0x05, 0x0009}, /* 9 columns (pixel clocks) */
280 struct sn9c20x_i2c_regs mt9m111_init
[] = {
286 /* Select Page map 0x01
287 * This means all new writes now have the address prefix 0x1.
288 * Example: 0x3a becomes 0x13a. */
290 /** Select output format:
291 * - output raw bayer (8+2 bit)
292 * FIXME: There are nearly all YUV and RGB variants possible.
293 * Maybe we should use them.
296 /* measure atoexposure through a mix of both possible windows */
298 /* Switch back to Page map 0x00 */
300 /* The following set the resoutiona and window size.
301 * It's a bit more than SXGA.
319 /* Protect settings */
329 /* Blanking (again?) */
336 struct sn9c20x_i2c_regs mt9m001_init
[] = {
337 {0x07, 0x0000}, {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
338 {0x01, 0x000e}, {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
339 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, {0x09, 0x0000},
340 {0x0a, 0x0000}, {0x0b, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
341 {0x1e, 0x8000}, {0x20, 0x1105}, {0x2b, 0x0008}, {0x2c, 0x0010},
342 {0x2d, 0x0014}, {0x2e, 0x0008}, {0x5f, 0x8904}, {0x60, 0x0000},
343 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, {0x68, 0x0000},
344 {0x20, 0x111d}, {0x06, 0x00f2}, {0x05, 0x0013}, {0x20, 0x111d},
345 {0x20, 0x111d}, {0x07, 0x0003}, {0x2b, 0x0010}, {0x2c, 0x0010},
346 {0x2d, 0x0010}, {0x2e, 0x0010}, {0x07, 0x0002}, {0x07, 0x0003},
347 {0x2c, 0x001d}, {0x2d, 0x001d}, {0x07, 0x0002}, {0x06, 0x00f2},
348 {0x05, 0x0013}, {0x09, 0x0387}, {0x07, 0x0003}, {0x2b, 0x0028},
349 {0x2c, 0x003f}, {0x2d, 0x003f}, {0x2e, 0x0028}, {0x07, 0x0002},
350 {0x09, 0x04f1}, {0x07, 0x0003}, {0x2b, 0x0024}, {0x2c, 0x0039},
351 {0x2d, 0x0039}, {0x2e, 0x0024}, {0x07, 0x0002}, {0xff, 0xffff},
354 int mt9v111_select_address_space(struct usb_sn9c20x
*dev
, __u8 address_space
)
360 /* check if selection is valid: */
361 if ((address_space
!= MT9V111_ADDRESSSPACE_IFP
) &&
362 (address_space
!= MT9V111_ADDRESSSPACE_SENSOR
)) {
363 UDIA_WARNING("invalid register address space "
364 "selection for sensor MT9V111/MI0360SOC !\n");
367 /* read address space slection register: */
370 while ((k
< 3) && (retI2C
!= 0)) {
371 retI2C
= sn9c20x_read_i2c_data(dev
, 2, 0x01, buf
);
372 if (retI2C
!= 0 && k
< 2)
377 UDIA_ERROR("MT9V111/MI0360SOC (I2C-slave 0x5c): "
378 "read of reg0x01 (address space selection) failed !\n");
381 /* check current address space: */
382 if ((buf
[0] != 0x00) || (buf
[1] != address_space
)) {
385 while ((k
< 3) && (retI2C
!= 0)) {
386 /* switch address space: */
387 buf
[0] = 0x00; buf
[1] = address_space
;
388 retI2C
= sn9c20x_write_i2c_data(dev
, 2, 0x01, buf
);
389 if (retI2C
!= 0 && k
< 2)
394 if (address_space
== MT9V111_ADDRESSSPACE_IFP
)
395 UDIA_ERROR("MT9V111/MI0360SOC "
396 "(I2C-slave 0x5c): switch to IFP "
397 "address space failed !\n");
399 UDIA_ERROR("MT9V111/MI0360SOC "
400 "(I2C-slave 0x5c): switch to sensor "
401 "core address space failed !\n");
408 int mt9v011_probe(struct usb_sn9c20x
*dev
)
413 dev
->camera
.address
= 0x5d;
414 ret
= sn9c20x_read_i2c_data16(dev
, 1, 0xff, &buf
);
415 if ((ret
== 0) && (buf
== 0x8243))
416 ret
= MT9V011_SENSOR
;
421 int mt9v111_probe(struct usb_sn9c20x
*dev
)
426 dev
->camera
.address
= 0x5c;
427 /* Select address-space: sensor */
429 ret
= sn9c20x_write_i2c_data16(dev
, 1, 0x01, &buf
);
433 ret
= sn9c20x_read_i2c_data16(dev
, 1, 0xff, &buf
);
434 if ((ret
== 0) && (buf
== 0x823a))
435 ret
= MT9V111_SENSOR
;
440 int mt9v112_probe(struct usb_sn9c20x
*dev
)
444 dev
->camera
.address
= 0x5d;
445 /* Select address-space: sensor */
447 ret
= sn9c20x_write_i2c_data16(dev
, 1, 0xf0, &buf
);
451 ret
= sn9c20x_read_i2c_data16(dev
, 1, 0x00, &buf
);
452 if ((ret
== 0) && (buf
== 0x1229))
453 return MT9V112_SENSOR
;
458 int mt9v011_set_exposure(struct usb_sn9c20x
*dev
)
463 buf
[0] = (dev
->vsettings
.exposure
>> 4);
465 ret
|= sn9c20x_write_i2c_data(dev
, 2, 0x09, buf
);
466 /* Maybe we have to disable AE/AWB/flicker avoidence (currently not
467 * used) for MT9V111 sensor, because IFP controls this register if
468 * one of them is enabled. */
472 int mt9v111_set_exposure(struct usb_sn9c20x
*dev
)
478 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_SENSOR
);
481 return -11; /* -EAGAIN */
483 buf
[0] = (dev
->vsettings
.exposure
>> 4);
485 ret
|= sn9c20x_write_i2c_data(dev
, 2, 0x09, buf
);
486 /* Maybe we have to disable AE/AWB/flicker avoidence (currently not
487 * used) for MT9V111 sensor, because IFP controls this register if
488 * one of them is enabled. */
492 int mt9v011_set_hvflip(struct usb_sn9c20x
*dev
)
497 if ((dev
->vsettings
.hflip
> 1) || (dev
->vsettings
.hflip
< 0))
499 if ((dev
->vsettings
.vflip
> 1) || (dev
->vsettings
.vflip
< 0))
502 ret
= sn9c20x_read_i2c_data(dev
, 2, 0x20, buf
);
506 if (dev
->vsettings
.hflip
) {
508 /* (MSB) set bit 15: read out from
509 * bottom to top (upside down) */
511 /* (LSB) set bit 7: readout starting 1 row later */
513 buf
[0] &= 0x7f; /* (MSB) unset bit 15: normal readout */
514 buf
[1] &= 0x7f; /* (LSB) unset bit 7: normal readout */
516 if (dev
->vsettings
.vflip
) {
518 /* (MSB) set bit 14: read out from right to left (mirrored) */
520 /* (LSB) set bit 5: readout starting 1 column later */
522 buf
[0] &= 0xbf; /* (MSB) unset bit 14: normal readout */
523 buf
[1] &= 0xdf; /* (LSB) unset bit 5: normal readout */
526 ret
= sn9c20x_write_i2c_data(dev
, 2, 0x20, buf
);
530 int mt9v111_set_hvflip(struct usb_sn9c20x
*dev
)
535 if ((dev
->vsettings
.hflip
> 1) || (dev
->vsettings
.hflip
< 0))
537 if ((dev
->vsettings
.vflip
> 1) || (dev
->vsettings
.vflip
< 0))
541 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_SENSOR
);
543 return -11; /* -EAGAIN */
545 ret
= sn9c20x_read_i2c_data(dev
, 2, 0x20, buf
);
549 if (dev
->vsettings
.hflip
) {
551 /* (MSB) set bit 15: read out from
552 * bottom to top (upside down) */
554 /* (LSB) set bit 7: readout starting 1 row later */
556 buf
[0] &= 0x7f; /* (MSB) unset bit 15: normal readout */
557 buf
[1] &= 0x7f; /* (LSB) unset bit 7: normal readout */
559 if (dev
->vsettings
.vflip
) {
561 /* (MSB) set bit 14: read out from right to left (mirrored) */
563 /* (LSB) set bit 5: readout starting 1 column later */
565 buf
[0] &= 0xbf; /* (MSB) unset bit 14: normal readout */
566 buf
[1] &= 0xdf; /* (LSB) unset bit 5: normal readout */
569 ret
= sn9c20x_write_i2c_data(dev
, 2, 0x20, buf
);
573 int mt9v111_set_autoexposure(struct usb_sn9c20x
*dev
)
578 /* Switch to IFP-register address space: */
579 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_IFP
);
581 return -11; /* -EAGAIN */
582 /* Read current value of IFP-register 0x06: */
583 ret
= sn9c20x_read_i2c_data16(dev
, 1, MT9V111_IFPREG_OPMODECTL
, buf
);
585 UDIA_ERROR("Error: setting of auto exposure failed: "
586 "error while reading from IFP-register 0x06\n");
590 /* Set new value for register 0x06: */
591 switch (dev
->vsettings
.auto_exposure
) {
592 case V4L2_EXPOSURE_AUTO
:
593 buf
[0] |= MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
595 case V4L2_EXPOSURE_MANUAL
:
596 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
598 case V4L2_EXPOSURE_SHUTTER_PRIORITY
:
599 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
601 case V4L2_EXPOSURE_APERTURE_PRIORITY
:
602 buf
[0] |= MT9V111_IFP_OPMODE_AUTOEXPOSURE
;
607 /* Write new value to IFP-register 0x06: */
608 ret
= sn9c20x_write_i2c_data16(dev
, 1, MT9V111_IFPREG_OPMODECTL
, buf
);
610 UDIA_ERROR("Error: setting of auto exposure failed: "
611 "error while writing to IFP-register 0x06\n");
617 int mt9v111_set_autowhitebalance(struct usb_sn9c20x
*dev
)
622 /* Switch to IFP-register address space: */
623 ret
= mt9v111_select_address_space(dev
, MT9V111_ADDRESSSPACE_IFP
);
625 return -11; /* -EAGAIN */
626 /* Read current value of IFP-register 0x06: */
627 ret
= sn9c20x_read_i2c_data16(dev
, 1,
628 MT9V111_IFPREG_OPMODECTL
, buf
);
630 UDIA_ERROR("Error: setting of auto whitebalance failed: "
631 "error while reading from IFP-register 0x06\n");
634 /* Set new value for register 0x06: */
635 if (dev
->vsettings
.auto_whitebalance
== 1) {
636 /* Enable automatic exposure: */
637 buf
[0] |= MT9V111_IFP_OPMODE_AUTOWHITEBALANCE
;
638 } else if (dev
->vsettings
.auto_whitebalance
== 0) {
639 /* Disable automatic exposure: */
640 buf
[0] &= ~MT9V111_IFP_OPMODE_AUTOWHITEBALANCE
;
643 /* Write new value to IFP-register 0x06:*/
644 ret
= sn9c20x_write_i2c_data16(dev
, 1,
645 MT9V111_IFPREG_OPMODECTL
, buf
);
647 UDIA_ERROR("Error: setting of auto whitebalance failed: "
648 "error while writing to IFP-register 0x06\n");