mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
input: mpu3050: add enable/disable sysfs attribute
allow sensor HAL control the power state of gyro sensor, so that sensor is disabled when not used. Change-Id: Ib9f8e9761ea518534ffcd06f30de4b8f1f198687 Signed-off-by: Orkhan Karimov <okarimov@codeaurora.org>
This commit is contained in:
parent
9d39b405d9
commit
fb46cdf3bf
1 changed files with 58 additions and 21 deletions
|
@ -124,6 +124,7 @@ struct mpu3050_sensor {
|
|||
u32 use_poll;
|
||||
u32 poll_interval;
|
||||
u32 dlpf_index;
|
||||
atomic_t enabled;
|
||||
};
|
||||
|
||||
struct sensor_regulator {
|
||||
|
@ -154,6 +155,10 @@ static struct dlpf_cfg_tb dlpf_table[] = {
|
|||
{0, 256, 8},
|
||||
};
|
||||
|
||||
static void mpu3050_set_power_mode(struct i2c_client *client, u8 val);
|
||||
static int mpu3050_start(struct mpu3050_sensor *sensor);
|
||||
static void mpu3050_stop(struct mpu3050_sensor *sensor);
|
||||
|
||||
static u8 interval_to_dlpf_cfg(u32 interval)
|
||||
{
|
||||
u32 sample_rate = 1000 / interval;
|
||||
|
@ -293,13 +298,45 @@ static ssize_t mpu3050_attr_set_polling_rate(struct device *dev,
|
|||
return size;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t mpu3050_attr_get_enable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
|
||||
int val = atomic_read(&sensor->enabled);
|
||||
return snprintf(buf, sizeof(val) + 2, "%d\n", val);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t mpu3050_attr_set_enable(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 10, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
mpu3050_start(sensor);
|
||||
else
|
||||
mpu3050_stop(sensor);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct device_attribute attributes[] = {
|
||||
|
||||
__ATTR(pollrate_ms, 0664,
|
||||
mpu3050_attr_get_polling_rate,
|
||||
mpu3050_attr_set_polling_rate),
|
||||
__ATTR(enable, 0664,
|
||||
mpu3050_attr_get_enable,
|
||||
mpu3050_attr_set_enable),
|
||||
};
|
||||
|
||||
|
||||
static int create_sysfs_interfaces(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
@ -409,16 +446,15 @@ static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
|
|||
}
|
||||
|
||||
/**
|
||||
* mpu3050_input_open - called on input event open
|
||||
* @input: input dev of opened device
|
||||
* mpu3050_start - called when sensor is enabled via sysfs
|
||||
* @sensor: the sensor
|
||||
*
|
||||
* The function gets called when the sensor is enabled via sysfs.
|
||||
* Interrupts will be enabled and the device will be ready to provide data.
|
||||
*
|
||||
* The input layer calls this function when input event is opened. The
|
||||
* function will push the device to resume. Then, the device is ready
|
||||
* to provide data.
|
||||
*/
|
||||
static int mpu3050_input_open(struct input_dev *input)
|
||||
static int mpu3050_start(struct mpu3050_sensor *sensor)
|
||||
{
|
||||
struct mpu3050_sensor *sensor = input_get_drvdata(input);
|
||||
int error;
|
||||
|
||||
pm_runtime_get_sync(sensor->dev);
|
||||
|
@ -440,16 +476,15 @@ static int mpu3050_input_open(struct input_dev *input)
|
|||
}
|
||||
|
||||
/**
|
||||
* mpu3050_input_close - called on input event close
|
||||
* @input: input dev of closed device
|
||||
* mpu3050_stop - called when sensor is disabled via sysfs
|
||||
* @sensor: the sensor
|
||||
*
|
||||
* The function gets called when the sensor is disabled via sysfs.
|
||||
* Device will be pushed to suspend mode.
|
||||
*
|
||||
* The input layer calls this function when input event is closed. The
|
||||
* function will push the device to suspend.
|
||||
*/
|
||||
static void mpu3050_input_close(struct input_dev *input)
|
||||
static void mpu3050_stop(struct mpu3050_sensor *sensor)
|
||||
{
|
||||
struct mpu3050_sensor *sensor = input_get_drvdata(input);
|
||||
|
||||
if (sensor->use_poll)
|
||||
cancel_delayed_work_sync(&sensor->input_work);
|
||||
|
||||
|
@ -595,6 +630,7 @@ static int __devinit mpu3050_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
mpu3050_set_power_mode(client, 1);
|
||||
atomic_set(&sensor->enabled, 1);
|
||||
msleep(10);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
|
||||
|
@ -614,9 +650,6 @@ static int __devinit mpu3050_probe(struct i2c_client *client,
|
|||
idev->id.bustype = BUS_I2C;
|
||||
idev->dev.parent = &client->dev;
|
||||
|
||||
idev->open = mpu3050_input_open;
|
||||
idev->close = mpu3050_input_close;
|
||||
|
||||
__set_bit(EV_ABS, idev->evbit);
|
||||
input_set_abs_params(idev, ABS_X,
|
||||
MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
|
||||
|
@ -739,8 +772,10 @@ static int __devexit mpu3050_remove(struct i2c_client *client)
|
|||
static int mpu3050_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
mpu3050_set_power_mode(client, 0);
|
||||
struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
|
||||
if (atomic_cmpxchg(&sensor->enabled, 1, 0)) {
|
||||
mpu3050_set_power_mode (sensor->client, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -754,8 +789,10 @@ static int mpu3050_suspend(struct device *dev)
|
|||
static int mpu3050_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
mpu3050_set_power_mode(client, 1);
|
||||
struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
|
||||
if (!atomic_cmpxchg(&sensor->enabled, 0, 1)) {
|
||||
mpu3050_set_power_mode (sensor->client, 1);
|
||||
}
|
||||
msleep(100); /* wait for gyro chip resume */
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue