static int mma8452_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct mma8452_data *data = iio_priv(indio_dev); __be16 buffer[3]; int i, ret; switch (mask) { case IIO_CHAN_INFO_RAW: if (iio_buffer_enabled(indio_dev)) return -EBUSY; mutex_lock(&data->lock); ret = mma8452_read(data, buffer); mutex_unlock(&data->lock); if (ret < 0) return ret; *val = sign_extend32(be16_to_cpu( buffer[chan->scan_index]) >> chan->scan_type.shift, chan->scan_type.realbits - 1); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK; *val = data->chip_info->mma_scales[i][0]; *val2 = data->chip_info->mma_scales[i][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: i = mma8452_get_odr_index(data); *val = mma8452_samp_freq[i][0]; *val2 = mma8452_samp_freq[i][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X + chan->scan_index); if (ret < 0) return ret; *val = sign_extend32(ret, 7); return IIO_VAL_INT; case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) { ret = mma8452_read_hp_filter(data, val, val2); if (ret < 0) return ret; } else { *val = 0; *val2 = 0; } return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; }
static int mma8452_get_hp_filter_index(struct mma8452_data *data, int val, int val2) { int i = mma8452_get_odr_index(data); return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i], ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2); }
static int mma8452_read_thresh(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int *val, int *val2) { struct mma8452_data *data = iio_priv(indio_dev); int ret, us; switch (info) { case IIO_EV_INFO_VALUE: ret = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_ths); if (ret < 0) return ret; *val = ret & data->chip_info->ev_ths_mask; return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: ret = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_count); if (ret < 0) return ret; us = ret * mma8452_transient_time_step_us[ mma8452_get_odr_index(data)]; *val = us / USEC_PER_SEC; *val2 = us % USEC_PER_SEC; return IIO_VAL_INT_PLUS_MICRO; case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); if (ret < 0) return ret; if (ret & MMA8452_TRANSIENT_CFG_HPF_BYP) { *val = 0; *val2 = 0; } else { ret = mma8452_read_hp_filter(data, val, val2); if (ret < 0) return ret; } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } }
static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct mma8452_data *data = iio_priv(indio_dev); int i = mma8452_get_odr_index(data); return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[i], ARRAY_SIZE(mma8452_hp_filter_cutoff[0])); }
static int mma8452_write_thresh(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int val, int val2) { struct mma8452_data *data = iio_priv(indio_dev); int ret, reg, steps; switch (info) { case IIO_EV_INFO_VALUE: if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK) return -EINVAL; return mma8452_change_config(data, data->chip_info->ev_ths, val); case IIO_EV_INFO_PERIOD: steps = (val * USEC_PER_SEC + val2) / mma8452_transient_time_step_us[ mma8452_get_odr_index(data)]; if (steps < 0 || steps > 0xff) return -EINVAL; return mma8452_change_config(data, data->chip_info->ev_count, steps); case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: reg = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); if (reg < 0) return reg; if (val == 0 && val2 == 0) { reg |= MMA8452_TRANSIENT_CFG_HPF_BYP; } else { reg &= ~MMA8452_TRANSIENT_CFG_HPF_BYP; ret = mma8452_set_hp_filter_frequency(data, val, val2); if (ret < 0) return ret; } return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg); default: return -EINVAL; } }
static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz) { int i, ret; ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); if (ret < 0) return ret; i = mma8452_get_odr_index(data); ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK; *hz = mma8452_hp_filter_cutoff[i][ret][0]; *uHz = mma8452_hp_filter_cutoff[i][ret][1]; return 0; }
static int mma8452_runtime_resume(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct mma8452_data *data = iio_priv(indio_dev); int ret, sleep_val; ret = mma8452_active(data); if (ret < 0) return ret; ret = mma8452_get_odr_index(data); sleep_val = 1000 / mma8452_samp_freq[ret][0]; if (sleep_val < 20) usleep_range(sleep_val * 1000, 20000); else msleep_interruptible(sleep_val); return 0; }