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

Reply via email to