]>
Commit | Line | Data |
---|---|---|
855ff38e FS |
1 | /* |
2 | em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices | |
3 | ||
4 | Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org> | |
5 | Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com> | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | ||
8314d402 MCC |
22 | #include "em28xx.h" |
23 | ||
855ff38e | 24 | #include <linux/i2c.h> |
ce8591ff | 25 | #include <linux/usb.h> |
b5dcee22 | 26 | #include <media/i2c/mt9v011.h> |
855ff38e FS |
27 | #include <media/v4l2-common.h> |
28 | ||
176013b1 FS |
29 | /* Possible i2c addresses of Micron sensors */ |
30 | static unsigned short micron_sensor_addrs[] = { | |
31 | 0xb8 >> 1, /* MT9V111, MT9V403 */ | |
32 | 0xba >> 1, /* MT9M001/011/111/112, MT9V011/012/112, MT9D011 */ | |
33 | 0x90 >> 1, /* MT9V012/112, MT9D011 (alternative address) */ | |
34 | I2C_CLIENT_END | |
35 | }; | |
36 | ||
bde03684 FS |
37 | /* Possible i2c addresses of Omnivision sensors */ |
38 | static unsigned short omnivision_sensor_addrs[] = { | |
39 | 0x42 >> 1, /* OV7725, OV7670/60/48 */ | |
40 | 0x60 >> 1, /* OV2640, OV9650/53/55 */ | |
41 | I2C_CLIENT_END | |
42 | }; | |
43 | ||
855ff38e FS |
44 | /* FIXME: Should be replaced by a proper mt9m111 driver */ |
45 | static int em28xx_initialize_mt9m111(struct em28xx *dev) | |
46 | { | |
47 | int i; | |
48 | unsigned char regs[][3] = { | |
49 | { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ | |
50 | { 0x0d, 0x00, 0x00, }, | |
51 | { 0x0a, 0x00, 0x21, }, | |
52 | { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ | |
53 | }; | |
54 | ||
55 | for (i = 0; i < ARRAY_SIZE(regs); i++) | |
56 | i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], | |
57 | ®s[i][0], 3); | |
58 | ||
37ecc7b1 MCC |
59 | /* FIXME: This won't be creating a sensor at the media graph */ |
60 | ||
855ff38e FS |
61 | return 0; |
62 | } | |
63 | ||
855ff38e FS |
64 | /* FIXME: Should be replaced by a proper mt9m001 driver */ |
65 | static int em28xx_initialize_mt9m001(struct em28xx *dev) | |
66 | { | |
67 | int i; | |
68 | unsigned char regs[][3] = { | |
69 | { 0x0d, 0x00, 0x01, }, | |
70 | { 0x0d, 0x00, 0x00, }, | |
71 | { 0x04, 0x05, 0x00, }, /* hres = 1280 */ | |
72 | { 0x03, 0x04, 0x00, }, /* vres = 1024 */ | |
73 | { 0x20, 0x11, 0x00, }, | |
74 | { 0x06, 0x00, 0x10, }, | |
75 | { 0x2b, 0x00, 0x24, }, | |
76 | { 0x2e, 0x00, 0x24, }, | |
77 | { 0x35, 0x00, 0x24, }, | |
78 | { 0x2d, 0x00, 0x20, }, | |
79 | { 0x2c, 0x00, 0x20, }, | |
80 | { 0x09, 0x0a, 0xd4, }, | |
81 | { 0x35, 0x00, 0x57, }, | |
82 | }; | |
83 | ||
84 | for (i = 0; i < ARRAY_SIZE(regs); i++) | |
85 | i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], | |
86 | ®s[i][0], 3); | |
87 | ||
37ecc7b1 MCC |
88 | /* FIXME: This won't be creating a sensor at the media graph */ |
89 | ||
855ff38e FS |
90 | return 0; |
91 | } | |
92 | ||
855ff38e | 93 | /* |
0af0b25a | 94 | * Probes Micron sensors with 8 bit address and 16 bit register width |
855ff38e | 95 | */ |
0af0b25a | 96 | static int em28xx_probe_sensor_micron(struct em28xx *dev) |
855ff38e | 97 | { |
176013b1 | 98 | int ret, i; |
855ff38e | 99 | char *name; |
855ff38e FS |
100 | u16 id; |
101 | ||
9e006953 | 102 | struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; |
176013b1 FS |
103 | |
104 | dev->em28xx_sensor = EM28XX_NOSENSOR; | |
176013b1 | 105 | for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { |
9e006953 | 106 | client->addr = micron_sensor_addrs[i]; |
176013b1 | 107 | /* Read chip ID from register 0x00 */ |
4d584436 | 108 | ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ |
176013b1 | 109 | if (ret < 0) { |
cb497c75 | 110 | if (ret != -ENXIO) |
29b05e22 | 111 | dev_err(&dev->intf->dev, |
ce8591ff | 112 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 113 | client->addr << 1, ret); |
176013b1 FS |
114 | continue; |
115 | } | |
4d584436 | 116 | id = swab16(ret); /* LE -> BE */ |
176013b1 | 117 | /* Read chip ID from register 0xff */ |
4d584436 | 118 | ret = i2c_smbus_read_word_data(client, 0xff); |
176013b1 | 119 | if (ret < 0) { |
29b05e22 | 120 | dev_err(&dev->intf->dev, |
ce8591ff | 121 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 122 | client->addr << 1, ret); |
176013b1 FS |
123 | continue; |
124 | } | |
125 | /* Validate chip ID to be sure we have a Micron device */ | |
4d584436 | 126 | if (id != swab16(ret)) |
176013b1 FS |
127 | continue; |
128 | /* Check chip ID */ | |
176013b1 FS |
129 | switch (id) { |
130 | case 0x1222: | |
131 | name = "MT9V012"; /* MI370 */ /* 640x480 */ | |
132 | break; | |
133 | case 0x1229: | |
134 | name = "MT9V112"; /* 640x480 */ | |
135 | break; | |
136 | case 0x1433: | |
137 | name = "MT9M011"; /* 1280x1024 */ | |
138 | break; | |
139 | case 0x143a: /* found in the ECS G200 */ | |
140 | name = "MT9M111"; /* MI1310 */ /* 1280x1024 */ | |
141 | dev->em28xx_sensor = EM28XX_MT9M111; | |
142 | break; | |
143 | case 0x148c: | |
144 | name = "MT9M112"; /* MI1320 */ /* 1280x1024 */ | |
145 | break; | |
146 | case 0x1511: | |
147 | name = "MT9D011"; /* MI2010 */ /* 1600x1200 */ | |
148 | break; | |
149 | case 0x8232: | |
150 | case 0x8243: /* rev B */ | |
151 | name = "MT9V011"; /* MI360 */ /* 640x480 */ | |
152 | dev->em28xx_sensor = EM28XX_MT9V011; | |
153 | break; | |
154 | case 0x8431: | |
155 | name = "MT9M001"; /* 1280x1024 */ | |
156 | dev->em28xx_sensor = EM28XX_MT9M001; | |
157 | break; | |
158 | default: | |
29b05e22 | 159 | dev_info(&dev->intf->dev, |
ce8591ff | 160 | "unknown Micron sensor detected: 0x%04x\n", id); |
0af0b25a | 161 | return 0; |
176013b1 FS |
162 | } |
163 | ||
164 | if (dev->em28xx_sensor == EM28XX_NOSENSOR) | |
29b05e22 | 165 | dev_info(&dev->intf->dev, |
ce8591ff | 166 | "unsupported sensor detected: %s\n", name); |
176013b1 | 167 | else |
29b05e22 | 168 | dev_info(&dev->intf->dev, |
ce8591ff | 169 | "sensor %s detected\n", name); |
176013b1 | 170 | |
176013b1 | 171 | return 0; |
855ff38e FS |
172 | } |
173 | ||
176013b1 | 174 | return -ENODEV; |
855ff38e FS |
175 | } |
176 | ||
0af0b25a | 177 | /* |
bde03684 | 178 | * Probes Omnivision sensors with 8 bit address and register width |
0af0b25a | 179 | */ |
bde03684 FS |
180 | static int em28xx_probe_sensor_omnivision(struct em28xx *dev) |
181 | { | |
182 | int ret, i; | |
183 | char *name; | |
184 | u8 reg; | |
185 | u16 id; | |
9e006953 | 186 | struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; |
bde03684 FS |
187 | |
188 | dev->em28xx_sensor = EM28XX_NOSENSOR; | |
189 | /* NOTE: these devices have the register auto incrementation disabled | |
190 | * by default, so we have to use single byte reads ! */ | |
191 | for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) { | |
9e006953 | 192 | client->addr = omnivision_sensor_addrs[i]; |
bde03684 FS |
193 | /* Read manufacturer ID from registers 0x1c-0x1d (BE) */ |
194 | reg = 0x1c; | |
9e006953 | 195 | ret = i2c_smbus_read_byte_data(client, reg); |
bde03684 | 196 | if (ret < 0) { |
cb497c75 | 197 | if (ret != -ENXIO) |
29b05e22 | 198 | dev_err(&dev->intf->dev, |
ce8591ff | 199 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 200 | client->addr << 1, ret); |
bde03684 FS |
201 | continue; |
202 | } | |
203 | id = ret << 8; | |
204 | reg = 0x1d; | |
9e006953 | 205 | ret = i2c_smbus_read_byte_data(client, reg); |
bde03684 | 206 | if (ret < 0) { |
29b05e22 | 207 | dev_err(&dev->intf->dev, |
ce8591ff | 208 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 209 | client->addr << 1, ret); |
bde03684 FS |
210 | continue; |
211 | } | |
212 | id += ret; | |
213 | /* Check manufacturer ID */ | |
214 | if (id != 0x7fa2) | |
215 | continue; | |
216 | /* Read product ID from registers 0x0a-0x0b (BE) */ | |
217 | reg = 0x0a; | |
9e006953 | 218 | ret = i2c_smbus_read_byte_data(client, reg); |
bde03684 | 219 | if (ret < 0) { |
29b05e22 | 220 | dev_err(&dev->intf->dev, |
ce8591ff | 221 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 222 | client->addr << 1, ret); |
bde03684 FS |
223 | continue; |
224 | } | |
225 | id = ret << 8; | |
226 | reg = 0x0b; | |
9e006953 | 227 | ret = i2c_smbus_read_byte_data(client, reg); |
bde03684 | 228 | if (ret < 0) { |
29b05e22 | 229 | dev_err(&dev->intf->dev, |
ce8591ff | 230 | "couldn't read from i2c device 0x%02x: error %i\n", |
9e006953 | 231 | client->addr << 1, ret); |
bde03684 FS |
232 | continue; |
233 | } | |
234 | id += ret; | |
235 | /* Check product ID */ | |
236 | switch (id) { | |
237 | case 0x2642: | |
238 | name = "OV2640"; | |
e4b7131d | 239 | dev->em28xx_sensor = EM28XX_OV2640; |
bde03684 FS |
240 | break; |
241 | case 0x7648: | |
242 | name = "OV7648"; | |
243 | break; | |
244 | case 0x7660: | |
245 | name = "OV7660"; | |
246 | break; | |
247 | case 0x7673: | |
248 | name = "OV7670"; | |
249 | break; | |
250 | case 0x7720: | |
251 | name = "OV7720"; | |
252 | break; | |
253 | case 0x7721: | |
254 | name = "OV7725"; | |
255 | break; | |
256 | case 0x9648: /* Rev 2 */ | |
257 | case 0x9649: /* Rev 3 */ | |
258 | name = "OV9640"; | |
259 | break; | |
260 | case 0x9650: | |
261 | case 0x9652: /* OV9653 */ | |
262 | name = "OV9650"; | |
263 | break; | |
264 | case 0x9656: /* Rev 4 */ | |
265 | case 0x9657: /* Rev 5 */ | |
266 | name = "OV9655"; | |
267 | break; | |
268 | default: | |
29b05e22 | 269 | dev_info(&dev->intf->dev, |
ce8591ff | 270 | "unknown OmniVision sensor detected: 0x%04x\n", |
2a96f60e | 271 | id); |
bde03684 FS |
272 | return 0; |
273 | } | |
274 | ||
275 | if (dev->em28xx_sensor == EM28XX_NOSENSOR) | |
29b05e22 | 276 | dev_info(&dev->intf->dev, |
ce8591ff | 277 | "unsupported sensor detected: %s\n", name); |
bde03684 | 278 | else |
29b05e22 | 279 | dev_info(&dev->intf->dev, |
ce8591ff | 280 | "sensor %s detected\n", name); |
bde03684 | 281 | |
bde03684 FS |
282 | return 0; |
283 | } | |
284 | ||
285 | return -ENODEV; | |
286 | } | |
287 | ||
0af0b25a FS |
288 | int em28xx_detect_sensor(struct em28xx *dev) |
289 | { | |
290 | int ret; | |
291 | ||
292 | ret = em28xx_probe_sensor_micron(dev); | |
bde03684 FS |
293 | |
294 | if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) | |
295 | ret = em28xx_probe_sensor_omnivision(dev); | |
296 | ||
52f1f230 FS |
297 | /* |
298 | * NOTE: the Windows driver also probes i2c addresses | |
299 | * 0x22 (Samsung ?) and 0x66 (Kodak ?) | |
300 | */ | |
301 | ||
0af0b25a | 302 | if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) { |
29b05e22 | 303 | dev_info(&dev->intf->dev, |
ce8591ff | 304 | "No sensor detected\n"); |
0af0b25a FS |
305 | return -ENODEV; |
306 | } | |
307 | ||
308 | return 0; | |
309 | } | |
310 | ||
855ff38e FS |
311 | int em28xx_init_camera(struct em28xx *dev) |
312 | { | |
fc5d0f8a GL |
313 | struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; |
314 | struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus]; | |
2c52a2fc | 315 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
fc5d0f8a | 316 | |
855ff38e FS |
317 | switch (dev->em28xx_sensor) { |
318 | case EM28XX_MT9V011: | |
319 | { | |
320 | struct mt9v011_platform_data pdata; | |
321 | struct i2c_board_info mt9v011_info = { | |
322 | .type = "mt9v011", | |
fc5d0f8a | 323 | .addr = client->addr, |
855ff38e FS |
324 | .platform_data = &pdata, |
325 | }; | |
326 | ||
d7dc18da FS |
327 | v4l2->sensor_xres = 640; |
328 | v4l2->sensor_yres = 480; | |
855ff38e FS |
329 | |
330 | /* | |
331 | * FIXME: mt9v011 uses I2S speed as xtal clk - at least with | |
332 | * the Silvercrest cam I have here for testing - for higher | |
333 | * resolutions, a high clock cause horizontal artifacts, so we | |
334 | * need to use a lower xclk frequency. | |
335 | * Yet, it would be possible to adjust xclk depending on the | |
336 | * desired resolution, since this affects directly the | |
337 | * frame rate. | |
338 | */ | |
339 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; | |
340 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); | |
d7dc18da FS |
341 | v4l2->sensor_xtal = 4300000; |
342 | pdata.xtal = v4l2->sensor_xtal; | |
855ff38e | 343 | if (NULL == |
5015389f | 344 | v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, |
2437aeb4 FS |
345 | &mt9v011_info, NULL)) |
346 | return -ENODEV; | |
855ff38e | 347 | /* probably means GRGB 16 bit bayer */ |
9297285e FS |
348 | v4l2->vinmode = 0x0d; |
349 | v4l2->vinctl = 0x00; | |
855ff38e FS |
350 | |
351 | break; | |
352 | } | |
353 | case EM28XX_MT9M001: | |
d7dc18da FS |
354 | v4l2->sensor_xres = 1280; |
355 | v4l2->sensor_yres = 1024; | |
855ff38e FS |
356 | |
357 | em28xx_initialize_mt9m001(dev); | |
358 | ||
359 | /* probably means BGGR 16 bit bayer */ | |
9297285e FS |
360 | v4l2->vinmode = 0x0c; |
361 | v4l2->vinctl = 0x00; | |
855ff38e FS |
362 | |
363 | break; | |
364 | case EM28XX_MT9M111: | |
d7dc18da FS |
365 | v4l2->sensor_xres = 640; |
366 | v4l2->sensor_yres = 512; | |
855ff38e FS |
367 | |
368 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; | |
369 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); | |
370 | em28xx_initialize_mt9m111(dev); | |
371 | ||
9297285e FS |
372 | v4l2->vinmode = 0x0a; |
373 | v4l2->vinctl = 0x00; | |
855ff38e FS |
374 | |
375 | break; | |
e4b7131d FS |
376 | case EM28XX_OV2640: |
377 | { | |
378 | struct v4l2_subdev *subdev; | |
379 | struct i2c_board_info ov2640_info = { | |
380 | .type = "ov2640", | |
381 | .flags = I2C_CLIENT_SCCB, | |
fc5d0f8a | 382 | .addr = client->addr, |
e4b7131d | 383 | }; |
ebf984bb HV |
384 | struct v4l2_subdev_format format = { |
385 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
386 | }; | |
e4b7131d FS |
387 | |
388 | /* | |
389 | * FIXME: sensor supports resolutions up to 1600x1200, but | |
390 | * resolution setting/switching needs to be modified to | |
391 | * - switch sensor output resolution (including further | |
392 | * configuration changes) | |
393 | * - adjust bridge xclk | |
394 | * - disable 16 bit (12 bit) output formats on high resolutions | |
395 | */ | |
d7dc18da FS |
396 | v4l2->sensor_xres = 640; |
397 | v4l2->sensor_yres = 480; | |
e4b7131d FS |
398 | |
399 | subdev = | |
5015389f | 400 | v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, |
e4b7131d | 401 | &ov2640_info, NULL); |
2437aeb4 FS |
402 | if (subdev == NULL) |
403 | return -ENODEV; | |
e4b7131d | 404 | |
ebf984bb HV |
405 | format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; |
406 | format.format.width = 640; | |
407 | format.format.height = 480; | |
408 | v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format); | |
e4b7131d FS |
409 | |
410 | /* NOTE: for UXGA=1600x1200 switch to 12MHz */ | |
411 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ; | |
412 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); | |
9297285e FS |
413 | v4l2->vinmode = 0x08; |
414 | v4l2->vinctl = 0x00; | |
e4b7131d FS |
415 | |
416 | break; | |
417 | } | |
855ff38e FS |
418 | case EM28XX_NOSENSOR: |
419 | default: | |
2437aeb4 | 420 | return -EINVAL; |
fc5d0f8a GL |
421 | } |
422 | ||
2437aeb4 | 423 | return 0; |
855ff38e | 424 | } |
01c28193 | 425 | EXPORT_SYMBOL_GPL(em28xx_init_camera); |