|
@@ -26,6 +26,15 @@
|
|
|
#include "em28xx.h"
|
|
|
|
|
|
|
|
|
+/* Possible i2c addresses of Micron sensors */
|
|
|
+static unsigned short micron_sensor_addrs[] = {
|
|
|
+ 0xb8 >> 1, /* MT9V111, MT9V403 */
|
|
|
+ 0xba >> 1, /* MT9M001/011/111/112, MT9V011/012/112, MT9D011 */
|
|
|
+ 0x90 >> 1, /* MT9V012/112, MT9D011 (alternative address) */
|
|
|
+ I2C_CLIENT_END
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
/* FIXME: Should be replaced by a proper mt9m111 driver */
|
|
|
static int em28xx_initialize_mt9m111(struct em28xx *dev)
|
|
|
{
|
|
@@ -78,44 +87,99 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev)
|
|
|
*/
|
|
|
int em28xx_detect_sensor(struct em28xx *dev)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ int ret, i;
|
|
|
char *name;
|
|
|
u8 reg;
|
|
|
__be16 id_be;
|
|
|
u16 id;
|
|
|
|
|
|
- /* Micron sensor detection */
|
|
|
- dev->i2c_client[dev->def_i2c_bus].addr = 0xba >> 1;
|
|
|
- reg = 0;
|
|
|
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®, 1);
|
|
|
- ret = i2c_master_recv(&dev->i2c_client[dev->def_i2c_bus],
|
|
|
- (char *)&id_be, 2);
|
|
|
- if (ret != 2)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- id = be16_to_cpu(id_be);
|
|
|
- switch (id) {
|
|
|
- case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */
|
|
|
- case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */
|
|
|
- name = "mt9v011";
|
|
|
- dev->em28xx_sensor = EM28XX_MT9V011;
|
|
|
- break;
|
|
|
- case 0x143a: /* MT9M111 as found in the ECS G200 */
|
|
|
- name = "mt9m111";
|
|
|
- dev->em28xx_sensor = EM28XX_MT9M111;
|
|
|
- break;
|
|
|
- case 0x8431:
|
|
|
- name = "mt9m001";
|
|
|
- dev->em28xx_sensor = EM28XX_MT9M001;
|
|
|
- break;
|
|
|
- default:
|
|
|
- em28xx_info("unknown Micron sensor detected: 0x%04x\n", id);
|
|
|
- return -EINVAL;
|
|
|
+ struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
|
|
|
+
|
|
|
+ dev->em28xx_sensor = EM28XX_NOSENSOR;
|
|
|
+ /* Probe Micron sensors with 8 bit address and 16 bit register width */
|
|
|
+ for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
|
|
|
+ client.addr = micron_sensor_addrs[i];
|
|
|
+ /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
|
|
|
+ /* Read chip ID from register 0x00 */
|
|
|
+ reg = 0x00;
|
|
|
+ ret = i2c_master_send(&client, ®, 1);
|
|
|
+ if (ret < 0) {
|
|
|
+ if (ret != -ENODEV)
|
|
|
+ em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
|
|
|
+ client.addr << 1, ret);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
|
|
|
+ if (ret < 0) {
|
|
|
+ em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
|
|
|
+ client.addr << 1, ret);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ id = be16_to_cpu(id_be);
|
|
|
+ /* Read chip ID from register 0xff */
|
|
|
+ reg = 0xff;
|
|
|
+ ret = i2c_master_send(&client, ®, 1);
|
|
|
+ if (ret < 0) {
|
|
|
+ em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
|
|
|
+ client.addr << 1, ret);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
|
|
|
+ if (ret < 0) {
|
|
|
+ em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
|
|
|
+ client.addr << 1, ret);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* Validate chip ID to be sure we have a Micron device */
|
|
|
+ if (id != be16_to_cpu(id_be))
|
|
|
+ continue;
|
|
|
+ /* Check chip ID */
|
|
|
+ id = be16_to_cpu(id_be);
|
|
|
+ switch (id) {
|
|
|
+ case 0x1222:
|
|
|
+ name = "MT9V012"; /* MI370 */ /* 640x480 */
|
|
|
+ break;
|
|
|
+ case 0x1229:
|
|
|
+ name = "MT9V112"; /* 640x480 */
|
|
|
+ break;
|
|
|
+ case 0x1433:
|
|
|
+ name = "MT9M011"; /* 1280x1024 */
|
|
|
+ break;
|
|
|
+ case 0x143a: /* found in the ECS G200 */
|
|
|
+ name = "MT9M111"; /* MI1310 */ /* 1280x1024 */
|
|
|
+ dev->em28xx_sensor = EM28XX_MT9M111;
|
|
|
+ break;
|
|
|
+ case 0x148c:
|
|
|
+ name = "MT9M112"; /* MI1320 */ /* 1280x1024 */
|
|
|
+ break;
|
|
|
+ case 0x1511:
|
|
|
+ name = "MT9D011"; /* MI2010 */ /* 1600x1200 */
|
|
|
+ break;
|
|
|
+ case 0x8232:
|
|
|
+ case 0x8243: /* rev B */
|
|
|
+ name = "MT9V011"; /* MI360 */ /* 640x480 */
|
|
|
+ dev->em28xx_sensor = EM28XX_MT9V011;
|
|
|
+ break;
|
|
|
+ case 0x8431:
|
|
|
+ name = "MT9M001"; /* 1280x1024 */
|
|
|
+ dev->em28xx_sensor = EM28XX_MT9M001;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ em28xx_info("unknown Micron sensor detected: 0x%04x\n",
|
|
|
+ id);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dev->em28xx_sensor == EM28XX_NOSENSOR)
|
|
|
+ em28xx_info("unsupported sensor detected: %s\n", name);
|
|
|
+ else
|
|
|
+ em28xx_info("sensor %s detected\n", name);
|
|
|
+
|
|
|
+ dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- em28xx_info("sensor %s detected\n", name);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
int em28xx_init_camera(struct em28xx *dev)
|