Stop sensor_init from being executed twice
[microdia.git] / mt9m111.c
blobc95c6b57ea8052b074bf571861d6accb4f6c2dbf
1 /**
2 * @file mt9m111.c
3 * @date 2008-10-28
5 * @brief Common control functions for Omnivision Image Sensors.
7 * @par Licences
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "microdia.h"
25 #include "sn9c20x.h"
27 static __u8 mt9m111_init[][3] = {
28 /* Reset sensor */
29 {0x0d, 0x00, 0x08},
30 {0x0d, 0x00, 0x09},
31 {0x0d, 0x00, 0x08},
32 /* Select Page map 0x01
33 * This means all new writes now have the address prefix 0x1.
34 * Example: 0x3a becomes 0x13a. */
35 {0xf0, 0x00, 0x01},
36 /** Select output format:
37 * - output raw bayer (8+2 bit)
38 * FIXME: There are nearly all YUV and RGB variants possible.
39 * Maybe we should use them.
41 {0x3a, 0x73, 0x00},
42 /* measure atoexposure through a mix of both possible windows */
43 {0x06, 0x30, 0x8c},
44 /* Switch back to Page map 0x00 */
45 {0xf0, 0x00, 0x00},
46 /* The following set the resoutiona and window size.
47 * It's a bit more than SXGA.
48 * VSTART */
49 {0x01, 0x00, 0x0e},
50 /* HSTART */
51 {0x02, 0x00, 0x14},
52 /* VSIZE */
53 {0x03, 0x03, 0xc4},
54 /* HSIZE */
55 {0x04, 0x05, 0x14},
56 /* Blanking */
57 {0xc8, 0x00, 0x03},
58 {0x0a, 0x00, 0x01},
59 {0x06, 0x00, 0x29},
60 {0x05, 0x00, 0x72},
61 {0x20, 0x00, 0x00},
62 {0x20, 0x00, 0x00},
63 /* Shutter width */
64 {0x09, 0x01, 0x90},
65 /* Protect settings */
66 {0x0d, 0x80, 0x08},
67 /* Green 1 gain */
68 {0x2b, 0x01, 0x88},
69 /* Blue gain */
70 {0x2c, 0x01, 0x88},
71 /* Red gain */
72 {0x2d, 0x01, 0x88},
73 /* Green 2 gain */
74 {0x2e, 0x01, 0x88},
75 /* Blanking (again?) */
76 {0x0a, 0x00, 0x01},
77 {0x06, 0x00, 0x29},
78 {0x05, 0x00, 0x72},
81 static __u8 mt9m001_init[][3] = {
82 {0x07, 0x00, 0x00},
83 {0x07, 0x00, 0x02},
84 {0x0d, 0x00, 0x01},
85 {0x0d, 0x00, 0x00},
86 {0x01, 0x00, 0x0e},
87 {0x02, 0x00, 0x14},
88 {0x03, 0x03, 0xc1},
89 {0x04, 0x05, 0x01},
90 {0x05, 0x00, 0x83},
91 {0x06, 0x00, 0x06},
92 {0x0d, 0x00, 0x02},
93 {0x09, 0x00, 0x00},
94 {0x0a, 0x00, 0x00},
95 {0x0b, 0x00, 0x00},
96 {0x0c, 0x00, 0x00},
97 {0x11, 0x00, 0x00},
98 {0x1e, 0x80, 0x00},
99 {0x20, 0x11, 0x05},
100 {0x2b, 0x00, 0x08},
101 {0x2c, 0x00, 0x10},
102 {0x2d, 0x00, 0x14},
103 {0x2e, 0x00, 0x08},
104 {0x5f, 0x89, 0x04},
105 {0x60, 0x00, 0x00},
106 {0x61, 0x00, 0x00},
107 {0x62, 0x04, 0x98},
108 {0x63, 0x00, 0x00},
109 {0x68, 0x00, 0x00},
110 {0x20, 0x11, 0x1d},
111 {0x06, 0x00, 0xf2},
112 {0x05, 0x00, 0x13},
113 {0x20, 0x11, 0x1d},
114 {0x20, 0x11, 0x1d},
115 {0x07, 0x00, 0x03},
116 {0x2b, 0x00, 0x10},
117 {0x2c, 0x00, 0x10},
118 {0x2d, 0x00, 0x10},
119 {0x2e, 0x00, 0x10},
120 {0x07, 0x00, 0x02},
121 {0x07, 0x00, 0x03},
122 {0x2c, 0x00, 0x1d},
123 {0x2d, 0x00, 0x1d},
124 {0x07, 0x00, 0x02},
125 {0x06, 0x00, 0xf2},
126 {0x05, 0x00, 0x13},
127 {0x09, 0x03, 0x87},
128 {0x07, 0x00, 0x03},
129 {0x2b, 0x00, 0x28},
130 {0x2c, 0x00, 0x3f},
131 {0x2d, 0x00, 0x3f},
132 {0x2e, 0x00, 0x28},
133 {0x07, 0x00, 0x02},
134 {0x09, 0x04, 0xf1},
135 {0x07, 0x00, 0x03},
136 {0x2b, 0x00, 0x24},
137 {0x2c, 0x00, 0x39},
138 {0x2d, 0x00, 0x39},
139 {0x2e, 0x00, 0x24},
140 {0x07, 0x00, 0x02},
143 struct microdia_video_format mt9m111_fmts[] = {
145 .pix_fmt = V4L2_PIX_FMT_SBGGR8,
146 .desc = "Bayer 8bit (BGGR)",
147 .depth = 8,
148 .set_format = sn9c20x_set_raw
151 .pix_fmt = V4L2_PIX_FMT_JPEG,
152 .desc = "JPEG (YUV 4:2:2)",
153 .depth = 16,
154 .set_format = sn9c20x_set_jpeg
158 struct microdia_video_resolution mt9m001_resolutions[] = {
160 .width = 160,
161 .height = 120,
162 .scale = SN9C20X_1_4_SCALE,
163 .window = {2, 2, 640, 480}
166 .width = 320,
167 .height = 240,
168 .scale = SN9C20X_1_2_SCALE,
169 .window = {2, 2, 640, 480}
172 .width = 640,
173 .height = 480,
174 .scale = SN9C20X_NO_SCALE,
175 .window = {2, 2, 640, 480}
180 * @brief Initialize mt9m111 sensors
182 * @param dev Pointer to device structure
184 * @return 0 or negative error code
187 int mt9m001_initialize(struct usb_microdia *dev)
189 int i;
190 int ret = 0;
191 __u8 value[2], reg;
193 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
194 reg = mt9m001_init[i][0];
195 value[0] = mt9m001_init[i][1];
196 value[1] = mt9m001_init[i][2];
197 ret = sn9c20x_write_i2c_data(dev, 2, reg, value);
198 if (ret < 0) {
199 UDIA_INFO("Sensor Init Error (%d). line %d\n", ret, i);
200 break;
204 return ret;
207 int mt9m001_probe(struct usb_microdia *dev)
209 int ret;
210 __u8 buf[2];
211 dev->camera.sensor_slave_address = 0x5d;
212 ret = sn9c20x_read_i2c_data(dev, 2, 0x00, buf);
213 if (ret == 0) {
214 if (buf[0] != 0x84)
215 return -EINVAL;
216 if (buf[1] == 0x31) {
217 mt9m001_initialize(dev);
218 dev->camera.modes = mt9m001_resolutions;
219 dev->camera.nmodes = ARRAY_SIZE(mt9m001_resolutions);
220 dev->camera.fmts = mt9m111_fmts;
221 dev->camera.nfmts = ARRAY_SIZE(mt9m111_fmts);
222 return MT9M001_SENSOR;
226 return -EINVAL;
229 struct microdia_video_resolution mt9m111_resolutions[] = {
231 .width = 160,
232 .height = 120,
233 .scale = SN9C20X_1_4_SCALE,
234 .window = {6, 2, 640, 480}
237 .width = 320,
238 .height = 240,
239 .scale = SN9C20X_1_2_SCALE,
240 .window = {6, 2, 640, 480}
243 .width = 640,
244 .height = 480,
245 .scale = SN9C20X_NO_SCALE,
246 .window = {6, 2, 640, 480}
251 * @brief Initialize mt9m111 sensors
253 * @param dev Pointer to device structure
255 * @return 0 or negative error code
258 int mt9m111_initialize(struct usb_microdia *dev)
260 int i;
261 int ret = 0;
262 __u8 value[2], reg;
264 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
265 reg = mt9m111_init[i][0];
266 value[0] = mt9m111_init[i][1];
267 value[1] = mt9m111_init[i][2];
268 ret = sn9c20x_write_i2c_data(dev, 2, reg, value);
269 if (ret < 0) {
270 UDIA_INFO("Sensor Init Error (%d). line %d\n", ret, i);
271 break;
275 return ret;
278 int mt9m111_probe(struct usb_microdia *dev)
280 int ret;
281 __u8 buf[2];
282 dev->camera.sensor_slave_address = 0x5d;
283 ret = sn9c20x_read_i2c_data(dev, 2, 0x00, buf);
284 if (ret == 0) {
285 if (buf[0] != 0x14)
286 return -EINVAL;
287 if (buf[1] == 0x3a) {
288 mt9m111_initialize(dev);
289 dev->camera.modes = mt9m111_resolutions;
290 dev->camera.nmodes = ARRAY_SIZE(mt9m111_resolutions);
291 dev->camera.fmts = mt9m111_fmts;
292 dev->camera.nfmts = ARRAY_SIZE(mt9m111_fmts);
293 return MT9M111_SENSOR;
297 return -EINVAL;