Signed-off-by: Peter Meerwald <pmeerw@xxxxxxxxxx> --- drivers/staging/iio/magnetometer/hmc5843.c | 135 +++++++++++----------------- 1 file changed, 54 insertions(+), 81 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 5327e5f..d8a5c01 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -165,18 +165,19 @@ static const int hmc5883l_regval_to_input_field_mga[] = { * 6 | 50 | 75 * 7 | Not used | Not used */ -static const char * const hmc5843_regval_to_sample_freq[] = { - "0.5", "1", "2", "5", "10", "20", "50", +static const int hmc5843_regval_to_samp_freq[7][2] = { + {0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0} }; -static const char * const hmc5883_regval_to_sample_freq[] = { - "0.75", "1.5", "3", "7.5", "15", "30", "75", +static const int hmc5883_regval_to_samp_freq[7][2] = { + {0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0}, + {75, 0} }; /* Describe chip variants */ struct hmc5843_chip_info { const struct iio_chan_spec *channels; - const char * const *regval_to_sample_freq; + const int (*regval_to_samp_freq)[2]; const int *regval_to_input_field_mga; const int *regval_to_nanoscale; }; @@ -370,17 +371,17 @@ static IIO_DEVICE_ATTR(meas_conf, hmc5843_set_measurement_configuration, 0); -static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t hmc5843_show_samp_freq_avail(struct device *dev, + struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct hmc5843_data *data = iio_priv(indio_dev); + struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev)); ssize_t total_n = 0; int i; for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]); + ssize_t n = sprintf(buf, "%d.%d ", + data->variant->regval_to_samp_freq[i][0], + data->variant->regval_to_samp_freq[i][1]); buf += n; total_n += n; } @@ -390,87 +391,30 @@ static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, return total_n; } -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available); +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail); static s32 hmc5843_set_rate(struct hmc5843_data *data, u8 rate) { - u8 reg_val; + u8 reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET); - if (rate >= HMC5843_RATE_NOT_USED) { - dev_err(&data->client->dev, - "data output rate is not supported\n"); - return -EINVAL; - } - - reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET); return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A, reg_val); } -static int hmc5843_check_sampling_frequency(struct hmc5843_data *data, - const char *buf) +static int hmc5843_check_samp_freq(struct hmc5843_data *data, + int val, int val2) { - const char * const *samp_freq = data->variant->regval_to_sample_freq; int i; for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { - if (sysfs_streq(buf, samp_freq[i])) + if (val == data->variant->regval_to_samp_freq[i][0] && + val2 == data->variant->regval_to_samp_freq[i][1]) return i; } return -EINVAL; } -static ssize_t hmc5843_set_sampling_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct hmc5843_data *data = iio_priv(indio_dev); - int rate; - - rate = hmc5843_check_sampling_frequency(data, buf); - if (rate < 0) { - dev_err(&data->client->dev, - "sampling frequency is not supported\n"); - return rate; - } - - mutex_lock(&data->lock); - dev_dbg(dev, "set rate to %d\n", rate); - if (hmc5843_set_rate(data->client, rate)) { - count = -EINVAL; - goto exit; - } - data->rate = rate; - -exit: - mutex_unlock(&data->lock); - return count; -} - -static ssize_t hmc5843_show_sampling_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct hmc5843_data *data = iio_priv(indio_dev); - s32 rate; - - rate = i2c_smbus_read_byte_data(data->client, this_attr->address); - if (rate < 0) - return rate; - rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET; - return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]); -} - -static IIO_DEVICE_ATTR(sampling_frequency, - S_IWUSR | S_IRUGO, - hmc5843_show_sampling_frequency, - hmc5843_set_sampling_frequency, - HMC5843_CONFIG_REG_A); - static ssize_t hmc5843_show_range_gain(struct device *dev, struct device_attribute *attr, char *buf) @@ -525,8 +469,7 @@ static IIO_DEVICE_ATTR(in_magn_range, static int hmc5843_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) + int *val, int *val2, long mask) { struct hmc5843_data *data = iio_priv(indio_dev); @@ -537,17 +480,47 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = data->variant->regval_to_nanoscale[data->range]; return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = data->variant->regval_to_samp_freq[data->rate][0]; + *val2 = data->variant->regval_to_samp_freq[data->rate][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } +static int hmc5843_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct hmc5843_data *data = iio_priv(indio_dev); + int ret, rate; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + rate = hmc5843_check_samp_freq(data, val, val2); + if (rate < 0) + return -EINVAL; + + mutex_lock(&data->lock); + ret = hmc5843_set_rate(data, rate); + if (ret >= 0) + data->rate = rate; + mutex_unlock(&data->lock); + + return ret; + default: + return -EINVAL; + } +} + #define HMC5843_CHANNEL(axis, addr) \ { \ .type = IIO_MAGN, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = addr \ } @@ -566,7 +539,6 @@ static const struct iio_chan_spec hmc5883_channels[] = { static struct attribute *hmc5843_attributes[] = { &iio_dev_attr_meas_conf.dev_attr.attr, &iio_dev_attr_operating_mode.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_in_magn_range.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL @@ -579,21 +551,21 @@ static const struct attribute_group hmc5843_group = { static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { [HMC5843_ID] = { .channels = hmc5843_channels, - .regval_to_sample_freq = hmc5843_regval_to_sample_freq, + .regval_to_samp_freq = hmc5843_regval_to_samp_freq, .regval_to_input_field_mga = hmc5843_regval_to_input_field_mga, .regval_to_nanoscale = hmc5843_regval_to_nanoscale, }, [HMC5883_ID] = { .channels = hmc5883_channels, - .regval_to_sample_freq = hmc5883_regval_to_sample_freq, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, .regval_to_input_field_mga = hmc5883_regval_to_input_field_mga, .regval_to_nanoscale = hmc5883_regval_to_nanoscale, }, [HMC5883L_ID] = { .channels = hmc5883_channels, - .regval_to_sample_freq = hmc5883_regval_to_sample_freq, + .regval_to_samp_freq = hmc5883_regval_to_samp_freq, .regval_to_input_field_mga = hmc5883l_regval_to_input_field_mga, .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, @@ -612,6 +584,7 @@ static void hmc5843_init(struct hmc5843_data *data) static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, .read_raw = &hmc5843_read_raw, + .write_raw = &hmc5843_write_raw, .driver_module = THIS_MODULE, }; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html