aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-04-01 12:56:31 -0400
committerJiri Kosina <jkosina@suse.cz>2014-04-01 12:56:31 -0400
commitba04a57b4acd05a764471b2accd02000f6641881 (patch)
tree1d33fff219a72bb11a5a5d5f9c3dc2accfd19b06 /drivers/hid
parentee5f68e6c2f183e6aade0e9c57af13d5eff44f2f (diff)
parent34f439e4afcdf4bdb42fda62428535a843bca02d (diff)
Merge branch 'for-3.15/i2c-hid' into for-linus
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c68
1 files changed, 57 insertions, 11 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index ce68a120ba26..c121990c6beb 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -25,6 +25,7 @@
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/pm.h> 27#include <linux/pm.h>
28#include <linux/pm_runtime.h>
28#include <linux/device.h> 29#include <linux/device.h>
29#include <linux/wait.h> 30#include <linux/wait.h>
30#include <linux/err.h> 31#include <linux/err.h>
@@ -454,10 +455,18 @@ static void i2c_hid_init_reports(struct hid_device *hid)
454 return; 455 return;
455 } 456 }
456 457
458 /*
459 * The device must be powered on while we fetch initial reports
460 * from it.
461 */
462 pm_runtime_get_sync(&client->dev);
463
457 list_for_each_entry(report, 464 list_for_each_entry(report,
458 &hid->report_enum[HID_FEATURE_REPORT].report_list, list) 465 &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
459 i2c_hid_init_report(report, inbuf, ihid->bufsize); 466 i2c_hid_init_report(report, inbuf, ihid->bufsize);
460 467
468 pm_runtime_put(&client->dev);
469
461 kfree(inbuf); 470 kfree(inbuf);
462} 471}
463 472
@@ -703,8 +712,8 @@ static int i2c_hid_open(struct hid_device *hid)
703 712
704 mutex_lock(&i2c_hid_open_mut); 713 mutex_lock(&i2c_hid_open_mut);
705 if (!hid->open++) { 714 if (!hid->open++) {
706 ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); 715 ret = pm_runtime_get_sync(&client->dev);
707 if (ret) { 716 if (ret < 0) {
708 hid->open--; 717 hid->open--;
709 goto done; 718 goto done;
710 } 719 }
@@ -712,7 +721,7 @@ static int i2c_hid_open(struct hid_device *hid)
712 } 721 }
713done: 722done:
714 mutex_unlock(&i2c_hid_open_mut); 723 mutex_unlock(&i2c_hid_open_mut);
715 return ret; 724 return ret < 0 ? ret : 0;
716} 725}
717 726
718static void i2c_hid_close(struct hid_device *hid) 727static void i2c_hid_close(struct hid_device *hid)
@@ -729,7 +738,7 @@ static void i2c_hid_close(struct hid_device *hid)
729 clear_bit(I2C_HID_STARTED, &ihid->flags); 738 clear_bit(I2C_HID_STARTED, &ihid->flags);
730 739
731 /* Save some power */ 740 /* Save some power */
732 i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); 741 pm_runtime_put(&client->dev);
733 } 742 }
734 mutex_unlock(&i2c_hid_open_mut); 743 mutex_unlock(&i2c_hid_open_mut);
735} 744}
@@ -738,19 +747,18 @@ static int i2c_hid_power(struct hid_device *hid, int lvl)
738{ 747{
739 struct i2c_client *client = hid->driver_data; 748 struct i2c_client *client = hid->driver_data;
740 struct i2c_hid *ihid = i2c_get_clientdata(client); 749 struct i2c_hid *ihid = i2c_get_clientdata(client);
741 int ret = 0;
742 750
743 i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl); 751 i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
744 752
745 switch (lvl) { 753 switch (lvl) {
746 case PM_HINT_FULLON: 754 case PM_HINT_FULLON:
747 ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); 755 pm_runtime_get_sync(&client->dev);
748 break; 756 break;
749 case PM_HINT_NORMAL: 757 case PM_HINT_NORMAL:
750 ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); 758 pm_runtime_put(&client->dev);
751 break; 759 break;
752 } 760 }
753 return ret; 761 return 0;
754} 762}
755 763
756static struct hid_ll_driver i2c_hid_ll_driver = { 764static struct hid_ll_driver i2c_hid_ll_driver = {
@@ -987,13 +995,17 @@ static int i2c_hid_probe(struct i2c_client *client,
987 if (ret < 0) 995 if (ret < 0)
988 goto err; 996 goto err;
989 997
998 pm_runtime_get_noresume(&client->dev);
999 pm_runtime_set_active(&client->dev);
1000 pm_runtime_enable(&client->dev);
1001
990 ret = i2c_hid_fetch_hid_descriptor(ihid); 1002 ret = i2c_hid_fetch_hid_descriptor(ihid);
991 if (ret < 0) 1003 if (ret < 0)
992 goto err; 1004 goto err_pm;
993 1005
994 ret = i2c_hid_init_irq(client); 1006 ret = i2c_hid_init_irq(client);
995 if (ret < 0) 1007 if (ret < 0)
996 goto err; 1008 goto err_pm;
997 1009
998 hid = hid_allocate_device(); 1010 hid = hid_allocate_device();
999 if (IS_ERR(hid)) { 1011 if (IS_ERR(hid)) {
@@ -1024,6 +1036,7 @@ static int i2c_hid_probe(struct i2c_client *client,
1024 goto err_mem_free; 1036 goto err_mem_free;
1025 } 1037 }
1026 1038
1039 pm_runtime_put(&client->dev);
1027 return 0; 1040 return 0;
1028 1041
1029err_mem_free: 1042err_mem_free:
@@ -1032,6 +1045,10 @@ err_mem_free:
1032err_irq: 1045err_irq:
1033 free_irq(client->irq, ihid); 1046 free_irq(client->irq, ihid);
1034 1047
1048err_pm:
1049 pm_runtime_put_noidle(&client->dev);
1050 pm_runtime_disable(&client->dev);
1051
1035err: 1052err:
1036 i2c_hid_free_buffers(ihid); 1053 i2c_hid_free_buffers(ihid);
1037 kfree(ihid); 1054 kfree(ihid);
@@ -1043,6 +1060,11 @@ static int i2c_hid_remove(struct i2c_client *client)
1043 struct i2c_hid *ihid = i2c_get_clientdata(client); 1060 struct i2c_hid *ihid = i2c_get_clientdata(client);
1044 struct hid_device *hid; 1061 struct hid_device *hid;
1045 1062
1063 pm_runtime_get_sync(&client->dev);
1064 pm_runtime_disable(&client->dev);
1065 pm_runtime_set_suspended(&client->dev);
1066 pm_runtime_put_noidle(&client->dev);
1067
1046 hid = ihid->hid; 1068 hid = ihid->hid;
1047 hid_destroy_device(hid); 1069 hid_destroy_device(hid);
1048 1070
@@ -1088,7 +1110,31 @@ static int i2c_hid_resume(struct device *dev)
1088} 1110}
1089#endif 1111#endif
1090 1112
1091static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume); 1113#ifdef CONFIG_PM_RUNTIME
1114static int i2c_hid_runtime_suspend(struct device *dev)
1115{
1116 struct i2c_client *client = to_i2c_client(dev);
1117
1118 i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
1119 disable_irq(client->irq);
1120 return 0;
1121}
1122
1123static int i2c_hid_runtime_resume(struct device *dev)
1124{
1125 struct i2c_client *client = to_i2c_client(dev);
1126
1127 enable_irq(client->irq);
1128 i2c_hid_set_power(client, I2C_HID_PWR_ON);
1129 return 0;
1130}
1131#endif
1132
1133static const struct dev_pm_ops i2c_hid_pm = {
1134 SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
1135 SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
1136 NULL)
1137};
1092 1138
1093static const struct i2c_device_id i2c_hid_id_table[] = { 1139static const struct i2c_device_id i2c_hid_id_table[] = {
1094 { "hid", 0 }, 1140 { "hid", 0 },