aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/ideapad_acpi.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad_acpi.c
index 798496353e8..c87693c7dde 100644
--- a/drivers/platform/x86/ideapad_acpi.c
+++ b/drivers/platform/x86/ideapad_acpi.c
@@ -49,6 +49,115 @@ static struct {
49 { "ideapad_killsw", RFKILL_TYPE_WLAN } 49 { "ideapad_killsw", RFKILL_TYPE_WLAN }
50}; 50};
51 51
52/*
53 * ACPI Helpers
54 */
55#define IDEAPAD_EC_TIMEOUT (100) /* in ms */
56
57static int read_method_int(acpi_handle handle, const char *method, int *val)
58{
59 acpi_status status;
60 unsigned long long result;
61
62 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
63 if (ACPI_FAILURE(status)) {
64 *val = -1;
65 return -1;
66 } else {
67 *val = result;
68 return 0;
69 }
70}
71
72static int method_vpcr(acpi_handle handle, int cmd, int *ret)
73{
74 acpi_status status;
75 unsigned long long result;
76 struct acpi_object_list params;
77 union acpi_object in_obj;
78
79 params.count = 1;
80 params.pointer = &in_obj;
81 in_obj.type = ACPI_TYPE_INTEGER;
82 in_obj.integer.value = cmd;
83
84 status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
85
86 if (ACPI_FAILURE(status)) {
87 *ret = -1;
88 return -1;
89 } else {
90 *ret = result;
91 return 0;
92 }
93}
94
95static int method_vpcw(acpi_handle handle, int cmd, int data)
96{
97 struct acpi_object_list params;
98 union acpi_object in_obj[2];
99 acpi_status status;
100
101 params.count = 2;
102 params.pointer = in_obj;
103 in_obj[0].type = ACPI_TYPE_INTEGER;
104 in_obj[0].integer.value = cmd;
105 in_obj[1].type = ACPI_TYPE_INTEGER;
106 in_obj[1].integer.value = data;
107
108 status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
109 if (status != AE_OK)
110 return -1;
111 return 0;
112}
113
114static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
115{
116 int val;
117 unsigned long int end_jiffies;
118
119 if (method_vpcw(handle, 1, cmd))
120 return -1;
121
122 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
123 time_before(jiffies, end_jiffies);) {
124 schedule();
125 if (method_vpcr(handle, 1, &val))
126 return -1;
127 if (val == 0) {
128 if (method_vpcr(handle, 0, &val))
129 return -1;
130 *data = val;
131 return 0;
132 }
133 }
134 pr_err("timeout in read_ec_cmd\n");
135 return -1;
136}
137
138static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
139{
140 int val;
141 unsigned long int end_jiffies;
142
143 if (method_vpcw(handle, 0, data))
144 return -1;
145 if (method_vpcw(handle, 1, cmd))
146 return -1;
147
148 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
149 time_before(jiffies, end_jiffies);) {
150 schedule();
151 if (method_vpcr(handle, 1, &val))
152 return -1;
153 if (val == 0)
154 return 0;
155 }
156 pr_err("timeout in write_ec_cmd\n");
157 return -1;
158}
159/* the above is ACPI helpers */
160
52static int ideapad_dev_exists(int device) 161static int ideapad_dev_exists(int device)
53{ 162{
54 acpi_status status; 163 acpi_status status;