]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/platform/x86/eeepc-laptop.c
eeepc-laptop: Remove uneccesary acpi_disabled check
[mirror_ubuntu-bionic-kernel.git] / drivers / platform / x86 / eeepc-laptop.c
index d379e74a05d0f7d55d22470a7c10f979bf969838..f5efe8da5e7aab4dcd7b04ad55bd559c90a7a541 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/rfkill.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
+#include <linux/leds.h>
 
 #define EEEPC_LAPTOP_VERSION   "0.1"
 
@@ -150,8 +151,6 @@ struct eeepc_hotk {
 /* The actual device the driver binds to */
 static struct eeepc_hotk *ehotk;
 
-static void eeepc_rfkill_hotplug(bool real);
-
 /* Platform device/driver */
 static int eeepc_hotk_thaw(struct device *device);
 static int eeepc_hotk_restore(struct device *device);
@@ -345,16 +344,7 @@ static bool eeepc_wlan_rfkill_blocked(void)
 static int eeepc_rfkill_set(void *data, bool blocked)
 {
        unsigned long asl = (unsigned long)data;
-       int ret;
-
-       if (asl != CM_ASL_WLAN)
-               return set_acpi(asl, !blocked);
-
-       /* hack to avoid panic with rt2860sta */
-       if (blocked)
-               eeepc_rfkill_hotplug(false);
-       ret = set_acpi(asl, !blocked);
-       return ret;
+       return set_acpi(asl, !blocked);
 }
 
 static const struct rfkill_ops eeepc_rfkill_ops = {
@@ -367,7 +357,8 @@ static void __devinit eeepc_enable_camera(void)
         * If the following call to set_acpi() fails, it's because there's no
         * camera so we can ignore the error.
         */
-       set_acpi(CM_ASL_CAMERA, 1);
+       if (get_acpi(CM_ASL_CAMERA) == 0)
+               set_acpi(CM_ASL_CAMERA, 1);
 }
 
 /*
@@ -390,7 +381,7 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
        if (rv > 0)
                value = set_acpi(cm, value);
        if (value < 0)
-               return value;
+               return -EIO;
        return rv;
 }
 
@@ -399,11 +390,11 @@ static ssize_t show_sys_acpi(int cm, char *buf)
        int value = get_acpi(cm);
 
        if (value < 0)
-               return value;
+               return -EIO;
        return sprintf(buf, "%d\n", value);
 }
 
-#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm)                           \
+#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm)                    \
        static ssize_t show_##_name(struct device *dev,                 \
                                    struct device_attribute *attr,      \
                                    char *buf)                          \
@@ -419,14 +410,14 @@ static ssize_t show_sys_acpi(int cm, char *buf)
        static struct device_attribute dev_attr_##_name = {             \
                .attr = {                                               \
                        .name = __stringify(_name),                     \
-                       .mode = 0644 },                                 \
+                       .mode = _mode },                                \
                .show   = show_##_name,                                 \
                .store  = store_##_name,                                \
        }
 
-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(camera, 0644, CM_ASL_CAMERA);
+EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
+EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
 
 struct eeepc_cpufv {
        int num;
@@ -516,6 +507,39 @@ static struct attribute_group platform_attribute_group = {
        .attrs = platform_attributes
 };
 
+/*
+ * LEDs
+ */
+/*
+ * These functions actually update the LED's, and are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
+static int tpd_led_wk;
+
+static void tpd_led_update(struct work_struct *ignored)
+{
+       int value = tpd_led_wk;
+       set_acpi(CM_ASL_TPD, value);
+}
+
+static struct workqueue_struct *led_workqueue;
+static DECLARE_WORK(tpd_led_work, tpd_led_update);
+
+static void tpd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       tpd_led_wk = (value > 0) ? 1 : 0;
+       queue_work(led_workqueue, &tpd_led_work);
+}
+
+static struct led_classdev tpd_led = {
+       .name           = "eeepc::touchpad",
+       .brightness_set = tpd_led_set,
+       .max_brightness = 1
+};
+
 /*
  * Hotkey functions
  */
@@ -654,13 +678,13 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
        return 0;
 }
 
