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>
This commit is contained in:
Vianney le Clément de Saint-Marcq 2015-03-24 16:54:15 +01:00 committed by Jonathan Cameron
parent 209c006919
commit bad4d1a074
1 changed files with 57 additions and 10 deletions

View File

@ -2,6 +2,7 @@
* mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
*
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
* Copyright (c) 2015 Essensium NV
*
* This file is subject to the terms and conditions of version 2 of
* 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,
int *val2, long mask)
{
struct mlx90614_data *data = iio_priv(indio_dev);
u8 cmd;
s32 ret;
switch (mask) {
case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */
switch (channel->channel2) {
case IIO_MOD_TEMP_AMBIENT:
ret = i2c_smbus_read_word_data(data->client,
MLX90614_TA);
if (ret < 0)
return ret;
cmd = MLX90614_TA;
break;
case IIO_MOD_TEMP_OBJECT:
ret = i2c_smbus_read_word_data(data->client,
MLX90614_TOBJ1);
if (ret < 0)
return ret;
switch (channel->channel) {
case 0:
cmd = MLX90614_TOBJ1;
break;
case 1:
cmd = MLX90614_TOBJ2;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
ret = i2c_smbus_read_word_data(data->client, cmd);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
@ -110,6 +119,16 @@ static const struct iio_chan_spec mlx90614_channels[] = {
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
},
{
.type = IIO_TEMP,
.indexed = 1,
.modified = 1,
.channel = 1,
.channel2 = IIO_MOD_TEMP_OBJECT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static const struct iio_info mlx90614_info = {
@ -117,11 +136,25 @@ static const struct iio_info mlx90614_info = {
.driver_module = THIS_MODULE,
};
/* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
static int mlx90614_probe_num_ir_sensors(struct i2c_client *client)
{
s32 ret;
ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
if (ret < 0)
return ret;
return (ret & MLX90614_CONFIG_DUAL_MASK) ? 1 : 0;
}
static int mlx90614_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct mlx90614_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
@ -139,8 +172,21 @@ static int mlx90614_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mlx90614_info;
indio_dev->channels = mlx90614_channels;
indio_dev->num_channels = ARRAY_SIZE(mlx90614_channels);
ret = mlx90614_probe_num_ir_sensors(client);
switch (ret) {
case 0:
dev_dbg(&client->dev, "Found single sensor");
indio_dev->channels = mlx90614_channels;
indio_dev->num_channels = 2;
break;
case 1:
dev_dbg(&client->dev, "Found dual sensor");
indio_dev->channels = mlx90614_channels;
indio_dev->num_channels = 3;
break;
default:
return ret;
}
return iio_device_register(indio_dev);
}
@ -170,5 +216,6 @@ static struct i2c_driver mlx90614_driver = {
module_i2c_driver(mlx90614_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>");
MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver");
MODULE_LICENSE("GPL");