Add support for runtime PM feature, and remove the old user controlled power functions.
Signed-off-by: Hong Liu <[email protected]> --- drivers/staging/mfld-sensors/ak8974.c | 124 +++++++++++++++++---------------- 1 files changed, 64 insertions(+), 60 deletions(-) diff --git a/drivers/staging/mfld-sensors/ak8974.c b/drivers/staging/mfld-sensors/ak8974.c index 58057a1..d0ecff6 100644 --- a/drivers/staging/mfld-sensors/ak8974.c +++ b/drivers/staging/mfld-sensors/ak8974.c @@ -28,7 +28,7 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/sysfs.h> -#include <linux/hwmon-sysfs.h> +#include <linux/pm_runtime.h> MODULE_AUTHOR("KalhanTrisal,Anantha Narayanan<[email protected]>"); MODULE_DESCRIPTION("ak8974 Compass Driver"); @@ -45,80 +45,49 @@ MODULE_LICENSE("GPL v2"); #define DATA_ZM 0x15 #define STAT_REG 0x18 #define CNTL_1 0x1B + #define CNTL1_MODE_ACTIVE (1 << 7) + #define CNTL1_STAT_FORCE (1 << 1) #define CNTL_2 0x1C #define CNTL_3 0x1D + #define CNTL3_SOFT_RESET (1 << 7) + #define CNTL3_START_MEASURE (1 << 6) #define PRET_REG 0x30 struct compass_data { - bool needresume; struct mutex write_lock; }; -static ssize_t power_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) +static void set_power_state(struct i2c_client *client, bool on) { - unsigned int ret_val; - struct i2c_client *client = to_i2c_client(dev); - - ret_val = i2c_smbus_read_byte_data(client, CNTL_1); - if (ret_val < 0) - dev_warn(dev, "failed power mode read\n"); - - return sprintf(buf, "%d\n", ((char)ret_val & 0x80) >> 7); -} - -static void set_power_state(struct i2c_client *client, bool on_off) -{ - char read_cntl1 = 0; struct compass_data *data = i2c_get_clientdata(client); + u8 cntl1; mutex_lock(&data->write_lock); - read_cntl1 = i2c_smbus_read_byte_data(client, CNTL_1); - if (on_off) - read_cntl1 = (read_cntl1 | 0x80); + cntl1 = i2c_smbus_read_byte_data(client, CNTL_1); + if (on) + cntl1 |= CNTL1_MODE_ACTIVE; else - read_cntl1 = (read_cntl1 & 0x7F); + cntl1 &= ~CNTL1_MODE_ACTIVE; - if (i2c_smbus_write_byte_data(client, CNTL_1, read_cntl1) < 0) + if (i2c_smbus_write_byte_data(client, CNTL_1, cntl1) < 0) dev_warn(&client->dev, "failed power state write\n"); mutex_unlock(&data->write_lock); } -static ssize_t power_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long set_val; - struct i2c_client *client = to_i2c_client(dev); - struct compass_data *data = i2c_get_clientdata(client); - - if (strict_strtoul(buf, 10, &set_val)) - return -EINVAL; - - if (set_val == 1) { - set_power_state(client, true); - data->needresume = true; - } else if (set_val == 0) { - set_power_state(client, false); - data->needresume = false; - } else - return -EINVAL; - - return count; -} - static ssize_t curr_xyz_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned short x, y, z; - unsigned char temp; struct i2c_client *client = to_i2c_client(dev); struct compass_data *data = i2c_get_clientdata(client); + unsigned short x, y, z; + u8 temp; + pm_runtime_get_sync(dev); mutex_lock(&data->write_lock); - if (i2c_smbus_write_byte_data(client, CNTL_3, 0x40) < 0) + if (i2c_smbus_write_byte_data(client, CNTL_3, CNTL3_START_MEASURE) < 0) dev_warn(dev, "failed xyz contrl3 register write\n"); /* wait for data ready */ @@ -136,26 +105,30 @@ static ssize_t curr_xyz_show(struct device *dev, z = z << 8 | temp; mutex_unlock(&data->write_lock); + pm_runtime_put_sync(dev); return sprintf(buf, "%x:%x:%x\n", x, y, z); } -static void ps_set_default_config(struct i2c_client *client) +/* change to active mode and do some default config */ +static void set_default_config(struct i2c_client *client) { - /*Power ON and set default*/ - if (i2c_smbus_write_byte_data(client, CNTL_1, 0x82) < 0) + u8 val; + + if (i2c_smbus_write_byte_data(client, CNTL_1, CNTL1_MODE_ACTIVE) < 0) dev_warn(&client->dev, "failed default power on write\n"); + val = i2c_smbus_read_byte_data(client, CNTL_1); + if (i2c_smbus_write_byte_data(client, CNTL_1, val | CNTL1_STAT_FORCE)) + dev_warn(&client->dev, "failed to set force state\n"); + if (i2c_smbus_write_byte_data(client, PRET_REG, 0x00) < 0) dev_warn(&client->dev, "failed default control write\n"); } -static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, - power_mode_show, power_mode_store); static DEVICE_ATTR(curr_pos, S_IRUGO, curr_xyz_show, NULL); static struct attribute *mid_att_compass[] = { - &dev_attr_power_state.attr, &dev_attr_curr_pos.attr, NULL }; @@ -185,9 +158,12 @@ static int ak8974_probe(struct i2c_client *client, } dev_info(&client->dev, "compass chip found \n"); - ps_set_default_config(client); - data->needresume = true; + set_default_config(client); mutex_init(&data->write_lock); + + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + return 0; compass_error1: @@ -196,11 +172,19 @@ compass_error1: return res; } -static int ak8974_remove(struct i2c_client *client) +static int __devexit ak8974_remove(struct i2c_client *client) { struct compass_data *data = i2c_get_clientdata(client); + pm_runtime_get_sync(&client->dev); + + set_power_state(client, false); sysfs_remove_group(&client->dev.kobj, &m_compass_gr); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + kfree(data); return 0; } @@ -213,13 +197,32 @@ static int ak8974_suspend(struct i2c_client *client, pm_message_t mesg) static int ak8974_resume(struct i2c_client *client) { - struct compass_data *data = i2c_get_clientdata(client); + set_default_config(client); + + return 0; +} + +static int ak8974_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + set_power_state(client, false); + return 0; +} - if (data->needresume == true) - set_power_state(client, true); +static int ak8974_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + set_power_state(client, true); return 0; } +static const struct dev_pm_ops ak8974_pm_ops = { + .runtime_suspend = ak8974_runtime_suspend, + .runtime_resume = ak8974_runtime_resume, +}; + static struct i2c_device_id ak8974_id[] = { { "ak8974", 0 }, { } @@ -228,9 +231,10 @@ static struct i2c_device_id ak8974_id[] = { static struct i2c_driver ak8974_driver = { .driver = { .name = "ak8974", + .pm = &ak8974_pm_ops, }, .probe = ak8974_probe, - .remove = ak8974_remove, + .remove = __devexit_p(ak8974_remove), .suspend = ak8974_suspend, .resume = ak8974_resume, .id_table = ak8974_id, -- 1.7.2.3 _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
