static int mma8452_write_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); int i, ret; if (iio_buffer_enabled(indio_dev)) return -EBUSY; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: i = mma8452_get_samp_freq_index(data, val, val2); if (i < 0) return i; data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK; data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT; return mma8452_change_config(data, MMA8452_CTRL_REG1, data->ctrl_reg1); case IIO_CHAN_INFO_SCALE: i = mma8452_get_scale_index(data, val, val2); if (i < 0) return i; data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK; data->data_cfg |= i; return mma8452_change_config(data, MMA8452_DATA_CFG, data->data_cfg); case IIO_CHAN_INFO_CALIBBIAS: if (val < -128 || val > 127) return -EINVAL; return mma8452_change_config(data, MMA8452_OFF_X + chan->scan_index, val); case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: if (val == 0 && val2 == 0) { data->data_cfg &= ~MMA8452_DATA_CFG_HPF_MASK; } else { data->data_cfg |= MMA8452_DATA_CFG_HPF_MASK; ret = mma8452_set_hp_filter_frequency(data, val, val2); if (ret < 0) return ret; } return mma8452_change_config(data, MMA8452_DATA_CFG, data->data_cfg); default: return -EINVAL; } }
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_set_freefall_mode(struct mma8452_data *data, bool state) { int val; const struct mma_chip_info *chip = data->chip_info; if ((state && mma8452_freefall_mode_enabled(data)) || (!state && !(mma8452_freefall_mode_enabled(data)))) return 0; val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); if (val < 0) return val; if (state) { val |= BIT(idx_x + chip->ev_cfg_chan_shift); val |= BIT(idx_y + chip->ev_cfg_chan_shift); val |= BIT(idx_z + chip->ev_cfg_chan_shift); val &= ~MMA8452_FF_MT_CFG_OAE; } else { val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); val |= MMA8452_FF_MT_CFG_OAE; } val = mma8452_change_config(data, chip->ev_cfg, val); if (val) return val; return 0; }
static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct mma8452_data *data = iio_priv(indio_dev); int reg; reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4); if (reg < 0) return reg; if (state) reg |= MMA8452_INT_DRDY; else reg &= ~MMA8452_INT_DRDY; return mma8452_change_config(data, MMA8452_CTRL_REG4, reg); }
static int mma8452_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, int state) { struct mma8452_data *data = iio_priv(indio_dev); const struct mma_chip_info *chip = data->chip_info; int val, ret; ret = mma8452_set_runtime_pm_state(data->client, state); if (ret) return ret; switch (dir) { case IIO_EV_DIR_FALLING: return mma8452_set_freefall_mode(data, state); case IIO_EV_DIR_RISING: val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); if (val < 0) return val; if (state) { if (mma8452_freefall_mode_enabled(data)) { val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); val |= MMA8452_FF_MT_CFG_OAE; } val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); } else { if (mma8452_freefall_mode_enabled(data)) return 0; val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); } val |= chip->ev_cfg_ele; return mma8452_change_config(data, chip->ev_cfg, val); default: return -EINVAL; } }
static int mma8452_set_hp_filter_frequency(struct mma8452_data *data, int val, int val2) { int i, reg; i = mma8452_get_hp_filter_index(data, val, val2); if (i < 0) return i; reg = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); if (reg < 0) return reg; reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK; reg |= i; return mma8452_change_config(data, MMA8452_HP_FILTER_CUTOFF, reg); }
static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, unsigned reg, unsigned writeval, unsigned *readval) { int ret; struct mma8452_data *data = iio_priv(indio_dev); if (reg > MMA8452_MAX_REG) return -EINVAL; if (!readval) return mma8452_change_config(data, reg, writeval); ret = i2c_smbus_read_byte_data(data->client, reg); if (ret < 0) return ret; *readval = ret; return 0; }
static int mma8452_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, int state) { struct mma8452_data *data = iio_priv(indio_dev); int val; val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); if (val < 0) return val; if (state) val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); else val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); val |= MMA8452_TRANSIENT_CFG_ELE; return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val); }
static int mma8452_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, int state) { struct mma8452_data *data = iio_priv(indio_dev); const struct mma_chip_info *chip = data->chip_info; int val; val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); if (val < 0) return val; if (state) val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); else val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); val |= chip->ev_cfg_ele; val |= MMA8452_FF_MT_CFG_OAE; return mma8452_change_config(data, chip->ev_cfg, val); }