diff options
Diffstat (limited to 'drivers/iio/accel/kxcjk-1013.c')
-rw-r--r-- | drivers/iio/accel/kxcjk-1013.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index da2fe93739a2..567de269cc00 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -108,6 +108,7 @@ struct kxcjk1013_data { bool motion_trigger_on; int64_t timestamp; enum kx_chipset chipset; + bool is_smo8500_device; }; enum kxcjk1013_axis { @@ -377,6 +378,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) { +#ifdef CONFIG_PM int ret; if (on) @@ -388,8 +390,11 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: kxcjk1013_set_power_state for %d\n", on); + if (on) + pm_runtime_put_noidle(&data->client->dev); return ret; } +#endif return 0; } @@ -858,6 +863,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, ret = kxcjk1013_setup_any_motion_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); + data->ev_enable_state = 0; mutex_unlock(&data->mutex); return ret; } @@ -1008,6 +1015,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, else ret = kxcjk1013_setup_new_data_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -1131,12 +1139,16 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) } static const char *kxcjk1013_match_acpi_device(struct device *dev, - enum kx_chipset *chipset) + enum kx_chipset *chipset, + bool *is_smo8500_device) { const struct acpi_device_id *id; + id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return NULL; + if (strcmp(id->id, "SMO8500") == 0) + *is_smo8500_device = true; *chipset = (enum kx_chipset)id->driver_data; return dev_name(dev); @@ -1151,6 +1163,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client, if (!client) return -EINVAL; + if (data->is_smo8500_device) + return -ENOTSUPP; dev = &client->dev; @@ -1200,7 +1214,8 @@ static int kxcjk1013_probe(struct i2c_client *client, name = id->name; } else if (ACPI_HANDLE(&client->dev)) { name = kxcjk1013_match_acpi_device(&client->dev, - &data->chipset); + &data->chipset, + &data->is_smo8500_device); } else return -ENODEV; @@ -1228,21 +1243,25 @@ static int kxcjk1013_probe(struct i2c_client *client, KXCJK1013_IRQ_NAME, indio_dev); if (ret) - return ret; + goto err_poweroff; data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, indio_dev->id); - if (!data->dready_trig) - return -ENOMEM; + if (!data->dready_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->motion_trig = devm_iio_trigger_alloc(&client->dev, "%s-any-motion-dev%d", indio_dev->name, indio_dev->id); - if (!data->motion_trig) - return -ENOMEM; + if (!data->motion_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->dready_trig->dev.parent = &client->dev; data->dready_trig->ops = &kxcjk1013_trigger_ops; @@ -1251,7 +1270,7 @@ static int kxcjk1013_probe(struct i2c_client *client, iio_trigger_get(indio_dev->trig); ret = iio_trigger_register(data->dready_trig); if (ret) - return ret; + goto err_poweroff; data->motion_trig->dev.parent = &client->dev; data->motion_trig->ops = &kxcjk1013_trigger_ops; @@ -1300,6 +1319,8 @@ err_trigger_unregister: iio_trigger_unregister(data->dready_trig); if (data->motion_trig) iio_trigger_unregister(data->motion_trig); +err_poweroff: + kxcjk1013_set_mode(data, STANDBY); return ret; } @@ -1349,10 +1370,7 @@ static int kxcjk1013_resume(struct device *dev) int ret = 0; mutex_lock(&data->mutex); - /* Check, if the suspend occured while active */ - if (data->dready_trigger_on || data->motion_trigger_on || - data->ev_enable_state) - ret = kxcjk1013_set_mode(data, OPERATION); + ret = kxcjk1013_set_mode(data, OPERATION); mutex_unlock(&data->mutex); return ret; @@ -1364,8 +1382,14 @@ static int kxcjk1013_runtime_suspend(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; - return kxcjk1013_set_mode(data, STANDBY); + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + return 0; } static int kxcjk1013_runtime_resume(struct device *dev) @@ -1399,6 +1423,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXTJ1009", KXTJ21009}, + {"SMO8500", KXCJ91008}, { }, }; MODULE_DEVICE_TABLE(acpi, kx_acpi_match); @@ -1407,6 +1432,7 @@ static const struct i2c_device_id kxcjk1013_id[] = { {"kxcjk1013", KXCJK1013}, {"kxcj91008", KXCJ91008}, {"kxtj21009", KXTJ21009}, + {"SMO8500", KXCJ91008}, {} }; |