Commit 176013b1 authored by Frank Schaefer's avatar Frank Schaefer Committed by Mauro Carvalho Chehab

[media] em28xx: detect further Micron sensors

Add further Micron chip IDs to be able to identify all Micron sensors listed
by Empiatech.
Also probe the two alternate i2c addresses used by Micron sensors with 8 bit
address and 16 bit register width.
Signed-off-by: default avatarFrank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 855ff38e
...@@ -26,6 +26,15 @@ ...@@ -26,6 +26,15 @@
#include "em28xx.h" #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 */ /* FIXME: Should be replaced by a proper mt9m111 driver */
static int em28xx_initialize_mt9m111(struct em28xx *dev) static int em28xx_initialize_mt9m111(struct em28xx *dev)
{ {
...@@ -78,44 +87,99 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) ...@@ -78,44 +87,99 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev)
*/ */
int em28xx_detect_sensor(struct em28xx *dev) int em28xx_detect_sensor(struct em28xx *dev)
{ {
int ret; int ret, i;
char *name; char *name;
u8 reg; u8 reg;
__be16 id_be; __be16 id_be;
u16 id; u16 id;
/* Micron sensor detection */ struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
dev->i2c_client[dev->def_i2c_bus].addr = 0xba >> 1;
reg = 0; dev->em28xx_sensor = EM28XX_NOSENSOR;
i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], &reg, 1); /* Probe Micron sensors with 8 bit address and 16 bit register width */
ret = i2c_master_recv(&dev->i2c_client[dev->def_i2c_bus], for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
(char *)&id_be, 2); client.addr = micron_sensor_addrs[i];
if (ret != 2) /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
return -EINVAL; /* Read chip ID from register 0x00 */
reg = 0x00;
ret = i2c_master_send(&client, &reg, 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, &reg, 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); id = be16_to_cpu(id_be);
switch (id) { switch (id) {
case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ case 0x1222:
case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ name = "MT9V012"; /* MI370 */ /* 640x480 */
name = "mt9v011";
dev->em28xx_sensor = EM28XX_MT9V011;
break; break;
case 0x143a: /* MT9M111 as found in the ECS G200 */ case 0x1229:
name = "mt9m111"; 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; dev->em28xx_sensor = EM28XX_MT9M111;
break; 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: case 0x8431:
name = "mt9m001"; name = "MT9M001"; /* 1280x1024 */
dev->em28xx_sensor = EM28XX_MT9M001; dev->em28xx_sensor = EM28XX_MT9M001;
break; break;
default: default:
em28xx_info("unknown Micron sensor detected: 0x%04x\n", id); em28xx_info("unknown Micron sensor detected: 0x%04x\n",
id);
return -EINVAL; return -EINVAL;
} }
if (dev->em28xx_sensor == EM28XX_NOSENSOR)
em28xx_info("unsupported sensor detected: %s\n", name);
else
em28xx_info("sensor %s detected\n", name); em28xx_info("sensor %s detected\n", name);
dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
return 0; return 0;
}
return -ENODEV;
} }
int em28xx_init_camera(struct em28xx *dev) int em28xx_init_camera(struct em28xx *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment