aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAceLan Kao <acelan.kao@canonical.com>2012-07-27 04:51:59 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2013-02-24 17:49:52 -0500
commit6cae06e603339f99334bc6b276e2ac619cf0d476 (patch)
tree8c42fb743dd64b92d54973de71b984e49f81d7c0 /drivers/platform
parent9e2d59ad580d590134285f361a0e80f0e98c0207 (diff)
asus-wmi: update wlan LED through rfkill led trigger
For those machines with wapf=4, BIOS won't update the wireless LED, since wapf=4 means user application will take in chage of the wifi and bt. So, we have to update wlan LED status explicitly. But I found there is another wireless LED bug in launchpad and which is not in the wapf=4 quirk. So, it might be better to set wireless LED status explicitly for all machines. BugLink: https://launchpad.net/bugs/901105 Signed-off-by: AceLan Kao <acelan.kao@canonical.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/asus-wmi.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index f80ae4d10f68..912ec7de71f4 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -187,6 +187,8 @@ struct asus_wmi {
187 struct device *hwmon_device; 187 struct device *hwmon_device;
188 struct platform_device *platform_device; 188 struct platform_device *platform_device;
189 189
190 struct led_classdev wlan_led;
191 int wlan_led_wk;
190 struct led_classdev tpd_led; 192 struct led_classdev tpd_led;
191 int tpd_led_wk; 193 int tpd_led_wk;
192 struct led_classdev kbd_led; 194 struct led_classdev kbd_led;
@@ -194,6 +196,7 @@ struct asus_wmi {
194 struct workqueue_struct *led_workqueue; 196 struct workqueue_struct *led_workqueue;
195 struct work_struct tpd_led_work; 197 struct work_struct tpd_led_work;
196 struct work_struct kbd_led_work; 198 struct work_struct kbd_led_work;
199 struct work_struct wlan_led_work;
197 200
198 struct asus_rfkill wlan; 201 struct asus_rfkill wlan;
199 struct asus_rfkill bluetooth; 202 struct asus_rfkill bluetooth;
@@ -456,12 +459,65 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
456 return value; 459 return value;
457} 460}
458 461
462static int wlan_led_unknown_state(struct asus_wmi *asus)
463{
464 u32 result;
465
466 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
467
468 return result & ASUS_WMI_DSTS_UNKNOWN_BIT;
469}
470
471static int wlan_led_presence(struct asus_wmi *asus)
472{
473 u32 result;
474
475 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
476
477 return result & ASUS_WMI_DSTS_PRESENCE_BIT;
478}
479
480static void wlan_led_update(struct work_struct *work)
481{
482 int ctrl_param;
483 struct asus_wmi *asus;
484
485 asus = container_of(work, struct asus_wmi, wlan_led_work);
486
487 ctrl_param = asus->wlan_led_wk;
488 asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL);
489}
490
491static void wlan_led_set(struct led_classdev *led_cdev,
492 enum led_brightness value)
493{
494 struct asus_wmi *asus;
495
496 asus = container_of(led_cdev, struct asus_wmi, wlan_led);
497
498 asus->wlan_led_wk = !!value;
499 queue_work(asus->led_workqueue, &asus->wlan_led_work);
500}
501
502static enum led_brightness wlan_led_get(struct led_classdev *led_cdev)
503{
504 struct asus_wmi *asus;
505 u32 result;
506
507 asus = container_of(led_cdev, struct asus_wmi, wlan_led);
508 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
509
510 return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
511}
512
459static void asus_wmi_led_exit(struct asus_wmi *asus) 513static void asus_wmi_led_exit(struct asus_wmi *asus)
460{ 514{
461 if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) 515 if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
462 led_classdev_unregister(&asus->kbd_led); 516 led_classdev_unregister(&asus->kbd_led);
463 if (!IS_ERR_OR_NULL(asus->tpd_led.dev)) 517 if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
464 led_classdev_unregister(&asus->tpd_led); 518 led_classdev_unregister(&asus->tpd_led);
519 if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
520 led_classdev_unregister(&asus->wlan_led);
465 if (asus->led_workqueue) 521 if (asus->led_workqueue)
466 destroy_workqueue(asus->led_workqueue); 522 destroy_workqueue(asus->led_workqueue);
467} 523}
@@ -498,6 +554,23 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
498 554
499 rv = led_classdev_register(&asus->platform_device->dev, 555 rv = led_classdev_register(&asus->platform_device->dev,
500 &asus->kbd_led); 556 &asus->kbd_led);
557 if (rv)
558 goto error;
559 }
560
561 if (wlan_led_presence(asus)) {
562 INIT_WORK(&asus->wlan_led_work, wlan_led_update);
563
564 asus->wlan_led.name = "asus::wlan";
565 asus->wlan_led.brightness_set = wlan_led_set;
566 if (!wlan_led_unknown_state(asus))
567 asus->wlan_led.brightness_get = wlan_led_get;
568 asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
569 asus->wlan_led.max_brightness = 1;
570 asus->wlan_led.default_trigger = "asus-wlan";
571
572 rv = led_classdev_register(&asus->platform_device->dev,
573 &asus->wlan_led);
501 } 574 }
502 575
503error: 576error:
@@ -813,6 +886,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
813 if (!*rfkill) 886 if (!*rfkill)
814 return -EINVAL; 887 return -EINVAL;
815 888
889 if (dev_id == ASUS_WMI_DEVID_WLAN)
890 rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
891
816 rfkill_init_sw_state(*rfkill, !result); 892 rfkill_init_sw_state(*rfkill, !result);
817 result = rfkill_register(*rfkill); 893 result = rfkill_register(*rfkill);
818 if (result) { 894 if (result) {