aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/ideapad_acpi.c53
1 files changed, 17 insertions, 36 deletions
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad_acpi.c
index e45fc50b93dc..09f6ce6b378d 100644
--- a/drivers/platform/x86/ideapad_acpi.c
+++ b/drivers/platform/x86/ideapad_acpi.c
@@ -160,32 +160,6 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
160} 160}
161/* the above is ACPI helpers */ 161/* the above is ACPI helpers */
162 162
163static int ideapad_dev_get_state(int device)
164{
165 acpi_status status;
166 union acpi_object in_param;
167 struct acpi_object_list input = { 1, &in_param };
168 struct acpi_buffer output;
169 union acpi_object out_obj;
170
171 output.length = sizeof(out_obj);
172 output.pointer = &out_obj;
173
174 in_param.type = ACPI_TYPE_INTEGER;
175 in_param.integer.value = device + 1;
176
177 status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output);
178 if (ACPI_FAILURE(status)) {
179 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status);
180 return -ENODEV;
181 }
182 if (out_obj.type != ACPI_TYPE_INTEGER) {
183 printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n");
184 return -ENODEV;
185 }
186 return out_obj.integer.value;
187}
188
189static int ideapad_dev_set_state(int device, int state) 163static int ideapad_dev_set_state(int device, int state)
190{ 164{
191 acpi_status status; 165 acpi_status status;
@@ -253,32 +227,39 @@ static struct rfkill_ops ideapad_rfk_ops = {
253static void ideapad_sync_rfk_state(struct acpi_device *adevice) 227static void ideapad_sync_rfk_state(struct acpi_device *adevice)
254{ 228{
255 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 229 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
256 int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW); 230 acpi_handle handle = priv->handle;
231 unsigned long hw_blocked;
257 int i; 232 int i;
258 233
259 rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], hw_blocked); 234 if (read_ec_data(handle, 0x23, &hw_blocked))
260 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
261 if (priv->rfk[i])
262 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
263 if (hw_blocked)
264 return; 235 return;
236 hw_blocked = !hw_blocked;
265 237
266 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) 238 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
267 if (priv->rfk[i]) 239 if (priv->rfk[i])
268 rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i)); 240 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
269} 241}
270 242
271static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) 243static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
272{ 244{
273 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 245 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
274 int ret; 246 int ret;
247 unsigned long sw_blocked;
275 248
276 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev, 249 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
277 ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops, 250 ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
278 (void *)(long)dev); 251 (void *)(long)dev);
279 if (!priv->rfk[dev]) 252 if (!priv->rfk[dev])
280 return -ENOMEM; 253 return -ENOMEM;
281 254
255 if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1,
256 &sw_blocked)) {
257 rfkill_init_sw_state(priv->rfk[dev], 0);
258 } else {
259 sw_blocked = !sw_blocked;
260 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
261 }
262
282 ret = rfkill_register(priv->rfk[dev]); 263 ret = rfkill_register(priv->rfk[dev]);
283 if (ret) { 264 if (ret) {
284 rfkill_destroy(priv->rfk[dev]); 265 rfkill_destroy(priv->rfk[dev]);