eeepc-laptop.c: use pr_fmt and pr_<level>
[cascardo/linux.git] / drivers / platform / x86 / eeepc-laptop.c
index 8153b3e..d14f714 100644 (file)
@@ -16,6 +16,8 @@
  *  GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -31,6 +33,7 @@
 #include <linux/input.h>
 #include <linux/rfkill.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 
 #define EEEPC_LAPTOP_VERSION   "0.1"
 
 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
 #define EEEPC_HOTK_HID         "ASUS010"
 
-#define EEEPC_LOG      EEEPC_HOTK_FILE ": "
-#define EEEPC_ERR      KERN_ERR        EEEPC_LOG
-#define EEEPC_WARNING  KERN_WARNING    EEEPC_LOG
-#define EEEPC_NOTICE   KERN_NOTICE     EEEPC_LOG
-#define EEEPC_INFO     KERN_INFO       EEEPC_LOG
 
 /*
  * Definitions for Asus EeePC
@@ -62,7 +60,10 @@ enum {
        DISABLE_ASL_GPS = 0x0020,
        DISABLE_ASL_DISPLAYSWITCH = 0x0040,
        DISABLE_ASL_MODEM = 0x0080,
-       DISABLE_ASL_CARDREADER = 0x0100
+       DISABLE_ASL_CARDREADER = 0x0100,
+       DISABLE_ASL_3G = 0x0200,
+       DISABLE_ASL_WIMAX = 0x0400,
+       DISABLE_ASL_HWCF = 0x0800
 };
 
 enum {
@@ -87,7 +88,13 @@ enum {
        CM_ASL_USBPORT3,
        CM_ASL_MODEM,
        CM_ASL_CARDREADER,
-       CM_ASL_LID
+       CM_ASL_3G,
+       CM_ASL_WIMAX,
+       CM_ASL_HWCF,
+       CM_ASL_LID,
+       CM_ASL_TYPE,
+       CM_ASL_PANELPOWER,      /*P901*/
+       CM_ASL_TPD
 };
 
 static const char *cm_getv[] = {
@@ -96,7 +103,8 @@ static const char *cm_getv[] = {
        NULL, "PBLG", NULL, NULL,
        "CFVG", NULL, NULL, NULL,
        "USBG", NULL, NULL, "MODG",
-       "CRDG", "LIDG"
+       "CRDG", "M3GG", "WIMG", "HWCF",
+       "LIDG", "TYPE", "PBPG", "TPDG"
 };
 
 static const char *cm_setv[] = {
@@ -105,7 +113,8 @@ static const char *cm_setv[] = {
        "SDSP", "PBLS", "HDPS", NULL,
        "CFVS", NULL, NULL, NULL,
        "USBG", NULL, NULL, "MODS",
-       "CRDS", NULL
+       "CRDS", "M3GS", "WIMS", NULL,
+       NULL, NULL, "PBPS", "TPDS"
 };
 
 #define EEEPC_EC       "\\_SB.PCI0.SBRG.EC0."
@@ -132,6 +141,7 @@ struct eeepc_hotk {
        u16 *keycode_map;
        struct rfkill *eeepc_wlan_rfkill;
        struct rfkill *eeepc_bluetooth_rfkill;
+       struct hotplug_slot *hotplug_slot;
 };
 
 /* The actual device the driver binds to */
@@ -181,6 +191,7 @@ static struct key_entry eeepc_keymap[] = {
 static int eeepc_hotk_add(struct acpi_device *device);
 static int eeepc_hotk_remove(struct acpi_device *device, int type);
 static int eeepc_hotk_resume(struct acpi_device *device);
+static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id eeepc_device_ids[] = {
        {EEEPC_HOTK_HID, 0},
@@ -192,13 +203,24 @@ static struct acpi_driver eeepc_hotk_driver = {
        .name = EEEPC_HOTK_NAME,
        .class = EEEPC_HOTK_CLASS,
        .ids = eeepc_device_ids,
+       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
        .ops = {
                .add = eeepc_hotk_add,
                .remove = eeepc_hotk_remove,
                .resume = eeepc_hotk_resume,
+               .notify = eeepc_hotk_notify,
        },
 };
 
+/* PCI hotplug ops */
+static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
+       .owner = THIS_MODULE,
+       .get_adapter_status = eeepc_get_adapter_status,
+       .get_power_status = eeepc_get_adapter_status,
+};
+
 /* The backlight device /sys/class/backlight */
 static struct backlight_device *eeepc_backlight_device;
 
@@ -260,7 +282,7 @@ static int set_acpi(int cm, int value)
                if (method == NULL)
                        return -ENODEV;
                if (write_acpi_int(ehotk->handle, method, value, NULL))
-                       printk(EEEPC_WARNING "Error writing %s\n", method);
+                       pr_warning("Error writing %s\n", method);
        }
        return 0;
 }
@@ -273,7 +295,7 @@ static int get_acpi(int cm)
                if (method == NULL)
                        return -ENODEV;
                if (read_acpi_int(ehotk->handle, method, &value))
-                       printk(EEEPC_WARNING "Error reading %s\n", method);
+                       pr_warning("Error reading %s\n", method);
        }
        return value;
 }
@@ -318,6 +340,15 @@ static const struct rfkill_ops eeepc_rfkill_ops = {
        .set_block = eeepc_rfkill_set,
 };
 
+static void __init 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);
+}
+
 /*
  * Sys helpers
  */
@@ -369,13 +400,88 @@ 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);
+
+struct eeepc_cpufv {
+       int num;
+       int cur;
+};
+
+static int get_cpufv(struct eeepc_cpufv *c)
+{
+       c->cur = get_acpi(CM_ASL_CPUFV);
+       c->num = (c->cur >> 8) & 0xff;
+       c->cur &= 0xff;
+       if (c->cur < 0 || c->num <= 0 || c->num > 12)
+               return -ENODEV;
+       return 0;
+}
+
+static ssize_t show_available_cpufv(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct eeepc_cpufv c;
+       int i;
+       ssize_t len = 0;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       for (i = 0; i < c.num; i++)
+               len += sprintf(buf + len, "%d ", i);
+       len += sprintf(buf + len, "\n");
+       return len;
+}
+
+static ssize_t show_cpufv(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+{
+       struct eeepc_cpufv c;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
+}
+
+static ssize_t store_cpufv(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct eeepc_cpufv c;
+       int rv, value;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       rv = parse_arg(buf, count, &value);
+       if (rv < 0)
+               return rv;
+       if (!rv || value < 0 || value >= c.num)
+               return -EINVAL;
+       set_acpi(CM_ASL_CPUFV, value);
+       return rv;
+}
+
+static struct device_attribute dev_attr_cpufv = {
+       .attr = {
+               .name = "cpufv",
+               .mode = 0644 },
+       .show   = show_cpufv,
+       .store  = store_cpufv
+};
+
+static struct device_attribute dev_attr_available_cpufv = {
+       .attr = {
+               .name = "available_cpufv",
+               .mode = 0444 },
+       .show   = show_available_cpufv
+};
 
 static struct attribute *platform_attributes[] = {
        &dev_attr_camera.attr,
        &dev_attr_cardr.attr,
        &dev_attr_disp.attr,
        &dev_attr_cpufv.attr,
+       &dev_attr_available_cpufv.attr,
        NULL
 };
 
@@ -453,26 +559,23 @@ static int eeepc_hotk_check(void)
        if (ehotk->device->status.present) {
                if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
                                    &buffer)) {
-                       printk(EEEPC_ERR "Hotkey initialization failed\n");
+                       pr_err("Hotkey initialization failed\n");
                        return -ENODEV;
                } else {
-                       printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
-                              ehotk->init_flag);
+                       pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
                }
                /* get control methods supported */
                if (read_acpi_int(ehotk->handle, "CMSG"
                                   , &ehotk->cm_supported)) {
-                       printk(EEEPC_ERR
-                              "Get control methods supported failed\n");
+                       pr_err("Get control methods supported failed\n");
                        return -ENODEV;
                } else {
-                       printk(EEEPC_INFO
-                              "Get control methods supported: 0x%x\n",
-                              ehotk->cm_supported);
+                       pr_info("Get control methods supported: 0x%x\n",
+                               ehotk->cm_supported);
                }
                ehotk->inputdev = input_allocate_device();
                if (!ehotk->inputdev) {
-                       printk(EEEPC_INFO "Unable to allocate input device\n");
+                       pr_info("Unable to allocate input device\n");
                        return 0;
                }
                ehotk->inputdev->name = "Asus EeePC extra buttons";
