diff options
author | Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com> | 2015-03-24 11:54:15 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-03-29 11:17:12 -0400 |
commit | bad4d1a074c7ba29636b951520574e18aec4c7fe (patch) | |
tree | a09405ded4560e47788f56be73667853c2f580d2 /drivers/iio | |
parent | 209c00691938c4b3d58142b05ca6f50b8971e521 (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.c | 67 |
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 | ||
115 | static const struct iio_info mlx90614_info = { | 134 | static 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. */ | ||
140 | static 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 | |||
120 | static int mlx90614_probe(struct i2c_client *client, | 152 | static 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 = { | |||
170 | module_i2c_driver(mlx90614_driver); | 216 | module_i2c_driver(mlx90614_driver); |
171 | 217 | ||
172 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | 218 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); |
219 | MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>"); | ||
173 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); | 220 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); |
174 | MODULE_LICENSE("GPL"); | 221 | MODULE_LICENSE("GPL"); |