diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 08:40:53 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 08:40:53 +0300 |
commit | 118c216e16c5ccb028cd03a0dcd56d17a07ff8d7 (patch) | |
tree | 94769cd9af230aec964d95f380b1119bb8d8edf0 /drivers/iio/temperature/mlx90614.c | |
parent | fd0d351de7bbd718bc2b34d5846854831aa2b88c (diff) | |
parent | e3cc3136df33de1aa26d606f2a42cac3fd30cf54 (diff) | |
download | linux-118c216e16c5ccb028cd03a0dcd56d17a07ff8d7.tar.xz |
Merge tag 'staging-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging driver updates from Greg KH:
"Here's the big staging driver update for 4.4-rc1. If you were
disappointed for 4.3-rc1 that we didn't contribute enough changesets,
you should be happy with this pull request of over 2400 patches.
But overall we removed more lines of code than we added, which is nice
to see. Full details in the shortlog.
All of these have been in linux-next for a while"
Greg, I've never been disappointed in how few commits Staging
contributes to the kernel.. Never.
* tag 'staging-4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (2431 commits)
Staging: rtl8192u: ieee80211: added missing blank lines
Staging: rtl8192u: ieee80211: removed unnecessary braces
Staging: rtl8192u: ieee80211: corrected block comments
Staging: rtl8192u: ieee80211: corrected indent
Staging: rtl8192u: ieee80211: added missing spaces after if
Staging: rtl8192u: ieee80211: added missing space around '='
Staging: rtl8192u: ieee80211: fixed position of else statements
Staging: rtl8192u: ieee80211: fixed open brace positions
staging: rdma: ipath: Remove unneeded vairable.
staging: rtl8188eu: pwrGrpCnt variable removed in store_pwrindex_offset function
staging: rtl8188eu: new variable for hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt] in store_pwrindex_offset function
staging: rtl8188eu: checkpatch fixes: 'Avoid CamelCase' in hal/bb_cfg.c
staging: rtl8188eu: checkpatch fixes: line over 80 characters splited into two parts
staging: rtl8188eu: checkpatch fixes: alignment should match open parenthesis
staging: rtl8188eu: checkpatch fixes: unnecessary parentheses removed in hal/bb_cfg.c
staging: rtl8188eu: checkpatch fixes: spaces preferred around that '|' in hal/bb_cfg.c
staging: rtl8188eu: operator = replaced by += in loop increment
staging: rtl8188eu: occurrence of the 5 GHz code marked
staging: rtl8188eu: increment placed into for loop header
staging: rtl8188eu: while loop replaced by for loop in rtw_restruct_wmm_ie
...
Diffstat (limited to 'drivers/iio/temperature/mlx90614.c')
-rw-r--r-- | drivers/iio/temperature/mlx90614.c | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 5d033a5af615..a570c2e2aac3 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -3,6 +3,7 @@ * * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> * Copyright (c) 2015 Essensium NV + * Copyright (c) 2015 Melexis * * 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 @@ -20,7 +21,6 @@ * always has a pull-up so we do not need an extra GPIO to drive it high. If * the "wakeup" GPIO is not given, power management will be disabled. * - * TODO: filter configuration */ #include <linux/err.h> @@ -32,6 +32,7 @@ #include <linux/pm_runtime.h> #include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #define MLX90614_OP_RAM 0x00 #define MLX90614_OP_EEPROM 0x20 @@ -71,6 +72,7 @@ #define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */ #define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */ #define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */ +#define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter */ struct mlx90614_data { struct i2c_client *client; @@ -79,6 +81,20 @@ struct mlx90614_data { unsigned long ready_timestamp; /* in jiffies */ }; +/* Bandwidth values for IIR filtering */ +static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86}; +static IIO_CONST_ATTR(in_temp_object_filter_low_pass_3db_frequency_available, + "0.15 0.20 0.31 0.77 0.86 1.10 1.53 7.23"); + +static struct attribute *mlx90614_attributes[] = { + &iio_const_attr_in_temp_object_filter_low_pass_3db_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group mlx90614_attr_group = { + .attrs = mlx90614_attributes, +}; + /* * Erase an address and write word. * The mutex must be locked before calling. @@ -117,6 +133,43 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, return ret; } +/* + * Find the IIR value inside mlx90614_iir_values array and return its position + * which is equivalent to the bit value in sensor register + */ +static inline s32 mlx90614_iir_search(const struct i2c_client *client, + int value) +{ + int i; + s32 ret; + + for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) { + if (value == mlx90614_iir_values[i]) + break; + } + + if (i == ARRAY_SIZE(mlx90614_iir_values)) + return -EINVAL; + + /* + * CONFIG register values must not be changed so + * we must read them before we actually write + * changes + */ + ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG); + if (ret < 0) + return ret; + + ret &= ~MLX90614_CONFIG_FIR_MASK; + ret |= MLX90614_CONST_FIR << MLX90614_CONFIG_FIR_SHIFT; + ret &= ~MLX90614_CONFIG_IIR_MASK; + ret |= i << MLX90614_CONFIG_IIR_SHIFT; + + /* Write changed values */ + ret = mlx90614_write_word(client, MLX90614_CONFIG, ret); + return ret; +} + #ifdef CONFIG_PM /* * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since @@ -236,6 +289,21 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION; } return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with + FIR = 1024 */ + mlx90614_power_get(data, false); + mutex_lock(&data->lock); + ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); + mutex_unlock(&data->lock); + mlx90614_power_put(data); + + if (ret < 0) + return ret; + + *val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100; + *val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) * + 10000; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -263,6 +331,18 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, mlx90614_power_put(data); return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR Filter setting */ + if (val < 0 || val2 < 0) + return -EINVAL; + + mlx90614_power_get(data, false); + mutex_lock(&data->lock); + ret = mlx90614_iir_search(data->client, + val * 100 + val2 / 10000); + mutex_unlock(&data->lock); + mlx90614_power_put(data); + + return ret; default: return -EINVAL; } @@ -275,6 +355,8 @@ static int mlx90614_write_raw_get_fmt(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBEMISSIVITY: return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -294,7 +376,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { .modified = 1, .channel2 = IIO_MOD_TEMP_OBJECT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, @@ -305,7 +388,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { .channel = 1, .channel2 = IIO_MOD_TEMP_OBJECT, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, @@ -315,6 +399,7 @@ static const struct iio_info mlx90614_info = { .read_raw = mlx90614_read_raw, .write_raw = mlx90614_write_raw, .write_raw_get_fmt = mlx90614_write_raw_get_fmt, + .attrs = &mlx90614_attr_group, .driver_module = THIS_MODULE, }; @@ -569,5 +654,6 @@ 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_AUTHOR("Crt Mori <cmo@melexis.com>"); MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); MODULE_LICENSE("GPL"); |