#define KXCJK1013_REG_XOUT_L 0x06 /* * From low byte X axis register, all the other addresses of Y and Z can be * obtained by just applying axis offset. The following axis defines are just * provide clarity, but not used.
*/ #define KXCJK1013_REG_XOUT_H 0x07 #define KXCJK1013_REG_YOUT_L 0x08 #define KXCJK1013_REG_YOUT_H 0x09 #define KXCJK1013_REG_ZOUT_L 0x0A #define KXCJK1013_REG_ZOUT_H 0x0B
staticint kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
{ conststruct kx_chipset_regs *regs = data->info->regs; int ret;
ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret;
}
ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 |
KXCJK1013_REG_CTRL1_BIT_GSEL1);
ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret;
}
#ifdef CONFIG_ACPI if (data->info->acpi_type == ACPI_KIOX010A) { /* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
} #endif
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); if (ret < 0) {
dev_err(&data->client->dev, "Error reading who_am_i\n"); return ret;
}
dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret);
ret = kxcjk1013_set_mode(data, STANDBY); if (ret < 0) return ret;
ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret;
}
/* Set 12 bit mode */
ret |= KXCJK1013_REG_CTRL1_BIT_RES;
ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl\n"); return ret;
}
/* Setting range to 4G */
ret = kxcjk1013_set_range(data, KXCJK1013_RANGE_4G); if (ret < 0) return ret;
ret = i2c_smbus_read_byte_data(data->client, regs->data_ctrl); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); return ret;
}
data->odr_bits = ret;
/* Set up INT polarity */
ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); return ret;
}
if (data->active_high_intr)
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEA; else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA;
ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); return ret;
}
/* On KX023, route all used interrupts to INT1 for now */ if (data->info == &kx0231025_info && data->client->irq > 0) {
ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4,
KX023_REG_INC4_DRDY1 |
KX023_REG_INC4_WUFI1); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_inc4\n"); return ret;
}
}
ret = kxcjk1013_set_mode(data, OPERATION); if (ret < 0) return ret;
ret = kxcjk1013_get_mode(data, &store_mode); if (ret < 0) return ret;
/* This is requirement by spec to change state to STANDBY */
ret = kxcjk1013_set_mode(data, STANDBY); if (ret < 0) return ret;
if (is_new_data == true) {
ret = kxcjk1013_chip_update_thresholds(data); if (ret < 0) return ret;
}
ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); return ret;
}
if (status)
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); return ret;
}
ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret;
}
if (is_new_data) { if (status)
ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; else
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
} else { if (status)
ret |= KXCJK1013_REG_CTRL1_BIT_WUFE; else
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
}
ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret;
}
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION); if (ret < 0) return ret;
}
return 0;
}
staticconststruct kx_odr_map *kxcjk1013_find_odr_value( conststruct kx_odr_map *map, size_t map_size, int val, int val2)
{ int i;
for (i = 0; i < map_size; ++i) { if (map[i].val == val && map[i].val2 == val2) return &map[i];
}
return ERR_PTR(-EINVAL);
}
staticint kxcjk1013_convert_odr_value(conststruct kx_odr_map *map,
size_t map_size, int odr_bits, int *val, int *val2)
{ int i;
for (i = 0; i < map_size; ++i) { if (map[i].odr_bits == odr_bits) {
*val = map[i].val;
*val2 = map[i].val2; return IIO_VAL_INT_PLUS_MICRO;
}
}
return -EINVAL;
}
staticint kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
{ conststruct kx_chipset_regs *regs = data->info->regs; int ret; enum kxcjk1013_mode store_mode; conststruct kx_odr_map *odr_setting;
ret = kxcjk1013_get_mode(data, &store_mode); if (ret < 0) return ret;
if (IS_ERR(odr_setting)) return PTR_ERR(odr_setting);
/* To change ODR, the chip must be set to STANDBY as per spec */
ret = kxcjk1013_set_mode(data, STANDBY); if (ret < 0) return ret;
ret = i2c_smbus_write_byte_data(data->client, regs->data_ctrl,
odr_setting->odr_bits); if (ret < 0) {
dev_err(&data->client->dev, "Error writing data_ctrl\n"); return ret;
}
data->odr_bits = odr_setting->odr_bits;
ret = i2c_smbus_write_byte_data(data->client, regs->wuf_ctrl,
odr_setting->wuf_bits); if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); return ret;
}
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION); if (ret < 0) return ret;
}
return 0;
}
staticint kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
{ if (data->info == &kxtf9_info) return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
data->odr_bits, val, val2); else return kxcjk1013_convert_odr_value(samp_freq_table,
ARRAY_SIZE(samp_freq_table),
data->odr_bits, val, val2);
}
staticint kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis)
{
u8 reg = KXCJK1013_REG_XOUT_L + axis * 2; int ret;
ret = i2c_smbus_read_word_data(data->client, reg); if (ret < 0) {
dev_err(&data->client->dev, "failed to read accel_%c registers\n", 'x' + axis); return ret;
}
return ret;
}
staticint kxcjk1013_set_scale(struct kxcjk1013_data *data, int val)
{ int ret, i; enum kxcjk1013_mode store_mode;
for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) { if (KXCJK1013_scale_table[i].scale == val) {
ret = kxcjk1013_get_mode(data, &store_mode); if (ret < 0) return ret;
ret = kxcjk1013_set_mode(data, STANDBY); if (ret < 0) return ret;
ret = kxcjk1013_set_range(data, i); if (ret < 0) return ret;
if (store_mode == OPERATION) {
ret = kxcjk1013_set_mode(data, OPERATION); if (ret) return ret;
}
return 0;
}
}
return -EINVAL;
}
staticint kxcjk1013_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct kxcjk1013_data *data = iio_priv(indio_dev); int ret;
switch (mask) { case IIO_CHAN_INFO_RAW:
mutex_lock(&data->mutex); if (iio_buffer_enabled(indio_dev))
ret = -EBUSY; else {
ret = kxcjk1013_set_power_state(data, true); if (ret < 0) {
mutex_unlock(&data->mutex); return ret;
}
ret = kxcjk1013_get_acc_reg(data, chan->scan_index); if (ret < 0) {
kxcjk1013_set_power_state(data, false);
mutex_unlock(&data->mutex); return ret;
}
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = kxcjk1013_set_power_state(data, false);
}
mutex_unlock(&data->mutex);
if (ret < 0) return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = KXCJK1013_scale_table[data->range].scale; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(&data->mutex);
ret = kxcjk1013_get_odr(data, val, val2);
mutex_unlock(&data->mutex); return ret;
default: return -EINVAL;
}
}
staticint kxcjk1013_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct kxcjk1013_data *data = iio_priv(indio_dev); int ret;
switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(&data->mutex);
ret = kxcjk1013_set_odr(data, val, val2);
mutex_unlock(&data->mutex); break; case IIO_CHAN_INFO_SCALE: if (val) return -EINVAL;
mutex_lock(&data->mutex);
ret = kxcjk1013_set_scale(data, val2);
mutex_unlock(&data->mutex); break; default:
ret = -EINVAL;
}
/* * We will expect the enable and disable to do operation in * reverse order. This will happen here anyway as our * resume operation uses sync mode runtime pm calls, the * suspend operation will be delayed by autosuspend delay * So the disable operation will still happen in reverse of * enable operation. When runtime pm is disabled the mode * is always on so sequence doesn't matter
*/
ret = kxcjk1013_set_power_state(data, state); if (ret < 0) {
mutex_unlock(&data->mutex); return ret;
}
ret = kxcjk1013_setup_interrupt(data, state, false); if (ret < 0) {
kxcjk1013_set_power_state(data, false);
data->ev_enable_state = 0;
mutex_unlock(&data->mutex); return ret;
}
if (!iio_read_acpi_mount_matrix(&client->dev, &data->orientation, "ROTM")) {
ret = iio_read_mount_matrix(&client->dev, &data->orientation); if (ret) return ret;
}
}
ret = devm_regulator_bulk_get_enable(&client->dev,
ARRAY_SIZE(regulator_names),
regulator_names); if (ret) return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
/* * A typical delay of 10ms is required for powering up * according to the data sheets of supported chips. * Hence double that to play safe.
*/
msleep(20);
if (id) {
name = id->name;
data->info = (conststruct kx_chipset_info *)(id->driver_data);
} else {
name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
data->info = ddata; if (data->info == &kxcj91008_kiox010a_info)
indio_dev->label = "accel-display"; elseif (data->info == &kxcj91008_kiox020a_info)
indio_dev->label = "accel-base";
} if (!name) return -ENODEV;
ret = kxcjk1013_chip_init(data); if (ret < 0) return ret;
mutex_lock(&data->mutex);
ret = kxcjk1013_set_mode(data, STANDBY);
mutex_unlock(&data->mutex);
return ret;
}
staticint kxcjk1013_resume(struct device *dev)
{ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct kxcjk1013_data *data = iio_priv(indio_dev); int ret = 0;
mutex_lock(&data->mutex);
ret = kxcjk1013_set_mode(data, OPERATION); if (ret == 0)
ret = kxcjk1013_set_range(data, data->range);
mutex_unlock(&data->mutex);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.