aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/hp-wmi.c
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2009-07-21 07:14:01 -0400
committerLen Brown <len.brown@intel.com>2009-12-09 23:52:54 -0500
commite5fbba85a7acc2626d4fe14501816811d702f3e9 (patch)
treeffc1fe9cb89268cd963f52f3552132aad8df7f79 /drivers/platform/x86/hp-wmi.c
parent22763c5cf3690a681551162c15d34d935308c8d7 (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.c139
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
54enum hp_wmi_radio {
55 HPWMI_WIFI = 0,
56 HPWMI_BLUETOOTH = 1,
57 HPWMI_WWAN = 2,
58};
59
54static int __init hp_wmi_bios_setup(struct platform_device *device); 60static int __init hp_wmi_bios_setup(struct platform_device *device);
55static int __exit hp_wmi_bios_remove(struct platform_device *device); 61static int __exit hp_wmi_bios_remove(struct platform_device *device);
56static int hp_wmi_resume_handler(struct device *device); 62static int hp_wmi_resume_handler(struct device *device);
@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void)
175 181
176static int hp_wmi_set_block(void *data, bool blocked) 182static 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
188static bool hp_wmi_wifi_state(void) 194static 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
198static 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
208static bool hp_wmi_wwan_state(void) 205static 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
382static int __init hp_wmi_input_setup(void) 386static 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