-static void eeepc_rfkill_hotplug(bool real)
+static void eeepc_rfkill_hotplug(void)
 {
        struct pci_dev *dev;
        struct pci_bus *bus;
-       bool blocked = real ? eeepc_wlan_rfkill_blocked() : true;
+       bool blocked = eeepc_wlan_rfkill_blocked();
 
-       if (real && ehotk->wlan_rfkill)
+       if (ehotk->wlan_rfkill)
                rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
 
        mutex_lock(&ehotk->hotplug_lock);
@@ -703,7 +727,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
        if (event != ACPI_NOTIFY_BUS_CHECK)
                return;
 
-       eeepc_rfkill_hotplug(true);
+       eeepc_rfkill_hotplug();
 }
 
 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
@@ -861,7 +885,7 @@ static int eeepc_hotk_restore(struct device *device)
 {
        /* Refresh both wlan rfkill state and pci hotplug */
        if (ehotk->wlan_rfkill)
-               eeepc_rfkill_hotplug(true);
+               eeepc_rfkill_hotplug();
 
        if (ehotk->bluetooth_rfkill)
                rfkill_set_sw_state(ehotk->bluetooth_rfkill,
@@ -1004,7 +1028,7 @@ static void eeepc_rfkill_exit(void)
         * Refresh pci hotplug in case the rfkill state was changed after
         * eeepc_unregister_rfkill_notifier()
         */
-       eeepc_rfkill_hotplug(true);
+       eeepc_rfkill_hotplug();
        if (ehotk->hotplug_slot)
                pci_hp_deregister(ehotk->hotplug_slot);
 
@@ -1044,6 +1068,14 @@ static void eeepc_hwmon_exit(void)
        eeepc_hwmon_device = NULL;
 }
 
+static void eeepc_led_exit(void)
+{
+       if (led_workqueue)
+               destroy_workqueue(led_workqueue);
+       if (tpd_led.dev)
+               led_classdev_unregister(&tpd_led);
+}
+
 static int eeepc_new_rfkill(struct rfkill **rfkill,
                            const char *name, struct device *dev,
                            enum rfkill_type type, int cm)
@@ -1120,7 +1152,7 @@ static int eeepc_rfkill_init(struct device *dev)
         * Refresh pci hotplug in case the rfkill state was changed during
         * setup.
         */
-       eeepc_rfkill_hotplug(true);
+       eeepc_rfkill_hotplug();
 
 exit:
        if (result && result != -ENODEV)
@@ -1200,13 +1232,29 @@ static int eeepc_input_init(struct device *dev)
        return 0;
 }
 
+static int eeepc_led_init(struct device *dev)
+{
+       int rv;
+
+       if (get_acpi(CM_ASL_TPD) == -ENODEV)
+               return 0;
+
+       rv = led_classdev_register(dev, &tpd_led);
+       if (rv)
+               return rv;
+
+       led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!led_workqueue)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int __devinit eeepc_hotk_add(struct acpi_device *device)
 {
        struct device *dev;
        int result;
 
-       if (!device)
-               return -EINVAL;
        pr_notice(EEEPC_HOTK_NAME "\n");
        ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
        if (!ehotk)
@@ -1258,6 +1306,10 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device)
        if (result)
                goto fail_hwmon;
 
+       result = eeepc_led_init(dev);
+       if (result)
+               goto fail_led;
+
        result = eeepc_rfkill_init(dev);
        if (result)
                goto fail_rfkill;
@@ -1265,6 +1317,8 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device)
        return 0;
 
 fail_rfkill:
+       eeepc_led_exit();
+fail_led:
        eeepc_hwmon_exit();
 fail_hwmon:
        eeepc_input_exit();
@@ -1287,13 +1341,11 @@ fail_platform_driver:
 
 static int eeepc_hotk_remove(struct acpi_device *device, int type)
 {
-       if (!device || !acpi_driver_data(device))
-               return -EINVAL;
-
        eeepc_backlight_exit();
        eeepc_rfkill_exit();
        eeepc_input_exit();
        eeepc_hwmon_exit();
+       eeepc_led_exit();
        sysfs_remove_group(&platform_device->dev.kobj,
                           &platform_attribute_group);
        platform_device_unregister(platform_device);
@@ -1307,8 +1359,6 @@ static int __init eeepc_laptop_init(void)
 {
        int result;
 
-       if (acpi_disabled)
-               return -ENODEV;
        result = acpi_bus_register_driver(&eeepc_hotk_driver);
        if (result < 0)
                return result;