Commit 4599cac8 authored by Jean-Baptiste Maneyrol's avatar Jean-Baptiste Maneyrol Committed by Jonathan Cameron

iio: imu: inv_mpu6050: use runtime pm with autosuspend

Use runtime power management for handling chip power and
sensor engines on/off. Simplifies things a lot since pm
runtime already has reference counter.
Usage of autosuspend reduces the number of power on/off. This
makes polling interface now usable to get data at low
frequency.
Signed-off-by: default avatarJean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 5e95ca36
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include "inv_mpu_iio.h" #include "inv_mpu_iio.h"
#include "inv_mpu_magn.h" #include "inv_mpu_magn.h"
...@@ -396,30 +398,18 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, ...@@ -396,30 +398,18 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
return 0; return 0;
} }
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) static int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st,
bool power_on)
{ {
int result; int result;
if (power_on) { result = inv_mpu6050_pwr_mgmt_1_write(st, !power_on, -1, -1);
if (!st->powerup_count) {
result = inv_mpu6050_pwr_mgmt_1_write(st, false, -1, -1);
if (result) if (result)
return result; return result;
if (power_on)
usleep_range(INV_MPU6050_REG_UP_TIME_MIN, usleep_range(INV_MPU6050_REG_UP_TIME_MIN,
INV_MPU6050_REG_UP_TIME_MAX); INV_MPU6050_REG_UP_TIME_MAX);
}
st->powerup_count++;
} else {
if (st->powerup_count == 1) {
result = inv_mpu6050_pwr_mgmt_1_write(st, true, -1, -1);
if (result)
return result;
}
st->powerup_count--;
}
dev_dbg(regmap_get_device(st->map), "set power %d, count=%u\n",
power_on, st->powerup_count);
return 0; return 0;
} }
...@@ -563,6 +553,7 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -563,6 +553,7 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
int *val) int *val)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
struct device *pdev = regmap_get_device(st->map);
unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us; unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;
int result; int result;
int ret; int ret;
...@@ -571,12 +562,15 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -571,12 +562,15 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
period_us = 1000000 / freq_hz; period_us = 1000000 / freq_hz;
result = inv_mpu6050_set_power_itg(st, true); result = pm_runtime_get_sync(pdev);
if (result) if (result < 0) {
pm_runtime_put_noidle(pdev);
return result; return result;
}
switch (chan->type) { switch (chan->type) {
case IIO_ANGL_VEL: case IIO_ANGL_VEL:
if (!st->chip_config.gyro_en) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_SENSOR_GYRO); INV_MPU6050_SENSOR_GYRO);
if (result) if (result)
...@@ -585,14 +579,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -585,14 +579,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
min_sleep_us = 2 * period_us; min_sleep_us = 2 * period_us;
max_sleep_us = 2 * (period_us + period_us / 2); max_sleep_us = 2 * (period_us + period_us / 2);
usleep_range(min_sleep_us, max_sleep_us); usleep_range(min_sleep_us, max_sleep_us);
}
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro, ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
chan->channel2, val); chan->channel2, val);
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_SENSOR_GYRO);
if (result)
goto error_power_off;
break; break;
case IIO_ACCEL: case IIO_ACCEL:
if (!st->chip_config.accl_en) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_SENSOR_ACCL); INV_MPU6050_SENSOR_ACCL);
if (result) if (result)
...@@ -601,14 +593,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -601,14 +593,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
min_sleep_us = period_us; min_sleep_us = period_us;
max_sleep_us = period_us + period_us / 2; max_sleep_us = period_us + period_us / 2;
usleep_range(min_sleep_us, max_sleep_us); usleep_range(min_sleep_us, max_sleep_us);
}
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl, ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
chan->channel2, val); chan->channel2, val);
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_SENSOR_ACCL);
if (result)
goto error_power_off;
break; break;
case IIO_TEMP: case IIO_TEMP:
if (!st->chip_config.temp_en) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_SENSOR_TEMP); INV_MPU6050_SENSOR_TEMP);
if (result) if (result)
...@@ -617,14 +607,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -617,14 +607,12 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
min_sleep_us = period_us; min_sleep_us = period_us;
max_sleep_us = period_us + period_us / 2; max_sleep_us = period_us + period_us / 2;
usleep_range(min_sleep_us, max_sleep_us); usleep_range(min_sleep_us, max_sleep_us);
}
ret = inv_mpu6050_sensor_show(st, st->reg->temperature, ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
IIO_MOD_X, val); IIO_MOD_X, val);
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_SENSOR_TEMP);
if (result)
goto error_power_off;
break; break;
case IIO_MAGN: case IIO_MAGN:
if (!st->chip_config.magn_en) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_SENSOR_MAGN); INV_MPU6050_SENSOR_MAGN);
if (result) if (result)
...@@ -638,25 +626,21 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ...@@ -638,25 +626,21 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
min_sleep_us = 2 * period_us; min_sleep_us = 2 * period_us;
max_sleep_us = 2 * (period_us + period_us / 2); max_sleep_us = 2 * (period_us + period_us / 2);
usleep_range(min_sleep_us, max_sleep_us); usleep_range(min_sleep_us, max_sleep_us);
}
ret = inv_mpu_magn_read(st, chan->channel2, val); ret = inv_mpu_magn_read(st, chan->channel2, val);
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_SENSOR_MAGN);
if (result)
goto error_power_off;
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
result = inv_mpu6050_set_power_itg(st, false); pm_runtime_mark_last_busy(pdev);
if (result) pm_runtime_put_autosuspend(pdev);
goto error_power_off;
return ret; return ret;
error_power_off: error_power_off:
inv_mpu6050_set_power_itg(st, false); pm_runtime_put_autosuspend(pdev);
return result; return result;
} }
...@@ -795,6 +779,7 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, ...@@ -795,6 +779,7 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask) int val, int val2, long mask)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
struct device *pdev = regmap_get_device(st->map);
int result; int result;
/* /*
...@@ -806,9 +791,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, ...@@ -806,9 +791,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
return result; return result;
mutex_lock(&st->lock); mutex_lock(&st->lock);
result = inv_mpu6050_set_power_itg(st, true); result = pm_runtime_get_sync(pdev);
if (result) if (result < 0) {
pm_runtime_put_noidle(pdev);
goto error_write_raw_unlock; goto error_write_raw_unlock;
}
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -846,7 +833,8 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, ...@@ -846,7 +833,8 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
break; break;
} }
result |= inv_mpu6050_set_power_itg(st, false); pm_runtime_mark_last_busy(pdev);
pm_runtime_put_autosuspend(pdev);
error_write_raw_unlock: error_write_raw_unlock:
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev); iio_device_release_direct_mode(indio_dev);
...@@ -903,6 +891,7 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, ...@@ -903,6 +891,7 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
int result; int result;
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
struct device *pdev = regmap_get_device(st->map);
if (kstrtoint(buf, 10, &fifo_rate)) if (kstrtoint(buf, 10, &fifo_rate))
return -EINVAL; return -EINVAL;
...@@ -920,9 +909,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, ...@@ -920,9 +909,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
result = 0; result = 0;
goto fifo_rate_fail_unlock; goto fifo_rate_fail_unlock;
} }
result = inv_mpu6050_set_power_itg(st, true); result = pm_runtime_get_sync(pdev);
if (result) if (result < 0) {
pm_runtime_put_noidle(pdev);
goto fifo_rate_fail_unlock; goto fifo_rate_fail_unlock;
}
result = regmap_write(st->map, st->reg->sample_rate_div, d); result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result) if (result)
...@@ -938,8 +929,9 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, ...@@ -938,8 +929,9 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (result) if (result)
goto fifo_rate_fail_power_off; goto fifo_rate_fail_power_off;
pm_runtime_mark_last_busy(pdev);
fifo_rate_fail_power_off: fifo_rate_fail_power_off:
result |= inv_mpu6050_set_power_itg(st, false); pm_runtime_put_autosuspend(pdev);
fifo_rate_fail_unlock: fifo_rate_fail_unlock:
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
if (result) if (result)
...@@ -1385,6 +1377,14 @@ static void inv_mpu_core_disable_regulator_action(void *_data) ...@@ -1385,6 +1377,14 @@ static void inv_mpu_core_disable_regulator_action(void *_data)
inv_mpu_core_disable_regulator_vddio(st); inv_mpu_core_disable_regulator_vddio(st);
} }
static void inv_mpu_pm_disable(void *data)
{
struct device *dev = data;
pm_runtime_put_sync_suspend(dev);
pm_runtime_disable(dev);
}
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type) int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
{ {
...@@ -1409,7 +1409,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -1409,7 +1409,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
mutex_init(&st->lock); mutex_init(&st->lock);
st->chip_type = chip_type; st->chip_type = chip_type;
st->powerup_count = 0;
st->irq = irq; st->irq = irq;
st->map = regmap; st->map = regmap;
...@@ -1521,8 +1520,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -1521,8 +1520,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
goto error_power_off; goto error_power_off;
} }
/* chip init is done, turning off */ /* chip init is done, turning on runtime power management */
result = inv_mpu6050_set_power_itg(st, false); result = pm_runtime_set_active(dev);
if (result)
goto error_power_off;
pm_runtime_get_noresume(dev);
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, INV_MPU6050_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
pm_runtime_put(dev);
result = devm_add_action_or_reset(dev, inv_mpu_pm_disable, dev);
if (result) if (result)
return result; return result;
...@@ -1590,11 +1597,10 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -1590,11 +1597,10 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
} }
EXPORT_SYMBOL_GPL(inv_mpu_core_probe); EXPORT_SYMBOL_GPL(inv_mpu_core_probe);
#ifdef CONFIG_PM_SLEEP static int __maybe_unused inv_mpu_resume(struct device *dev)
static int inv_mpu_resume(struct device *dev)
{ {
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev)); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result; int result;
mutex_lock(&st->lock); mutex_lock(&st->lock);
...@@ -1603,27 +1609,101 @@ static int inv_mpu_resume(struct device *dev) ...@@ -1603,27 +1609,101 @@ static int inv_mpu_resume(struct device *dev)
goto out_unlock; goto out_unlock;
result = inv_mpu6050_set_power_itg(st, true); result = inv_mpu6050_set_power_itg(st, true);
if (result)
goto out_unlock;
result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors);
if (result)
goto out_unlock;
if (iio_buffer_enabled(indio_dev))
result = inv_mpu6050_prepare_fifo(st, true);
out_unlock: out_unlock:
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
return result; return result;
} }
static int inv_mpu_suspend(struct device *dev) static int __maybe_unused inv_mpu_suspend(struct device *dev)
{ {
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev)); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result; int result;
mutex_lock(&st->lock); mutex_lock(&st->lock);
if (iio_buffer_enabled(indio_dev)) {
result = inv_mpu6050_prepare_fifo(st, false);
if (result)
goto out_unlock;
}
st->suspended_sensors = 0;
if (st->chip_config.accl_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
if (st->chip_config.gyro_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_GYRO;
if (st->chip_config.temp_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_TEMP;
if (st->chip_config.magn_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_MAGN;
result = inv_mpu6050_switch_engine(st, false, st->suspended_sensors);
if (result)
goto out_unlock;
result = inv_mpu6050_set_power_itg(st, false); result = inv_mpu6050_set_power_itg(st, false);
if (result)
goto out_unlock;
inv_mpu_core_disable_regulator_vddio(st); inv_mpu_core_disable_regulator_vddio(st);
out_unlock:
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
return result; return result;
} }
#endif /* CONFIG_PM_SLEEP */
SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); static int __maybe_unused inv_mpu_runtime_suspend(struct device *dev)
{
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
unsigned int sensors;
int ret;
mutex_lock(&st->lock);
sensors = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO |
INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN;
ret = inv_mpu6050_switch_engine(st, false, sensors);
if (ret)
goto out_unlock;
ret = inv_mpu6050_set_power_itg(st, false);
if (ret)
goto out_unlock;
inv_mpu_core_disable_regulator_vddio(st);
out_unlock:
mutex_unlock(&st->lock);
return ret;
}
static int __maybe_unused inv_mpu_runtime_resume(struct device *dev)
{
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
int ret;
ret = inv_mpu_core_enable_regulator_vddio(st);
if (ret)
return ret;
return inv_mpu6050_set_power_itg(st, true);
}
const struct dev_pm_ops inv_mpu_pmops = {
SET_SYSTEM_SLEEP_PM_OPS(inv_mpu_suspend, inv_mpu_resume)
SET_RUNTIME_PM_OPS(inv_mpu_runtime_suspend, inv_mpu_runtime_resume, NULL)
};
EXPORT_SYMBOL_GPL(inv_mpu_pmops); EXPORT_SYMBOL_GPL(inv_mpu_pmops);
MODULE_AUTHOR("Invensense Corporation"); MODULE_AUTHOR("Invensense Corporation");
......
...@@ -164,6 +164,7 @@ struct inv_mpu6050_hw { ...@@ -164,6 +164,7 @@ struct inv_mpu6050_hw {
* @magn_disabled: magnetometer disabled for backward compatibility reason. * @magn_disabled: magnetometer disabled for backward compatibility reason.
* @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss. * @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss.
* @magn_orient: magnetometer sensor chip orientation if available. * @magn_orient: magnetometer sensor chip orientation if available.
* @suspended_sensors: sensors mask of sensors turned off for suspend
*/ */
struct inv_mpu6050_state { struct inv_mpu6050_state {
struct mutex lock; struct mutex lock;
...@@ -174,7 +175,6 @@ struct inv_mpu6050_state { ...@@ -174,7 +175,6 @@ struct inv_mpu6050_state {
enum inv_devices chip_type; enum inv_devices chip_type;
struct i2c_mux_core *muxc; struct i2c_mux_core *muxc;
struct i2c_client *mux_client; struct i2c_client *mux_client;
unsigned int powerup_count;
struct inv_mpu6050_platform_data plat_data; struct inv_mpu6050_platform_data plat_data;
struct iio_mount_matrix orientation; struct iio_mount_matrix orientation;
struct regmap *map; struct regmap *map;
...@@ -189,6 +189,7 @@ struct inv_mpu6050_state { ...@@ -189,6 +189,7 @@ struct inv_mpu6050_state {
bool magn_disabled; bool magn_disabled;
s32 magn_raw_to_gauss[3]; s32 magn_raw_to_gauss[3];
struct iio_mount_matrix magn_orient; struct iio_mount_matrix magn_orient;
unsigned int suspended_sensors;
}; };
/*register and associated bit definition*/ /*register and associated bit definition*/
...@@ -312,6 +313,7 @@ struct inv_mpu6050_state { ...@@ -312,6 +313,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_ACCEL_UP_TIME 20 #define INV_MPU6050_ACCEL_UP_TIME 20
#define INV_MPU6050_GYRO_UP_TIME 35 #define INV_MPU6050_GYRO_UP_TIME 35
#define INV_MPU6050_GYRO_DOWN_TIME 150 #define INV_MPU6050_GYRO_DOWN_TIME 150
#define INV_MPU6050_SUSPEND_DELAY_MS 2000
/* delay time in microseconds */ /* delay time in microseconds */
#define INV_MPU6050_REG_UP_TIME_MIN 5000 #define INV_MPU6050_REG_UP_TIME_MIN 5000
...@@ -439,7 +441,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable); ...@@ -439,7 +441,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable);
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
unsigned int mask); unsigned int mask);
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val); int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
int inv_mpu_acpi_create_mux_client(struct i2c_client *client); int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
void inv_mpu_acpi_delete_mux_client(struct i2c_client *client); void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (C) 2012 Invensense, Inc. * Copyright (C) 2012 Invensense, Inc.
*/ */
#include <linux/pm_runtime.h>
#include "inv_mpu_iio.h" #include "inv_mpu_iio.h"
static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev) static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
...@@ -156,41 +157,43 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable) ...@@ -156,41 +157,43 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
struct device *pdev = regmap_get_device(st->map);
unsigned int scan; unsigned int scan;
int result; int result;
scan = inv_scan_query(indio_dev);
if (enable) { if (enable) {
result = inv_mpu6050_set_power_itg(st, true); scan = inv_scan_query(indio_dev);
if (result) result = pm_runtime_get_sync(pdev);
if (result < 0) {
pm_runtime_put_noidle(pdev);
return result; return result;
}
/*
* In case autosuspend didn't trigger, turn off first not
* required sensors.
*/
result = inv_mpu6050_switch_engine(st, false, ~scan);
if (result)
goto error_power_off;
result = inv_mpu6050_switch_engine(st, true, scan); result = inv_mpu6050_switch_engine(st, true, scan);
if (result) if (result)
goto error_power_off; goto error_power_off;
st->skip_samples = inv_compute_skip_samples(st); st->skip_samples = inv_compute_skip_samples(st);
result = inv_mpu6050_prepare_fifo(st, true); result = inv_mpu6050_prepare_fifo(st, true);
if (result) if (result)
goto error_sensors_off; goto error_power_off;
} else { } else {
result = inv_mpu6050_prepare_fifo(st, false); result = inv_mpu6050_prepare_fifo(st, false);
if (result)
goto error_sensors_off;
result = inv_mpu6050_switch_engine(st, false, scan);
if (result)
goto error_power_off;
result = inv_mpu6050_set_power_itg(st, false);
if (result) if (result)
goto error_power_off; goto error_power_off;
pm_runtime_mark_last_busy(pdev);
pm_runtime_put_autosuspend(pdev);
} }
return 0; return 0;
error_sensors_off:
inv_mpu6050_switch_engine(st, false, scan);
error_power_off: error_power_off:
inv_mpu6050_set_power_itg(st, false); pm_runtime_put_autosuspend(pdev);
return result; return result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment