diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-07-21 07:14:01 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-09 23:52:54 -0500 |
commit | e5fbba85a7acc2626d4fe14501816811d702f3e9 (patch) | |
tree | ffc1fe9cb89268cd963f52f3552132aad8df7f79 /drivers/platform/x86/hp-wmi.c | |
parent | 22763c5cf3690a681551162c15d34d935308c8d7 (diff) |
hp-wmi: improve rfkill support
1) Add support for reading the hardware blocked state. Previously
we read a combination of the hardware and software blocked states,
reporting it as the software blocked state. This caused some
confusing behaviour.
2) The software state is persistent, mark it as such.
3) Check rfkill in the resume handler. Both the hard and soft
blocked states may change over hibernation.
Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Acked-by: Matthew Garrett <mjg@redhat.com>
Tested-by: Maciej Rutecki <maciej.rutecki@gmail.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform/x86/hp-wmi.c')
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 139 |
1 files changed, 84 insertions, 55 deletions
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index c2842171cec6..804cfdb88286 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); | |||
51 | #define HPWMI_WIRELESS_QUERY 0x5 | 51 | #define HPWMI_WIRELESS_QUERY 0x5 |
52 | #define HPWMI_HOTKEY_QUERY 0xc | 52 | #define HPWMI_HOTKEY_QUERY 0xc |
53 | 53 | ||
54 | enum hp_wmi_radio { | ||
55 | HPWMI_WIFI = 0, | ||
56 | HPWMI_BLUETOOTH = 1, | ||
57 | HPWMI_WWAN = 2, | ||
58 | }; | ||
59 | |||
54 | static int __init hp_wmi_bios_setup(struct platform_device *device); | 60 | static int __init hp_wmi_bios_setup(struct platform_device *device); |
55 | static int __exit hp_wmi_bios_remove(struct platform_device *device); | 61 | static int __exit hp_wmi_bios_remove(struct platform_device *device); |
56 | static int hp_wmi_resume_handler(struct device *device); | 62 | static int hp_wmi_resume_handler(struct device *device); |
@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void) | |||
175 | 181 | ||
176 | static int hp_wmi_set_block(void *data, bool blocked) | 182 | static int hp_wmi_set_block(void *data, bool blocked) |
177 | { | 183 | { |
178 | unsigned long b = (unsigned long) data; | 184 | enum hp_wmi_radio r = (enum hp_wmi_radio) data; |
179 | int query = BIT(b + 8) | ((!blocked) << b); | 185 | int query = BIT(r + 8) | ((!blocked) << r); |
180 | 186 | ||
181 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); | 187 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); |
182 | } | 188 | } |
@@ -185,31 +191,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = { | |||
185 | .set_block = hp_wmi_set_block, | 191 | .set_block = hp_wmi_set_block, |
186 | }; | 192 | }; |
187 | 193 | ||
188 | static bool hp_wmi_wifi_state(void) | 194 | static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) |
189 | { | ||
190 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | ||
191 | |||
192 | if (wireless & 0x100) | ||
193 | return false; | ||
194 | else | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | static bool hp_wmi_bluetooth_state(void) | ||
199 | { | 195 | { |
200 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | 196 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); |
197 | int mask = 0x200 << (r * 8); | ||
201 | 198 | ||
202 | if (wireless & 0x10000) | 199 | if (wireless & mask) |
203 | return false; | 200 | return false; |
204 | else | 201 | else |
205 | return true; | 202 | return true; |
206 | } | 203 | } |
207 | 204 | ||
208 | static bool hp_wmi_wwan_state(void) | 205 | static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) |
209 | { | 206 | { |
210 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | 207 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); |
208 | int mask = 0x800 << (r * 8); | ||
211 | 209 | ||
212 | if (wireless & 0x1000000) | 210 | if (wireless & mask) |
213 | return false; | 211 | return false; |
214 | else | 212 | else |
215 | return true; | 213 | return true; |
@@ -334,49 +332,55 @@ static void hp_wmi_notify(u32 value, void *context) | |||
334 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | 332 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
335 | static struct key_entry *key; | 333 | static struct key_entry *key; |
336 | union acpi_object *obj; | 334 | union acpi_object *obj; |
335 | int eventcode; | ||
337 | 336 | ||
338 | wmi_get_event_data(value, &response); | 337 | wmi_get_event_data(value, &response); |
339 | 338 | ||
340 | obj = (union acpi_object *)response.pointer; | 339 | obj = (union acpi_object *)response.pointer; |
341 | 340 | ||
342 | if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { | 341 | if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { |
343 | int eventcode = *((u8 *) obj->buffer.pointer); | 342 | printk(KERN_INFO "HP WMI: Unknown response received\n"); |
344 | if (eventcode == 0x4) | 343 | return; |
345 | eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, | 344 | } |
346 | 0); | 345 | |
347 | key = hp_wmi_get_entry_by_scancode(eventcode); | 346 | eventcode = *((u8 *) obj->buffer.pointer); |
348 | if (key) { | 347 | if (eventcode == 0x4) |
349 | switch (key->type) { | 348 | eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, |
350 | case KE_KEY: | 349 | 0); |
351 | input_report_key(hp_wmi_input_dev, | 350 | key = hp_wmi_get_entry_by_scancode(eventcode); |
352 | key->keycode, 1); | 351 | if (key) { |
353 | input_sync(hp_wmi_input_dev); | 352 | switch (key->type) { |
354 | input_report_key(hp_wmi_input_dev, | 353 | case KE_KEY: |
355 | key->keycode, 0); | 354 | input_report_key(hp_wmi_input_dev, |
356 | input_sync(hp_wmi_input_dev); | 355 | key->keycode, 1); |
357 | break; | 356 | input_sync(hp_wmi_input_dev); |
358 | } | 357 | input_report_key(hp_wmi_input_dev, |
359 | } else if (eventcode == 0x1) { | 358 | key->keycode, 0); |
360 | input_report_switch(hp_wmi_input_dev, SW_DOCK, | ||
361 | hp_wmi_dock_state()); | ||
362 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | ||
363 | hp_wmi_tablet_state()); | ||
364 | input_sync(hp_wmi_input_dev); | 359 | input_sync(hp_wmi_input_dev); |
365 | } else if (eventcode == 0x5) { | 360 | break; |
366 | if (wifi_rfkill) | 361 | } |
367 | rfkill_set_sw_state(wifi_rfkill, | 362 | } else if (eventcode == 0x1) { |
368 | hp_wmi_wifi_state()); | 363 | input_report_switch(hp_wmi_input_dev, SW_DOCK, |
369 | if (bluetooth_rfkill) | 364 | hp_wmi_dock_state()); |
370 | rfkill_set_sw_state(bluetooth_rfkill, | 365 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, |
371 | hp_wmi_bluetooth_state()); | 366 | hp_wmi_tablet_state()); |
372 | if (wwan_rfkill) | 367 | input_sync(hp_wmi_input_dev); |
373 | rfkill_set_sw_state(wwan_rfkill, | 368 | } else if (eventcode == 0x5) { |
374 | hp_wmi_wwan_state()); | 369 | if (wifi_rfkill) |
375 | } else | 370 | rfkill_set_states(wifi_rfkill, |
376 | printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", | 371 | hp_wmi_get_sw_state(HPWMI_WIFI), |
377 | eventcode); | 372 | hp_wmi_get_hw_state(HPWMI_WIFI)); |
373 | if (bluetooth_rfkill) | ||
374 | rfkill_set_states(bluetooth_rfkill, | ||
375 | hp_wmi_get_sw_state(HPWMI_BLUETOOTH), | ||
376 | hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); | ||
377 | if (wwan_rfkill) | ||
378 | rfkill_set_states(wwan_rfkill, | ||
379 | hp_wmi_get_sw_state(HPWMI_WWAN), | ||
380 | hp_wmi_get_hw_state(HPWMI_WWAN)); | ||
378 | } else | 381 | } else |
379 | printk(KERN_INFO "HP WMI: Unknown response received\n"); | 382 | printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", |
383 | eventcode); | ||
380 | } | 384 | } |
381 | 385 | ||
382 | static int __init hp_wmi_input_setup(void) | 386 | static int __init hp_wmi_input_setup(void) |
@@ -455,7 +459,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
455 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, | 459 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, |
456 | RFKILL_TYPE_WLAN, | 460 | RFKILL_TYPE_WLAN, |
457 | &hp_wmi_rfkill_ops, | 461 | &hp_wmi_rfkill_ops, |
458 | (void *) 0); | 462 | (void *) HPWMI_WIFI); |
463 | rfkill_init_sw_state(wifi_rfkill, | ||
464 | hp_wmi_get_sw_state(HPWMI_WIFI)); | ||
465 | rfkill_set_hw_state(wifi_rfkill, | ||
466 | hp_wmi_get_hw_state(HPWMI_WIFI)); | ||
459 | err = rfkill_register(wifi_rfkill); | 467 | err = rfkill_register(wifi_rfkill); |
460 | if (err) | 468 | if (err) |
461 | goto register_wifi_error; | 469 | goto register_wifi_error; |
@@ -465,7 +473,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
465 | bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, | 473 | bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, |
466 | RFKILL_TYPE_BLUETOOTH, | 474 | RFKILL_TYPE_BLUETOOTH, |
467 | &hp_wmi_rfkill_ops, | 475 | &hp_wmi_rfkill_ops, |
468 | (void *) 1); | 476 | (void *) HPWMI_BLUETOOTH); |
477 | rfkill_init_sw_state(bluetooth_rfkill, | ||
478 | hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); | ||
479 | rfkill_set_hw_state(bluetooth_rfkill, | ||
480 | hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); | ||
469 | err = rfkill_register(bluetooth_rfkill); | 481 | err = rfkill_register(bluetooth_rfkill); |
470 | if (err) | 482 | if (err) |
471 | goto register_bluetooth_error; | 483 | goto register_bluetooth_error; |
@@ -475,7 +487,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
475 | wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, | 487 | wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, |
476 | RFKILL_TYPE_WWAN, | 488 | RFKILL_TYPE_WWAN, |
477 | &hp_wmi_rfkill_ops, | 489 | &hp_wmi_rfkill_ops, |
478 | (void *) 2); | 490 | (void *) HPWMI_WWAN); |
491 | rfkill_init_sw_state(wwan_rfkill, | ||
492 | hp_wmi_get_sw_state(HPWMI_WWAN)); | ||
493 | rfkill_set_hw_state(wwan_rfkill, | ||
494 | hp_wmi_get_hw_state(HPWMI_WWAN)); | ||
479 | err = rfkill_register(wwan_rfkill); | 495 | err = rfkill_register(wwan_rfkill); |
480 | if (err) | 496 | if (err) |
481 | goto register_wwan_err; | 497 | goto register_wwan_err; |
@@ -533,6 +549,19 @@ static int hp_wmi_resume_handler(struct device *device) | |||
533 | input_sync(hp_wmi_input_dev); | 549 | input_sync(hp_wmi_input_dev); |
534 | } | 550 | } |
535 | 551 | ||
552 | if (wifi_rfkill) | ||
553 | rfkill_set_states(wifi_rfkill, | ||
554 | hp_wmi_get_sw_state(HPWMI_WIFI), | ||
555 | hp_wmi_get_hw_state(HPWMI_WIFI)); | ||
556 | if (bluetooth_rfkill) | ||
557 | rfkill_set_states(bluetooth_rfkill, | ||
558 | hp_wmi_get_sw_state(HPWMI_BLUETOOTH), | ||
559 | hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); | ||
560 | if (wwan_rfkill) | ||
561 | rfkill_set_states(wwan_rfkill, | ||
562 | hp_wmi_get_sw_state(HPWMI_WWAN), | ||
563 | hp_wmi_get_hw_state(HPWMI_WWAN)); | ||
564 | |||
536 | return 0; | 565 | return 0; |
537 | } | 566 | } |
538 | 567 | ||