@@ -491,12 +594,12 @@ static int eeepc_hotk_check(void)
                }
                result = input_register_device(ehotk->inputdev);
                if (result) {
-                       printk(EEEPC_INFO "Unable to register input device\n");
+                       pr_info("Unable to register input device\n");
                        input_free_device(ehotk->inputdev);
                        return 0;
                }
        } else {
-               printk(EEEPC_ERR "Hotkey device not present, aborting\n");
+               pr_err("Hotkey device not present, aborting\n");
                return -EINVAL;
        }
        return 0;
@@ -514,6 +617,19 @@ static int notify_brn(void)
        return -1;
 }
 
+static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
+                                   u8 *value)
+{
+       int val = get_acpi(CM_ASL_WLAN);
+
+       if (val == 1 || val == 0)
+               *value = val;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
 static void eeepc_rfkill_hotplug(void)
 {
        struct pci_dev *dev;
@@ -521,7 +637,7 @@ static void eeepc_rfkill_hotplug(void)
        bool blocked;
 
        if (!bus) {
-               printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
+               pr_warning("Unable to find PCI bus 1?\n");
                return;
        }
 
@@ -537,7 +653,7 @@ static void eeepc_rfkill_hotplug(void)
                if (dev) {
                        pci_bus_assign_resources(bus);
                        if (pci_bus_add_device(dev))
-                               printk(EEEPC_ERR "Unable to hotplug wifi\n");
+                               pr_err("Unable to hotplug wifi\n");
                }
        } else {
                dev = pci_get_slot(bus, 0);
@@ -558,7 +674,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
        eeepc_rfkill_hotplug();
 }
 
-static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
+static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
 {
        static struct key_entry *key;
        u16 count;
@@ -566,6 +682,8 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 
        if (!ehotk)
                return;
+       if (event > ACPI_MAX_SYS_NOTIFY)
+               return;
        if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
                brn = notify_brn();
        count = ehotk->event_count[event % 128]++;
@@ -618,8 +736,7 @@ static int eeepc_register_rfkill_notifier(char *node)
                                                     eeepc_rfkill_notify,
                                                     NULL);
                if (ACPI_FAILURE(status))
-                       printk(EEEPC_WARNING
-                              "Failed to register notify on %s\n", node);
+                       pr_warning("Failed to register notify on %s\n", node);
        } else
                return -ENODEV;
 
@@ -638,20 +755,66 @@ static void eeepc_unregister_rfkill_notifier(char *node)
                                                     ACPI_SYSTEM_NOTIFY,
                                                     eeepc_rfkill_notify);
                if (ACPI_FAILURE(status))
-                       printk(EEEPC_ERR
-                              "Error removing rfkill notify handler %s\n",
+                       pr_err("Error removing rfkill notify handler %s\n",
                                node);
        }
 }
 
