#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/err.h>
                return;
        }
 
+       /*
+        * The device must be powered on while we fetch initial reports
+        * from it.
+        */
+       pm_runtime_get_sync(&client->dev);
+
        list_for_each_entry(report,
                &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
                i2c_hid_init_report(report, inbuf, ihid->bufsize);
 
+       pm_runtime_put(&client->dev);
+
        kfree(inbuf);
 }
 
 
        mutex_lock(&i2c_hid_open_mut);
        if (!hid->open++) {
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
-               if (ret) {
+               ret = pm_runtime_get_sync(&client->dev);
+               if (ret < 0) {
                        hid->open--;
                        goto done;
                }
        }
 done:
        mutex_unlock(&i2c_hid_open_mut);
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 static void i2c_hid_close(struct hid_device *hid)
                clear_bit(I2C_HID_STARTED, &ihid->flags);
 
                /* Save some power */
-               i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               pm_runtime_put(&client->dev);
        }
        mutex_unlock(&i2c_hid_open_mut);
 }
 {
        struct i2c_client *client = hid->driver_data;
        struct i2c_hid *ihid = i2c_get_clientdata(client);
-       int ret = 0;
 
        i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
 
        switch (lvl) {
        case PM_HINT_FULLON:
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+               pm_runtime_get_sync(&client->dev);
                break;
        case PM_HINT_NORMAL:
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               pm_runtime_put(&client->dev);
                break;
        }
-       return ret;
+       return 0;
 }
 
 static struct hid_ll_driver i2c_hid_ll_driver = {
        if (ret < 0)
                goto err;
 
+       pm_runtime_get_noresume(&client->dev);
+       pm_runtime_set_active(&client->dev);
+       pm_runtime_enable(&client->dev);
+
        ret = i2c_hid_fetch_hid_descriptor(ihid);
        if (ret < 0)
-               goto err;
+               goto err_pm;
 
        ret = i2c_hid_init_irq(client);
        if (ret < 0)
-               goto err;
+               goto err_pm;
 
        hid = hid_allocate_device();
        if (IS_ERR(hid)) {
                goto err_mem_free;
        }
 
+       pm_runtime_put(&client->dev);
        return 0;
 
 err_mem_free:
 err_irq:
        free_irq(client->irq, ihid);
 
+err_pm:
+       pm_runtime_put_noidle(&client->dev);
+       pm_runtime_disable(&client->dev);
+
 err:
        i2c_hid_free_buffers(ihid);
        kfree(ihid);
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid;
 
+       pm_runtime_get_sync(&client->dev);
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+       pm_runtime_put_noidle(&client->dev);
+
        hid = ihid->hid;
        hid_destroy_device(hid);
 
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+#ifdef CONFIG_PM_RUNTIME
+static int i2c_hid_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+       disable_irq(client->irq);
+       return 0;
+}
+
+static int i2c_hid_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       enable_irq(client->irq);
+       i2c_hid_set_power(client, I2C_HID_PWR_ON);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops i2c_hid_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
+       SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
+                          NULL)
+};
 
 static const struct i2c_device_id i2c_hid_id_table[] = {
        { "hid", 0 },