aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-03-27 16:06:32 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-29 05:38:08 -0400
commit176013b19e848204895bfcaea8b9b39fba5b26dd (patch)
tree4b993a31f4f0378e9420c86562c6050bb9bdb8ae
parent855ff38e880f57814ea5c0cbea853da11fcdf42f (diff)
[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: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c126
1 files changed, 95 insertions, 31 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 28dd8489ac9c..2e4856aebae8 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -26,6 +26,15 @@
26#include "em28xx.h" 26#include "em28xx.h"
27 27
28 28
29/* Possible i2c addresses of Micron sensors */
30static 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
37
29/* FIXME: Should be replaced by a proper mt9m111 driver */ 38/* FIXME: Should be replaced by a proper mt9m111 driver */
30static int em28xx_initialize_mt9m111(struct em28xx *dev) 39static int em28xx_initialize_mt9m111(struct em28xx *dev)
31{ 40{
@@ -78,44 +87,99 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev)
78 */ 87 */
79int em28xx_detect_sensor(struct em28xx *dev) 88int em28xx_detect_sensor(struct em28xx *dev)
80{ 89{
81 int ret; 90 int ret, i;
82 char *name; 91 char *name;
83 u8 reg; 92 u8 reg;
84 __be16 id_be; 93 __be16 id_be;
85 u16 id; 94 u16 id;
86 95
87 /* Micron sensor detection */ 96 struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
88 dev->i2c_client[dev->def_i2c_bus].addr = 0xba >> 1; 97
89 reg = 0; 98 dev->em28xx_sensor = EM28XX_NOSENSOR;
90 i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], &reg, 1); 99 /* Probe Micron sensors with 8 bit address and 16 bit register width */
91 ret = i2c_master_recv(&dev->i2c_client[dev->def_i2c_bus], 100 for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
92 (char *)&id_be, 2); 101 client.addr = micron_sensor_addrs[i];
93 if (ret != 2) 102 /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
94 return -EINVAL; 103 /* Read chip ID from register 0x00 */
95 104 reg = 0x00;
96 id = be16_to_cpu(id_be); 105 ret = i2c_master_send(&client, &reg, 1);
97 switch (id) { 106 if (ret < 0) {
98 case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ 107 if (ret != -ENODEV)
99 case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ 108 em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
100 name = "mt9v011"; 109 client.addr << 1, ret);
101 dev->em28xx_sensor = EM28XX_MT9V011; 110 continue;
102 break; 111 }
103 case 0x143a: /* MT9M111 as found in the ECS G200 */ 112 ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
104 name = "mt9m111"; 113 if (ret < 0) {
105 dev->em28xx_sensor = EM28XX_MT9M111; 114 em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
106 break; 115 client.addr << 1, ret);
107 case 0x8431: 116 continue;
108 name = "mt9m001"; 117 }
109 dev->em28xx_sensor = EM28XX_MT9M001; 118 id = be16_to_cpu(id_be);
110 break; 119 /* Read chip ID from register 0xff */
111 default: 120 reg = 0xff;
112 em28xx_info("unknown Micron sensor detected: 0x%04x\n", id); 121 ret = i2c_master_send(&client, &reg, 1);
113 return -EINVAL; 122 if (ret < 0) {
123 em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
124 client.addr << 1, ret);
125 continue;
126 }
127 ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
128 if (ret < 0) {
129 em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
130 client.addr << 1, ret);
131 continue;
132 }
133 /* Validate chip ID to be sure we have a Micron device */
134 if (id != be16_to_cpu(id_be))
135 continue;
136 /* Check chip ID */
137 id = be16_to_cpu(id_be);
138 switch (id) {
139 case 0x1222:
140 name = "MT9V012"; /* MI370 */ /* 640x480 */
141 break;
142 case 0x1229:
143 name = "MT9V112"; /* 640x480 */
144 break;
145 case 0x1433:
146 name = "MT9M011"; /* 1280x1024 */
147 break;
148 case 0x143a: /* found in the ECS G200 */
149 name = "MT9M111"; /* MI1310 */ /* 1280x1024 */
150 dev->em28xx_sensor = EM28XX_MT9M111;
151 break;
152 case 0x148c:
153 name = "MT9M112"; /* MI1320 */ /* 1280x1024 */
154 break;
155 case 0x1511:
156 name = "MT9D011"; /* MI2010 */ /* 1600x1200 */
157 break;
158 case 0x8232:
159 case 0x8243: /* rev B */
160 name = "MT9V011"; /* MI360 */ /* 640x480 */
161 dev->em28xx_sensor = EM28XX_MT9V011;
162 break;
163 case 0x8431:
164 name = "MT9M001"; /* 1280x1024 */
165 dev->em28xx_sensor = EM28XX_MT9M001;
166 break;
167 default:
168 em28xx_info("unknown Micron sensor detected: 0x%04x\n",
169 id);
170 return -EINVAL;
171 }
172
173 if (dev->em28xx_sensor == EM28XX_NOSENSOR)
174 em28xx_info("unsupported sensor detected: %s\n", name);
175 else
176 em28xx_info("sensor %s detected\n", name);
177
178 dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
179 return 0;
114 } 180 }
115 181
116 em28xx_info("sensor %s detected\n", name); 182 return -ENODEV;
117
118 return 0;
119} 183}
120 184
121int em28xx_init_camera(struct em28xx *dev) 185int em28xx_init_camera(struct em28xx *dev)