aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorVianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>2015-03-24 11:54:15 -0400
committerJonathan Cameron <jic23@kernel.org>2015-03-29 11:17:12 -0400
commitbad4d1a074c7ba29636b951520574e18aec4c7fe (patch)
treea09405ded4560e47788f56be73667853c2f580d2 /drivers/iio
parent209c00691938c4b3d58142b05ca6f50b8971e521 (diff)
iio: mlx90614: Support devices with dual IR sensor
The model is detected by reading the EEPROM configuration during probing. Signed-off-by: Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com> Cc: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/temperature/mlx90614.c67
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index a2e3aa6aa39d..a112fc9abf43 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -2,6 +2,7 @@
2 * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor 2 * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
3 * 3 *
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> 4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 * Copyright (c) 2015 Essensium NV
5 * 6 *
6 * This file is subject to the terms and conditions of version 2 of 7 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main 8 * the GNU General Public License. See the file COPYING in the main
@@ -59,26 +60,34 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
59 int *val2, long mask) 60 int *val2, long mask)
60{ 61{
61 struct mlx90614_data *data = iio_priv(indio_dev); 62 struct mlx90614_data *data = iio_priv(indio_dev);
63 u8 cmd;
62 s32 ret; 64 s32 ret;
63 65
64 switch (mask) { 66 switch (mask) {
65 case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */ 67 case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */
66 switch (channel->channel2) { 68 switch (channel->channel2) {
67 case IIO_MOD_TEMP_AMBIENT: 69 case IIO_MOD_TEMP_AMBIENT:
68 ret = i2c_smbus_read_word_data(data->client, 70 cmd = MLX90614_TA;
69 MLX90614_TA);
70 if (ret < 0)
71 return ret;
72 break; 71 break;
73 case IIO_MOD_TEMP_OBJECT: 72 case IIO_MOD_TEMP_OBJECT:
74 ret = i2c_smbus_read_word_data(data->client, 73 switch (channel->channel) {
75 MLX90614_TOBJ1); 74 case 0:
76 if (ret < 0) 75 cmd = MLX90614_TOBJ1;
77 return ret; 76 break;
77 case 1:
78 cmd = MLX90614_TOBJ2;
79 break;
80 default:
81 return -EINVAL;
82 }
78 break; 83 break;
79 default: 84 default:
80 return -EINVAL; 85 return -EINVAL;
81 } 86 }
87
88 ret = i2c_smbus_read_word_data(data->client, cmd);
89 if (ret < 0)
90 return ret;
82 *val = ret; 91 *val = ret;
83 return IIO_VAL_INT; 92 return IIO_VAL_INT;
84 case IIO_CHAN_INFO_OFFSET: 93 case IIO_CHAN_INFO_OFFSET:
@@ -110,6 +119,16 @@ static const struct iio_chan_spec mlx90614_channels[] = {
110 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 119 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
111 BIT(IIO_CHAN_INFO_SCALE), 120 BIT(IIO_CHAN_INFO_SCALE),
112 }, 121 },
122 {
123 .type = IIO_TEMP,
124 .indexed = 1,
125 .modified = 1,
126 .channel = 1,
127 .channel2 = IIO_MOD_TEMP_OBJECT,
128 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
129 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
130 BIT(IIO_CHAN_INFO_SCALE),
131 },
113}; 132};
114 133
115static const struct iio_info mlx90614_info = { 134static const struct iio_info mlx90614_info = {
@@ -117,11 +136,25 @@ static const struct iio_info mlx90614_info = {
117 .driver_module = THIS_MODULE, 136 .driver_module = THIS_MODULE,
118}; 137};
119 138
139/* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
140static int mlx90614_probe_num_ir_sensors(struct i2c_client *client)
141{
142 s32 ret;
143
144 ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
145
146 if (ret < 0)
147 return ret;
148
149 return (ret & MLX90614_CONFIG_DUAL_MASK) ? 1 : 0;
150}
151
120static int mlx90614_probe(struct i2c_client *client, 152static int mlx90614_probe(struct i2c_client *client,
121 const struct i2c_device_id *id) 153 const struct i2c_device_id *id)
122{ 154{
123 struct iio_dev *indio_dev; 155 struct iio_dev *indio_dev;
124 struct mlx90614_data *data; 156 struct mlx90614_data *data;
157 int ret;
125 158
126 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 159 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
127 return -ENODEV; 160 return -ENODEV;
@@ -139,8 +172,21 @@ static int mlx90614_probe(struct i2c_client *client,
139 indio_dev->modes = INDIO_DIRECT_MODE; 172 indio_dev->modes = INDIO_DIRECT_MODE;
140 indio_dev->info = &mlx90614_info; 173 indio_dev->info = &mlx90614_info;
141 174
142 indio_dev->channels = mlx90614_channels; 175 ret = mlx90614_probe_num_ir_sensors(client);
143 indio_dev->num_channels = ARRAY_SIZE(mlx90614_channels); 176 switch (ret) {
177 case 0:
178 dev_dbg(&client->dev, "Found single sensor");
179 indio_dev->channels = mlx90614_channels;
180 indio_dev->num_channels = 2;
181 break;
182 case 1:
183 dev_dbg(&client->dev, "Found dual sensor");
184 indio_dev->channels = mlx90614_channels;
185 indio_dev->num_channels = 3;
186 break;
187 default:
188 return ret;
189 }
144 190
145 return iio_device_register(indio_dev); 191 return iio_device_register(indio_dev);
146} 192}
@@ -170,5 +216,6 @@ static struct i2c_driver mlx90614_driver = {
170module_i2c_driver(mlx90614_driver); 216module_i2c_driver(mlx90614_driver);
171 217
172MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 218MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
219MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>");
173MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); 220MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver");
174MODULE_LICENSE("GPL"); 221MODULE_LICENSE("GPL");