+static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+       kfree(hotplug_slot->info);
+       kfree(hotplug_slot);
+}
+
+static int eeepc_setup_pci_hotplug(void)
+{
+       int ret = -ENOMEM;
+       struct pci_bus *bus = pci_find_bus(0, 1);
+
+       if (!bus) {
+               pr_err("Unable to find wifi PCI bus\n");
+               return -ENODEV;
+       }
+
+       ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+       if (!ehotk->hotplug_slot)
+               goto error_slot;
+
+       ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+                                           GFP_KERNEL);
+       if (!ehotk->hotplug_slot->info)
+               goto error_info;
+
+       ehotk->hotplug_slot->private = ehotk;
+       ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
+       ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
+       eeepc_get_adapter_status(ehotk->hotplug_slot,
+                                &ehotk->hotplug_slot->info->adapter_status);
+
+       ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
+       if (ret) {
+               pr_err("Unable to register hotplug slot - %d\n", ret);
+               goto error_register;
+       }
+
+       return 0;
+
+error_register:
+       kfree(ehotk->hotplug_slot->info);
+error_info:
+       kfree(ehotk->hotplug_slot);
+       ehotk->hotplug_slot = NULL;
+error_slot:
+       return ret;
+}
+
 static int eeepc_hotk_add(struct acpi_device *device)
 {
-       acpi_status status = AE_OK;
        int result;
 
        if (!device)
                 return -EINVAL;
-       printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
+       pr_notice(EEEPC_HOTK_NAME "\n");
        ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
        if (!ehotk)
                return -ENOMEM;
@@ -664,10 +827,6 @@ static int eeepc_hotk_add(struct acpi_device *device)
        result = eeepc_hotk_check();
        if (result)
                goto ehotk_fail;
-       status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
-                                            eeepc_hotk_notify, ehotk);
-       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");
@@ -707,8 +866,21 @@ static int eeepc_hotk_add(struct acpi_device *device)
                        goto bluetooth_fail;
        }
 
+       result = eeepc_setup_pci_hotplug();
+       /*
+        * If we get -EBUSY then something else is handling the PCI hotplug -
+        * don't fail in this case
+        */
+       if (result == -EBUSY)
+               return 0;
+       else if (result)
+               goto pci_fail;
+
        return 0;
 
+ pci_fail:
+       if (ehotk->eeepc_bluetooth_rfkill)
+               rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
  bluetooth_fail:
        rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
        rfkill_unregister(ehotk->eeepc_wlan_rfkill);
@@ -725,17 +897,13 @@ static int eeepc_hotk_add(struct acpi_device *device)
 
 static int eeepc_hotk_remove(struct acpi_device *device, int type)
 {
-       acpi_status status = 0;
-
        if (!device || !acpi_driver_data(device))
                 return -EINVAL;
-       status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
-                                           eeepc_hotk_notify);
-       if (ACPI_FAILURE(status))
-               printk(EEEPC_ERR "Error removing notify handler\n");
 
        eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
        eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
+       if (ehotk->hotplug_slot)
+               pci_hp_deregister(ehotk->hotplug_slot);
 
        kfree(ehotk);
        return 0;
@@ -929,8 +1097,7 @@ static int eeepc_backlight_init(struct device *dev)
        bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
                                       NULL, &eeepcbl_ops);
        if (IS_ERR(bd)) {
-               printk(EEEPC_ERR
-                      "Could not register eeepc backlight device\n");
+               pr_err("Could not register eeepc backlight device\n");
                eeepc_backlight_device = NULL;
                return PTR_ERR(bd);
        }
@@ -949,8 +1116,7 @@ static int eeepc_hwmon_init(struct device *dev)
 
        hwmon = hwmon_device_register(dev);
        if (IS_ERR(hwmon)) {
-               printk(EEEPC_ERR
-                      "Could not register eeepc hwmon device\n");
+               pr_err("Could not register eeepc hwmon device\n");
                eeepc_hwmon_device = NULL;
                return PTR_ERR(hwmon);
        }
@@ -983,12 +1149,14 @@ static int __init eeepc_laptop_init(void)
                if (result)
                        goto fail_backlight;
        } else
-               printk(EEEPC_INFO "Backlight controlled by ACPI video "
-                      "driver\n");
+               pr_info("Backlight controlled by ACPI video driver\n");
 
        result = eeepc_hwmon_init(dev);
        if (result)
                goto fail_hwmon;
+
+       eeepc_enable_camera();
+
        /* Register platform stuff */
        result = platform_driver_register(&platform_driver);
        if (result)