]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/platform/x86/eeepc-laptop.c
rfkill: rewrite
[mirror_ubuntu-bionic-kernel.git] / drivers / platform / x86 / eeepc-laptop.c
index 6f54fd1757cd873e24a2dc2e690923a9f061db21..1208d0cedd15d76ed0903632a4993d80da329b8d 100644 (file)
@@ -158,6 +158,7 @@ enum { KE_KEY, KE_END };
 static struct key_entry eeepc_keymap[] = {
        /* Sleep already handled via generic ACPI code */
        {KE_KEY, 0x10, KEY_WLAN },
+       {KE_KEY, 0x11, KEY_WLAN },
        {KE_KEY, 0x12, KEY_PROG1 },
        {KE_KEY, 0x13, KEY_MUTE },
        {KE_KEY, 0x14, KEY_VOLUMEDOWN },
@@ -166,6 +167,8 @@ static struct key_entry eeepc_keymap[] = {
        {KE_KEY, 0x1b, KEY_ZOOM },
        {KE_KEY, 0x1c, KEY_PROG2 },
        {KE_KEY, 0x1d, KEY_PROG3 },
+       {KE_KEY, NOTIFY_BRN_MIN,     KEY_BRIGHTNESSDOWN },
+       {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
        {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
        {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
        {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
@@ -296,39 +299,22 @@ static int update_bl_status(struct backlight_device *bd)
  * Rfkill helpers
  */
 
-static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state)
-{
-       if (state == RFKILL_STATE_SOFT_BLOCKED)
-               return set_acpi(CM_ASL_WLAN, 0);
-       else
-               return set_acpi(CM_ASL_WLAN, 1);
-}
-
-static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
+static bool eeepc_wlan_rfkill_blocked(void)
 {
        if (get_acpi(CM_ASL_WLAN) == 1)
-               *state = RFKILL_STATE_UNBLOCKED;
-       else
-               *state = RFKILL_STATE_SOFT_BLOCKED;
-       return 0;
+               return false;
+       return true;
 }
 
-static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state)
+static int eeepc_rfkill_set(void *data, bool blocked)
 {
-       if (state == RFKILL_STATE_SOFT_BLOCKED)
-               return set_acpi(CM_ASL_BLUETOOTH, 0);
-       else
-               return set_acpi(CM_ASL_BLUETOOTH, 1);
+       unsigned long asl = (unsigned long)data;
+       return set_acpi(asl, !blocked);
 }
 
-static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state)
-{
-       if (get_acpi(CM_ASL_BLUETOOTH) == 1)
-               *state = RFKILL_STATE_UNBLOCKED;
-       else
-               *state = RFKILL_STATE_SOFT_BLOCKED;
-       return 0;
-}
+static const struct rfkill_ops eeepc_rfkill_ops = {
+       .set_block = eeepc_rfkill_set,
+};
 
 /*
  * Sys helpers
@@ -381,11 +367,13 @@ static ssize_t show_sys_acpi(int cm, char *buf)
 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
+EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV);
 
 static struct attribute *platform_attributes[] = {
        &dev_attr_camera.attr,
        &dev_attr_cardr.attr,
        &dev_attr_disp.attr,
+       &dev_attr_cpufv.attr,
        NULL
 };
 
@@ -512,17 +500,23 @@ static int eeepc_hotk_check(void)
        return 0;
 }
 
-static void notify_brn(void)
+static int notify_brn(void)
 {
+       /* returns the *previous* brightness, or -1 */
        struct backlight_device *bd = eeepc_backlight_device;
-       if (bd)
+       if (bd) {
+               int old = bd->props.brightness;
                bd->props.brightness = read_brightness(bd);
+               return old;
+       }
+       return -1;
 }
 
 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 {
        struct pci_dev *dev;
        struct pci_bus *bus = pci_find_bus(0, 1);
+       bool blocked;
 
        if (event != ACPI_NOTIFY_BUS_CHECK)
                return;
@@ -532,7 +526,8 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
                return;
        }
 
-       if (get_acpi(CM_ASL_WLAN) == 1) {
+       blocked = eeepc_wlan_rfkill_blocked();
+       if (!blocked) {
                dev = pci_get_slot(bus, 0);
                if (dev) {
                        /* Device already present */
@@ -552,23 +547,41 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
                        pci_dev_put(dev);
                }
        }
+
+       rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
 }
 
 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
        static struct key_entry *key;
        u16 count;
+       int brn = -ENODEV;
 
        if (!ehotk)
                return;
        if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
-               notify_brn();
+               brn = notify_brn();
        count = ehotk->event_count[event % 128]++;
        acpi_bus_generate_proc_event(ehotk->device, event, count);
        acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
                                        dev_name(&ehotk->device->dev), event,
                                        count);
        if (ehotk->inputdev) {
+               if (brn != -ENODEV) {
+                       /* brightness-change events need special
+                        * handling for conversion to key events
+                        */
+                       if (brn < 0)
+                               brn = event;
+                       else
+                               brn += NOTIFY_BRN_MIN;
+                       if (event < brn)
+                               event = NOTIFY_BRN_MIN; /* brightness down */
+                       else if (event > brn)
+                               event = NOTIFY_BRN_MIN + 2; /* ... up */
+                       else
+                               event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
+               }
                key = eepc_get_entry_by_scancode(event);
                if (key) {
                        switch (key->type) {
@@ -649,27 +662,21 @@ static int eeepc_hotk_add(struct acpi_device *device)
        if (ACPI_FAILURE(status))
                printk(EEEPC_ERR "Error installing notify handler\n");
 
+       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
+       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
+
        if (get_acpi(CM_ASL_WLAN) != -1) {
-               ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev,
-                                                          RFKILL_TYPE_WLAN);
+               ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
+                                                       &device->dev,
+                                                       RFKILL_TYPE_WLAN,
+                                                       &eeepc_rfkill_ops,
+                                                       (void *)CM_ASL_WLAN);
 
                if (!ehotk->eeepc_wlan_rfkill)
                        goto wlan_fail;
 
-               ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
-               ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
-               ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
-               if (get_acpi(CM_ASL_WLAN) == 1) {
-                       ehotk->eeepc_wlan_rfkill->state =
-                               RFKILL_STATE_UNBLOCKED;
-                       rfkill_set_default(RFKILL_TYPE_WLAN,
-                                          RFKILL_STATE_UNBLOCKED);
-               } else {
-                       ehotk->eeepc_wlan_rfkill->state =
-                               RFKILL_STATE_SOFT_BLOCKED;
-                       rfkill_set_default(RFKILL_TYPE_WLAN,
-                                          RFKILL_STATE_SOFT_BLOCKED);
-               }
+               rfkill_set_global_sw_state(RFKILL_TYPE_WLAN,
+                                          get_acpi(CM_ASL_WLAN) != 1);
                result = rfkill_register(ehotk->eeepc_wlan_rfkill);
                if (result)
                        goto wlan_fail;
@@ -677,46 +684,31 @@ static int eeepc_hotk_add(struct acpi_device *device)
 
        if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
                ehotk->eeepc_bluetooth_rfkill =
-                       rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
+                       rfkill_alloc("eeepc-bluetooth",
+                                    &device->dev,
+                                    RFKILL_TYPE_BLUETOOTH,
+                                    &eeepc_rfkill_ops,
+                                    (void *)CM_ASL_BLUETOOTH);
 
                if (!ehotk->eeepc_bluetooth_rfkill)
                        goto bluetooth_fail;
 
-               ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
-               ehotk->eeepc_bluetooth_rfkill->toggle_radio =
-                       eeepc_bluetooth_rfkill_set;
-               ehotk->eeepc_bluetooth_rfkill->get_state =
-                       eeepc_bluetooth_rfkill_state;
-               if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
-                       ehotk->eeepc_bluetooth_rfkill->state =
-                               RFKILL_STATE_UNBLOCKED;
-                       rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
-                                          RFKILL_STATE_UNBLOCKED);
-               } else {
-                       ehotk->eeepc_bluetooth_rfkill->state =
-                               RFKILL_STATE_SOFT_BLOCKED;
-                       rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
-                                          RFKILL_STATE_SOFT_BLOCKED);
-               }
-
+               rfkill_set_global_sw_state(RFKILL_TYPE_BLUETOOTH,
+                                          get_acpi(CM_ASL_BLUETOOTH) != 1);
                result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
                if (result)
                        goto bluetooth_fail;
        }
 
-       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
-       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
-
        return 0;
 
  bluetooth_fail:
-       if (ehotk->eeepc_bluetooth_rfkill)
-               rfkill_free(ehotk->eeepc_bluetooth_rfkill);
+       rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
        rfkill_unregister(ehotk->eeepc_wlan_rfkill);
-       ehotk->eeepc_wlan_rfkill = NULL;
  wlan_fail:
-       if (ehotk->eeepc_wlan_rfkill)
-               rfkill_free(ehotk->eeepc_wlan_rfkill);
+       rfkill_destroy(ehotk->eeepc_wlan_rfkill);
+       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
+       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
  ehotk_fail:
        kfree(ehotk);
        ehotk = NULL;