From 9593bd07ec8eaaa30aba4281b2b3273282fc344f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 00:02:16 -0800 Subject: sony-laptop - remove private workqueue, use keventd instead If we reschedule work instead of having work function sleep for 10 msecs between reads from kfifo we can safely use the main workqueue (keventd) and not bother with creating driver-private one. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 71 +++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 32 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6f..c42d35ba73d6 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -145,7 +145,6 @@ struct sony_laptop_input_s { struct input_dev *key_dev; struct kfifo fifo; spinlock_t fifo_lock; - struct workqueue_struct *wq; }; static struct sony_laptop_input_s sony_laptop_input = { @@ -301,18 +300,28 @@ static int sony_laptop_input_keycode_map[] = { /* release buttons after a short delay if pressed */ static void do_sony_laptop_release_key(struct work_struct *work) { + struct delayed_work *dwork = + container_of(work, struct delayed_work, work); struct sony_laptop_keypress kp; + unsigned long flags; + + spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags); - while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, - sizeof(kp), &sony_laptop_input.fifo_lock) - == sizeof(kp)) { - msleep(10); + if (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); } + + /* If there is something in the fifo schedule next release. */ + if (kfifo_len(&sony_laptop_input.fifo) != 0) + schedule_delayed_work(dwork, msecs_to_jiffies(10)); + + spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); } -static DECLARE_WORK(sony_laptop_release_key_work, - do_sony_laptop_release_key); + +static DECLARE_DELAYED_WORK(sony_laptop_release_key_work, + do_sony_laptop_release_key); /* forward event to the input subsystem */ static void sony_laptop_report_input_event(u8 event) @@ -366,13 +375,13 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_in_locked(&sony_laptop_input.fifo, - (unsigned char *)&kp, sizeof(kp), - &sony_laptop_input.fifo_lock); - if (!work_pending(&sony_laptop_release_key_work)) - queue_work(sony_laptop_input.wq, - &sony_laptop_release_key_work); + /* schedule key release */ + kfifo_in_locked(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp), + &sony_laptop_input.fifo_lock); + schedule_delayed_work(&sony_laptop_release_key_work, + msecs_to_jiffies(10)); } else dprintk("unknown input event %.2x\n", event); } @@ -390,27 +399,18 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); - error = - kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); + error = kfifo_alloc(&sony_laptop_input.fifo, + SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); goto err_dec_users; } - /* init workqueue */ - sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); - if (!sony_laptop_input.wq) { - printk(KERN_ERR DRV_PFX - "Unable to create workqueue.\n"); - error = -ENXIO; - goto err_free_kfifo; - } - /* input keys */ key_dev = input_allocate_device(); if (!key_dev) { error = -ENOMEM; - goto err_destroy_wq; + goto err_free_kfifo; } key_dev->name = "Sony Vaio Keys"; @@ -473,9 +473,6 @@ err_unregister_keydev: err_free_keydev: input_free_device(key_dev); -err_destroy_wq: - destroy_workqueue(sony_laptop_input.wq); - err_free_kfifo: kfifo_free(&sony_laptop_input.fifo); @@ -486,12 +483,23 @@ err_dec_users: static void sony_laptop_remove_input(void) { - /* cleanup only after the last user has gone */ + struct sony_laptop_keypress kp = { NULL }; + + /* Cleanup only after the last user has gone */ if (!atomic_dec_and_test(&sony_laptop_input.users)) return; - /* flush workqueue first */ - flush_workqueue(sony_laptop_input.wq); + cancel_delayed_work_sync(&sony_laptop_release_key_work); + + /* + * Generate key-up events for remaining keys. Note that we don't + * need locking since nobody is adding new events to the kfifo. + */ + while (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { + input_report_key(kp.dev, kp.key, 0); + input_sync(kp.dev); + } /* destroy input devs */ input_unregister_device(sony_laptop_input.key_dev); @@ -502,7 +510,6 @@ static void sony_laptop_remove_input(void) sony_laptop_input.jog_dev = NULL; } - destroy_workqueue(sony_laptop_input.wq); kfifo_free(&sony_laptop_input.fifo); } -- cgit v1.2.3-70-g09d2 From c45bc9d62c39202b401d1bf7bb2812abb88798a1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 00:02:23 -0800 Subject: sony-laptop - simplify keymap initialization Also use input_set_capability() helper instead of manipulating bits directly. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index c42d35ba73d6..b7aa959b0c05 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -419,18 +419,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) key_dev->dev.parent = &acpi_device->dev; /* Initialize the Input Drivers: special keys */ - set_bit(EV_KEY, key_dev->evbit); - set_bit(EV_MSC, key_dev->evbit); - set_bit(MSC_SCAN, key_dev->mscbit); + input_set_capability(key_dev, EV_MSC, MSC_SCAN); + + __set_bit(EV_KEY, key_dev->evbit); key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); key_dev->keycode = &sony_laptop_input_keycode_map; - for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { - if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { - set_bit(sony_laptop_input_keycode_map[i], - key_dev->keybit); - } - } + for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) + __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit); + __clear_bit(KEY_RESERVED, key_dev->keybit); error = input_register_device(key_dev); if (error) @@ -450,9 +447,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) jog_dev->id.vendor = PCI_VENDOR_ID_SONY; key_dev->dev.parent = &acpi_device->dev; - jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); - jog_dev->relbit[0] = BIT_MASK(REL_WHEEL); + input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE); + input_set_capability(jog_dev, EV_REL, REL_WHEEL); error = input_register_device(jog_dev); if (error) -- cgit v1.2.3-70-g09d2 From cffdde993a016bedbc2f5eb60d00c3a766ffb612 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 00:02:30 -0800 Subject: sony-laptop - switch from workqueue to a timer The function that is executing in workqueue context does not need to sleep so let's switch to a timer which is more lightweight. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index b7aa959b0c05..cc7172ea19dd 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -145,6 +145,7 @@ struct sony_laptop_input_s { struct input_dev *key_dev; struct kfifo fifo; spinlock_t fifo_lock; + struct timer_list release_key_timer; }; static struct sony_laptop_input_s sony_laptop_input = { @@ -298,10 +299,8 @@ static int sony_laptop_input_keycode_map[] = { }; /* release buttons after a short delay if pressed */ -static void do_sony_laptop_release_key(struct work_struct *work) +static void do_sony_laptop_release_key(unsigned long unused) { - struct delayed_work *dwork = - container_of(work, struct delayed_work, work); struct sony_laptop_keypress kp; unsigned long flags; @@ -315,14 +314,12 @@ static void do_sony_laptop_release_key(struct work_struct *work) /* If there is something in the fifo schedule next release. */ if (kfifo_len(&sony_laptop_input.fifo) != 0) - schedule_delayed_work(dwork, msecs_to_jiffies(10)); + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); } -static DECLARE_DELAYED_WORK(sony_laptop_release_key_work, - do_sony_laptop_release_key); - /* forward event to the input subsystem */ static void sony_laptop_report_input_event(u8 event) { @@ -380,8 +377,8 @@ static void sony_laptop_report_input_event(u8 event) kfifo_in_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, sizeof(kp), &sony_laptop_input.fifo_lock); - schedule_delayed_work(&sony_laptop_release_key_work, - msecs_to_jiffies(10)); + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); } else dprintk("unknown input event %.2x\n", event); } @@ -406,6 +403,9 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) goto err_dec_users; } + setup_timer(&sony_laptop_input.release_key_timer, + do_sony_laptop_release_key, 0); + /* input keys */ key_dev = input_allocate_device(); if (!key_dev) { @@ -485,7 +485,7 @@ static void sony_laptop_remove_input(void) if (!atomic_dec_and_test(&sony_laptop_input.users)) return; - cancel_delayed_work_sync(&sony_laptop_release_key_work); + del_timer_sync(&sony_laptop_input.release_key_timer); /* * Generate key-up events for remaining keys. Note that we don't -- cgit v1.2.3-70-g09d2 From da8ba01deb98f3dc0558b1f5a37e64f40bba7904 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 6 Jan 2010 22:07:37 +0100 Subject: eeepc-laptop: disable cpu speed control on EeePC 701 The EeePC 4G ("701") implements CFVS, but it is not supported by the pre-installed OS, and the original option to change it in the BIOS setup screen was removed in later versions. Judging by the lack of "Super Hybrid Engine" on Asus product pages, this applies to all "701" models (4G/4G Surf/2G Surf). So Asus made a deliberate decision not to support it on this model. We have several reports that using it can cause the system to hang [1]. That said, it does not happen all the time. Some users do not experience it at all (and apparently wish to continue "right-clocking"). Check for the EeePC 701 using DMI. If met, then disable writes to the "cpufv" sysfs attribute and log an explanatory message. Add a "cpufv_disabled" attribute which allow users to override this policy. Writing to this attribute will log a second message. The sysfs attribute is more useful than a module option, because it makes it easier for userspace scripts to provide consistent behaviour (according to user configuration), regardless of whether the kernel includes this change. [1] Signed-off-by: Alan Jenkins Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb3..e954f2af5724 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -35,6 +35,7 @@ #include #include #include +#include #define EEEPC_LAPTOP_VERSION "0.1" #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" @@ -159,6 +160,7 @@ struct eeepc_laptop { acpi_handle handle; /* the handle of the acpi device */ u32 cm_supported; /* the control methods supported by this BIOS */ + bool cpufv_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev, struct eeepc_cpufv c; int rv, value; + if (eeepc->cpufv_disabled) + return -EPERM; if (get_cpufv(eeepc, &c)) return -ENODEV; rv = parse_arg(buf, count, &value); @@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev, return rv; } +static ssize_t show_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", eeepc->cpufv_disabled); +} + +static ssize_t store_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + int rv, value; + + rv = parse_arg(buf, count, &value); + if (rv < 0) + return rv; + + switch (value) { + case 0: + if (eeepc->cpufv_disabled) + pr_warning("cpufv enabled (not officially supported " + "on this model)\n"); + eeepc->cpufv_disabled = false; + return rv; + case 1: + return -EPERM; + default: + return -EINVAL; + } +} + + static struct device_attribute dev_attr_cpufv = { .attr = { .name = "cpufv", @@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = { .show = show_available_cpufv }; +static struct device_attribute dev_attr_cpufv_disabled = { + .attr = { + .name = "cpufv_disabled", + .mode = 0644 }, + .show = show_cpufv_disabled, + .store = store_cpufv_disabled +}; + + 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, + &dev_attr_cpufv_disabled.attr, NULL }; @@ -1261,6 +1310,42 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) } } +static void eeepc_dmi_check(struct eeepc_laptop *eeepc) +{ + const char *model; + + /* + * Blacklist for setting cpufv (cpu speed). + * + * EeePC 4G ("701") implements CFVS, but it is not supported + * by the pre-installed OS, and the original option to change it + * in the BIOS setup screen was removed in later versions. + * + * Judging by the lack of "Super Hybrid Engine" on Asus product pages, + * this applies to all "701" models (4G/4G Surf/2G Surf). + * + * So Asus made a deliberate decision not to support it on this model. + * We have several reports that using it can cause the system to hang + * + * The hang has also been reported on a "702" (Model name "8G"?). + * + * We avoid dmi_check_system() / dmi_match(), because they use + * substring matching. We don't want to affect the "701SD" + * and "701SDX" models, because they do support S.H.E. + */ + + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + + if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { + eeepc->cpufv_disabled = true; + pr_info("model %s does not officially support setting cpu " + "speed\n", model); + pr_info("cpufv disabled to avoid instability\n"); + } +} + static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) { int dummy; @@ -1342,6 +1427,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc_dmi_check(eeepc); + result = eeepc_acpi_init(eeepc, device); if (result) goto fail_platform; -- cgit v1.2.3-70-g09d2 From 10ae4b5663ff3092553bfbd867e7bd474ce6c553 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:38 +0100 Subject: eeepc-laptop: dmi blacklist to disable pci hotplug code This is a short term workaround for Eeepc 1005HA. refs: Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e954f2af5724..7fc944ac2070 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -161,6 +161,7 @@ struct eeepc_laptop { u32 cm_supported; /* the control methods supported by this BIOS */ bool cpufv_disabled; + bool hotplug_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -845,6 +846,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) if (result && result != -ENODEV) goto exit; + if (eeepc->hotplug_disabled) + return 0; + result = eeepc_setup_pci_hotplug(eeepc); /* * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1314,6 +1318,10 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) { const char *model; + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + /* * Blacklist for setting cpufv (cpu speed). * @@ -1333,17 +1341,24 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * substring matching. We don't want to affect the "701SD" * and "701SDX" models, because they do support S.H.E. */ - - model = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!model) - return; - if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { eeepc->cpufv_disabled = true; pr_info("model %s does not officially support setting cpu " "speed\n", model); pr_info("cpufv disabled to avoid instability\n"); } + + /* + * Blacklist for wlan hotplug + * + * Eeepc 1005HA doesn't work like others models and don't need the + * hotplug code. In fact, current hotplug code seems to unplug another + * device... + */ + if (strcmp(model, "1005HA") == 0) { + eeepc->hotplug_disabled = true; + pr_info("wlan hotplug disabled\n"); + } } static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) -- cgit v1.2.3-70-g09d2 From 642e0447cb910ceabae0b4ea6c0cd3449d5c5abb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 22:07:39 +0100 Subject: eeepc-laptop: switch to using sparse keymap library Signed-off-by: Dmitry Torokhov Tested-by: Alan Jenkins Acked-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/eeepc-laptop.c | 186 ++++++++++-------------------------- 2 files changed, 52 insertions(+), 135 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e3605..f526e735c5ab 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -364,6 +364,7 @@ config EEEPC_LAPTOP select HWMON select LEDS_CLASS select NEW_LEDS + select INPUT_SPARSEKMAP ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 7fc944ac2070..07d7978c558f 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -121,38 +122,28 @@ static const char *cm_setv[] = { NULL, NULL, "PBPS", "TPDS" }; -struct key_entry { - char type; - u8 code; - u16 keycode; -}; - -enum { KE_KEY, KE_END }; - static const 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 }, - {KE_KEY, 0x15, KEY_VOLUMEUP }, - {KE_KEY, 0x16, KEY_DISPLAY_OFF }, - {KE_KEY, 0x1a, KEY_COFFEE }, - {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_MAX, KEY_BRIGHTNESSUP }, - {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ - {KE_KEY, 0x38, KEY_F14 }, - {KE_END, 0}, + { 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 } }, + { KE_KEY, 0x15, { KEY_VOLUMEUP } }, + { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, + { KE_KEY, 0x1a, { KEY_COFFEE } }, + { 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_MAX, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ + { KE_KEY, 0x38, { KEY_F14 } }, + { KE_END, 0 }, }; - /* * This is the main structure, we can use it to store useful information */ @@ -1143,120 +1134,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) /* * Input device (i.e. hotkeys) */ -static struct key_entry *eeepc_get_entry_by_scancode( - struct eeepc_laptop *eeepc, - int code) +static int eeepc_input_init(struct eeepc_laptop *eeepc) { - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->code) - return key; + struct input_dev *input; + int error; - return NULL; -} - -static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) -{ - static struct key_entry *key; - - key = eeepc_get_entry_by_scancode(eeepc, event); - if (key) { - switch (key->type) { - case KE_KEY: - input_report_key(eeepc->inputdev, key->keycode, - 1); - input_sync(eeepc->inputdev); - input_report_key(eeepc->inputdev, key->keycode, - 0); - input_sync(eeepc->inputdev); - break; - } + input = input_allocate_device(); + if (!input) { + pr_info("Unable to allocate input device\n"); + return -ENOMEM; } -} - -static struct key_entry *eeepc_get_entry_by_keycode( - struct eeepc_laptop *eeepc, int code) -{ - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->keycode && key->type == KE_KEY) - return key; - return NULL; -} + input->name = "Asus EeePC extra buttons"; + input->phys = EEEPC_LAPTOP_FILE "/input0"; + input->id.bustype = BUS_HOST; + input->dev.parent = &eeepc->platform_device->dev; -static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + error = sparse_keymap_setup(input, eeepc_keymap, NULL); + if (error) { + pr_err("Unable to setup input device keymap\n"); + goto err_free_dev; } - return -EINVAL; -} - -static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = eeepc_get_entry_by_scancode(eeepc, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + error = input_register_device(input); + if (error) { + pr_err("Unable to register input device\n"); + goto err_free_keymap; } - return -EINVAL; -} - -static int eeepc_input_init(struct eeepc_laptop *eeepc) -{ - const struct key_entry *key; - int result; - - eeepc->inputdev = input_allocate_device(); - if (!eeepc->inputdev) { - pr_info("Unable to allocate input device\n"); - return -ENOMEM; - } - eeepc->inputdev->name = "Asus EeePC extra buttons"; - eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; - eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; - eeepc->inputdev->id.bustype = BUS_HOST; - eeepc->inputdev->getkeycode = eeepc_getkeycode; - eeepc->inputdev->setkeycode = eeepc_setkeycode; - input_set_drvdata(eeepc->inputdev, eeepc); - - eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), - GFP_KERNEL); - for (key = eeepc_keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, eeepc->inputdev->evbit); - set_bit(key->keycode, eeepc->inputdev->keybit); - break; - } - } - result = input_register_device(eeepc->inputdev); - if (result) { - pr_info("Unable to register input device\n"); - input_free_device(eeepc->inputdev); - return result; - } + eeepc->inputdev = input; return 0; + + err_free_keymap: + sparse_keymap_free(input); + err_free_dev: + input_free_device(input); + return error; } static void eeepc_input_exit(struct eeepc_laptop *eeepc) @@ -1306,11 +1219,12 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) * event will be desired value (or else ignored) */ } - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, + 1, true); } } else { /* Everything else is a bona-fide keypress event */ - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, 1, true); } } @@ -1554,10 +1468,12 @@ static int __init eeepc_laptop_init(void) result = acpi_bus_register_driver(&eeepc_acpi_driver); if (result < 0) goto fail_acpi_driver; + if (!eeepc_device_present) { result = -ENODEV; goto fail_no_device; } + return 0; fail_no_device: -- cgit v1.2.3-70-g09d2 From 322a1356be96bcc4b97e8e370f6468c821330077 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:40 +0100 Subject: eeepc-laptop: add hotplug_disable parameter Some new models need to disable wireless hotplug. For the moment, we don't know excactly what models need that, except 1005HA. Users will be able to use that param as a workaround. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 07d7978c558f..a959abdea3a7 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -50,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); MODULE_LICENSE("GPL"); +static bool hotplug_disabled; + +module_param(hotplug_disabled, bool, 0644); +MODULE_PARM_DESC(hotplug_disabled, + "Disable hotplug for wireless device. " + "If your laptop need that, please report to " + "acpi4asus-user@lists.sourceforge.net."); + /* * Definitions for Asus EeePC */ @@ -1356,6 +1364,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc->hotplug_disabled = hotplug_disabled; + eeepc_dmi_check(eeepc); result = eeepc_acpi_init(eeepc, device); -- cgit v1.2.3-70-g09d2 From 4194e2f551a6308e6ab34ac88210bf54858aa7df Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:41 +0100 Subject: eeepc-laptop: disable wireless hotplug for 1201N Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index a959abdea3a7..e2be6bb33d92 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1277,7 +1277,7 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * hotplug code. In fact, current hotplug code seems to unplug another * device... */ - if (strcmp(model, "1005HA") == 0) { + if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { eeepc->hotplug_disabled = true; pr_info("wlan hotplug disabled\n"); } -- cgit v1.2.3-70-g09d2 From c14973f93027500301fc40333e16ae49e58923a7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 10 Jan 2010 00:15:44 -0800 Subject: sony-laptop - fix using of uninitialized variable CC [M] drivers/platform/x86/sony-laptop.o drivers/platform/x86/sony-laptop.c: In function 'sony_nc_rfkill_setup': drivers/platform/x86/sony-laptop.c:1162: warning: 'i' may be used uninitialized in this function Signed-off-by: Dmitry Torokhov Acked-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6f..3f71a605a492 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) /* the buffer is filled with magic numbers describing the devices * available, 0xff terminates the enumeration */ - while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && - i < device_enum->buffer.length) { - i++; + for (i = 0; i < device_enum->buffer.length; i++) { + + dev_code = *(device_enum->buffer.pointer + i); + if (dev_code == 0xff) + break; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) -- cgit v1.2.3-70-g09d2 From 439913fffd39374c3737186b22d2d56c3a0ae526 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 28 Jan 2010 10:53:19 +0800 Subject: ACPI: replace acpi_integer by u64 acpi_integer is now obsolete and removed from the ACPICA code base, replaced by u64. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- arch/ia64/hp/common/aml_nfw.c | 6 ++--- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 6 ++--- drivers/acpi/battery.c | 4 +-- drivers/acpi/ec.c | 4 +-- drivers/acpi/glue.c | 4 +-- drivers/acpi/osl.c | 4 +-- drivers/acpi/power_meter.c | 30 +++++++++++----------- drivers/acpi/processor_idle.c | 2 +- drivers/acpi/processor_throttling.c | 24 +++++++++--------- drivers/acpi/utils.c | 16 ++++++------ drivers/acpi/video.c | 2 +- drivers/ata/libata-acpi.c | 4 +-- drivers/ide/ide-acpi.c | 8 +++--- drivers/input/misc/atlas_btns.c | 2 +- drivers/pci/pci-acpi.c | 2 +- drivers/platform/x86/toshiba_bluetooth.c | 4 +-- drivers/platform/x86/wmi.c | 4 +-- include/acpi/acpi_bus.h | 6 ++--- include/acpi/processor.h | 42 +++++++++++++++---------------- 19 files changed, 87 insertions(+), 87 deletions(-) (limited to 'drivers/platform') diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c index 4abd2c79bb1d..22078486d35d 100644 --- a/arch/ia64/hp/common/aml_nfw.c +++ b/arch/ia64/hp/common/aml_nfw.c @@ -77,7 +77,7 @@ static void aml_nfw_execute(struct ia64_nfw_context *c) c->arg[4], c->arg[5], c->arg[6], c->arg[7]); } -static void aml_nfw_read_arg(u8 *offset, u32 bit_width, acpi_integer *value) +static void aml_nfw_read_arg(u8 *offset, u32 bit_width, u64 *value) { switch (bit_width) { case 8: @@ -95,7 +95,7 @@ static void aml_nfw_read_arg(u8 *offset, u32 bit_width, acpi_integer *value) } } -static void aml_nfw_write_arg(u8 *offset, u32 bit_width, acpi_integer *value) +static void aml_nfw_write_arg(u8 *offset, u32 bit_width, u64 *value) { switch (bit_width) { case 8: @@ -114,7 +114,7 @@ static void aml_nfw_write_arg(u8 *offset, u32 bit_width, acpi_integer *value) } static acpi_status aml_nfw_handler(u32 function, acpi_physical_address address, - u32 bit_width, acpi_integer *value, void *handler_context, + u32 bit_width, u64 *value, void *handler_context, void *region_context) { struct ia64_nfw_context *context = handler_context; diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index f125e5c551c0..55d42bc443e8 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -806,7 +806,7 @@ static int find_psb_table(struct powernow_k8_data *data) static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { - acpi_integer control; + u64 control; if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) return; @@ -824,7 +824,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { struct cpufreq_frequency_table *powernow_table; int ret_val = -ENODEV; - acpi_integer control, status; + u64 control, status; if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { dprintk("register performance failed: bad ACPI data\n"); @@ -948,7 +948,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, u32 fid; u32 vid; u32 freq, index; - acpi_integer status, control; + u64 status, control; if (data->exttype) { status = data->acpi_data.states[i].status; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index cada73ffdfa7..58d2c91ba62b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -324,8 +324,8 @@ static int extract_package(struct acpi_battery *battery, strncpy(ptr, element->string.pointer, 32); else if (element->type == ACPI_TYPE_INTEGER) { strncpy(ptr, (u8 *)&element->integer.value, - sizeof(acpi_integer)); - ptr[sizeof(acpi_integer)] = 0; + sizeof(u64)); + ptr[sizeof(u64)] = 0; } else *ptr = 0; /* don't have value */ } else { diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d6471bb6852f..748ced85dec5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -589,7 +589,7 @@ static u32 acpi_ec_gpe_handler(void *data) static acpi_status acpi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer *value, + u32 bits, u64 *value, void *handler_context, void *region_context) { struct acpi_ec *ec = handler_context; @@ -620,7 +620,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, ++address; if (function == ACPI_READ) { result = acpi_ec_read(ec, address, &temp); - (*value) |= ((acpi_integer)temp) << i; + (*value) |= ((u64)temp) << i; } else { temp = 0xff & ((*value) >> i); result = acpi_ec_write(ec, address, temp); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 4c8fcff662cf..6d5b64b7d526 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -87,7 +87,7 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) /* Get device's handler per its address under its parent */ struct acpi_find_child { acpi_handle handle; - acpi_integer address; + u64 address; }; static acpi_status @@ -106,7 +106,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address) +acpi_handle acpi_get_child(acpi_handle parent, u64 address) { struct acpi_find_child find = { NULL, address }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 02e8464e480f..8e6d8665f0ae 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -436,7 +436,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) * Running in interpreter thread context, safe to sleep */ -void acpi_os_sleep(acpi_integer ms) +void acpi_os_sleep(u64 ms) { schedule_timeout_interruptible(msecs_to_jiffies(ms)); } @@ -603,7 +603,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, acpi_status acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, - acpi_integer value, u32 width) + u64 value, u32 width) { int result, size; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index dc4ffadf8122..834c5af0de4b 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -71,17 +71,17 @@ static const struct acpi_device_id power_meter_ids[] = { MODULE_DEVICE_TABLE(acpi, power_meter_ids); struct acpi_power_meter_capabilities { - acpi_integer flags; - acpi_integer units; - acpi_integer type; - acpi_integer accuracy; - acpi_integer sampling_time; - acpi_integer min_avg_interval; - acpi_integer max_avg_interval; - acpi_integer hysteresis; - acpi_integer configurable_cap; - acpi_integer min_cap; - acpi_integer max_cap; + u64 flags; + u64 units; + u64 type; + u64 accuracy; + u64 sampling_time; + u64 min_avg_interval; + u64 max_avg_interval; + u64 hysteresis; + u64 configurable_cap; + u64 min_cap; + u64 max_cap; }; struct acpi_power_meter_resource { @@ -93,9 +93,9 @@ struct acpi_power_meter_resource { acpi_string model_number; acpi_string serial_number; acpi_string oem_info; - acpi_integer power; - acpi_integer cap; - acpi_integer avg_interval; + u64 power; + u64 cap; + u64 avg_interval; int sensors_valid; unsigned long sensors_last_updated; struct sensor_device_attribute sensors[NUM_SENSORS]; @@ -402,7 +402,7 @@ static ssize_t show_val(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - acpi_integer val = 0; + u64 val = 0; switch (attr->index) { case 0: diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7c0441f63b39..3455d7abf5f3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -352,7 +352,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { acpi_status status = 0; - acpi_integer count; + u64 count; int current_count; int i; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 1c5d7a8b2fdf..7ded7542fc9d 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -660,7 +660,7 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) #ifdef CONFIG_X86 static int acpi_throttling_rdmsr(struct acpi_processor *pr, - acpi_integer * value) + u64 *value) { struct cpuinfo_x86 *c; u64 msr_high, msr_low; @@ -681,13 +681,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr, rdmsr_safe(MSR_IA32_THERM_CONTROL, (u32 *)&msr_low , (u32 *) &msr_high); msr = (msr_high << 32) | msr_low; - *value = (acpi_integer) msr; + *value = (u64) msr; ret = 0; } return ret; } -static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) { struct cpuinfo_x86 *c; unsigned int cpu; @@ -711,14 +711,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) } #else static int acpi_throttling_rdmsr(struct acpi_processor *pr, - acpi_integer * value) + u64 *value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); return -1; } -static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); @@ -727,7 +727,7 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) #endif static int acpi_read_throttling_status(struct acpi_processor *pr, - acpi_integer *value) + u64 *value) { u32 bit_width, bit_offset; u64 ptc_value; @@ -746,7 +746,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, address, (u32 *) &ptc_value, (u32) (bit_width + bit_offset)); ptc_mask = (1 << bit_width) - 1; - *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); + *value = (u64) ((ptc_value >> bit_offset) & ptc_mask); ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: @@ -760,7 +760,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, } static int acpi_write_throttling_state(struct acpi_processor *pr, - acpi_integer value) + u64 value) { u32 bit_width, bit_offset; u64 ptc_value; @@ -793,7 +793,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr, } static int acpi_get_throttling_state(struct acpi_processor *pr, - acpi_integer value) + u64 value) { int i; @@ -808,7 +808,7 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, } static int acpi_get_throttling_value(struct acpi_processor *pr, - int state, acpi_integer *value) + int state, u64 *value) { int ret = -1; @@ -826,7 +826,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) { int state = 0; int ret; - acpi_integer value; + u64 value; if (!pr) return -EINVAL; @@ -993,7 +993,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state, bool force) { int ret; - acpi_integer value; + u64 value; if (!pr) return -EINVAL; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 811fec10462b..11882dbe2094 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -107,12 +107,12 @@ acpi_extract_package(union acpi_object *package, case ACPI_TYPE_INTEGER: switch (format_string[i]) { case 'N': - size_required += sizeof(acpi_integer); - tail_offset += sizeof(acpi_integer); + size_required += sizeof(u64); + tail_offset += sizeof(u64); break; case 'S': size_required += - sizeof(char *) + sizeof(acpi_integer) + + sizeof(char *) + sizeof(u64) + sizeof(char); tail_offset += sizeof(char *); break; @@ -193,17 +193,17 @@ acpi_extract_package(union acpi_object *package, case ACPI_TYPE_INTEGER: switch (format_string[i]) { case 'N': - *((acpi_integer *) head) = + *((u64 *) head) = element->integer.value; - head += sizeof(acpi_integer); + head += sizeof(u64); break; case 'S': pointer = (u8 **) head; *pointer = tail; - *((acpi_integer *) tail) = + *((u64 *) tail) = element->integer.value; - head += sizeof(acpi_integer *); - tail += sizeof(acpi_integer); + head += sizeof(u64 *); + tail += sizeof(u64); /* NULL terminate string */ *tail = (char)0; tail += sizeof(char); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b765790b32be..6e9b49149fce 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -759,7 +759,7 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video, static int acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) { - acpi_integer status = 0; + u64 status = 0; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 1245838ac13d..292fdbc0431a 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -64,7 +64,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA)); if (!sata_pmp_attached(ap)) { - acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); + u64 adr = SATA_ADR(ap->port_no, NO_PORT_MULT); ap->link.device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); @@ -74,7 +74,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) ap->link.device->acpi_handle = NULL; ata_for_each_link(link, ap, EDGE) { - acpi_integer adr = SATA_ADR(ap->port_no, link->pmp); + u64 adr = SATA_ADR(ap->port_no, link->pmp); link->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index c0cf45a11b93..5cb01e5c323c 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -108,11 +108,11 @@ bool ide_port_acpi(ide_hwif_t *hwif) * Returns 0 on success, <0 on error. */ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, - acpi_integer *pcidevfn) + u64 *pcidevfn) { struct pci_dev *pdev = to_pci_dev(dev); unsigned int bus, devnum, func; - acpi_integer addr; + u64 addr; acpi_handle dev_handle; acpi_status status; struct acpi_device_info *dinfo = NULL; @@ -122,7 +122,7 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, devnum = PCI_SLOT(pdev->devfn); func = PCI_FUNC(pdev->devfn); /* ACPI _ADR encoding for PCI bus: */ - addr = (acpi_integer)(devnum << 16 | func); + addr = (u64)(devnum << 16 | func); DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func); @@ -169,7 +169,7 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) { struct device *dev = hwif->gendev.parent; acpi_handle uninitialized_var(dev_handle); - acpi_integer pcidevfn; + u64 pcidevfn; acpi_handle chan_handle; int err; diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 1b871917340a..dfaa9a045ed8 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -47,7 +47,7 @@ static acpi_status acpi_atlas_button_setup(acpi_handle region_handle, static acpi_status acpi_atlas_button_handler(u32 function, acpi_physical_address address, - u32 bit_width, acpi_integer *value, + u32 bit_width, u64 *value, void *handler_context, void *region_context) { acpi_status status; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7e2829538a4c..441326c44138 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -143,7 +143,7 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { struct pci_dev * pci_dev; - acpi_integer addr; + u64 addr; pci_dev = to_pci_dev(dev); /* Please ref to ACPI spec for the syntax of _ADR */ diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index a350418e87ea..944068611919 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -57,7 +57,7 @@ static struct acpi_driver toshiba_bt_rfkill_driver = { static int toshiba_bluetooth_enable(acpi_handle handle) { acpi_status res1, res2; - acpi_integer result; + u64 result; /* * Query ACPI to verify RFKill switch is set to 'on'. @@ -95,7 +95,7 @@ static int toshiba_bt_resume(struct acpi_device *device) static int toshiba_bt_rfkill_add(struct acpi_device *device) { acpi_status status; - acpi_integer bt_present; + u64 bt_present; int result = -ENODEV; /* diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index b104302fea0a..09e9918c69c1 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -796,7 +796,7 @@ static __init acpi_status parse_wdg(acpi_handle handle) */ static acpi_status acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer * value, + u32 bits, u64 *value, void *handler_context, void *region_context) { int result = 0, i = 0; @@ -813,7 +813,7 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, if (function == ACPI_READ) { result = ec_read(address, &temp); - (*value) |= ((acpi_integer)temp) << i; + (*value) |= ((u64)temp) << i; } else { temp = 0xff & ((*value) >> i); result = ec_write(address, temp); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3cd9ccdcbd8f..71c105c9b0ee 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -250,8 +250,8 @@ struct acpi_device_wakeup_state { struct acpi_device_wakeup { acpi_handle gpe_device; - acpi_integer gpe_number; - acpi_integer sleep_state; + u64 gpe_number; + u64 sleep_state; struct acpi_handle_list resources; struct acpi_device_wakeup_state state; struct acpi_device_wakeup_flags flags; @@ -380,7 +380,7 @@ struct acpi_pci_root { }; /* helper */ -acpi_handle acpi_get_child(acpi_handle, acpi_integer); +acpi_handle acpi_get_child(acpi_handle, u64); int acpi_is_root_bridge(acpi_handle); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 0ea5ef4eb6a9..29831768c0e6 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -92,11 +92,11 @@ struct acpi_processor_power { /* Performance Management */ struct acpi_psd_package { - acpi_integer num_entries; - acpi_integer revision; - acpi_integer domain; - acpi_integer coord_type; - acpi_integer num_processors; + u64 num_entries; + u64 revision; + u64 domain; + u64 coord_type; + u64 num_processors; } __attribute__ ((packed)); struct acpi_pct_register { @@ -110,12 +110,12 @@ struct acpi_pct_register { } __attribute__ ((packed)); struct acpi_processor_px { - acpi_integer core_frequency; /* megahertz */ - acpi_integer power; /* milliWatts */ - acpi_integer transition_latency; /* microseconds */ - acpi_integer bus_master_latency; /* microseconds */ - acpi_integer control; /* control value */ - acpi_integer status; /* success indicator */ + u64 core_frequency; /* megahertz */ + u64 power; /* milliWatts */ + u64 transition_latency; /* microseconds */ + u64 bus_master_latency; /* microseconds */ + u64 control; /* control value */ + u64 status; /* success indicator */ }; struct acpi_processor_performance { @@ -133,11 +133,11 @@ struct acpi_processor_performance { /* Throttling Control */ struct acpi_tsd_package { - acpi_integer num_entries; - acpi_integer revision; - acpi_integer domain; - acpi_integer coord_type; - acpi_integer num_processors; + u64 num_entries; + u64 revision; + u64 domain; + u64 coord_type; + u64 num_processors; } __attribute__ ((packed)); struct acpi_ptc_register { @@ -151,11 +151,11 @@ struct acpi_ptc_register { } __attribute__ ((packed)); struct acpi_processor_tx_tss { - acpi_integer freqpercentage; /* */ - acpi_integer power; /* milliWatts */ - acpi_integer transition_latency; /* microseconds */ - acpi_integer control; /* control value */ - acpi_integer status; /* success indicator */ + u64 freqpercentage; /* */ + u64 power; /* milliWatts */ + u64 transition_latency; /* microseconds */ + u64 control; /* control value */ + u64 status; /* success indicator */ }; struct acpi_processor_tx { u16 power; -- cgit v1.2.3-70-g09d2 From 9ddc5b6f18fbac07d2746566b73b89e89fdd4e6a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 20 Jan 2010 17:02:24 +0100 Subject: tree-wide: fix typos "ammount" -> "amount" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- arch/powerpc/mm/init_32.c | 2 +- drivers/char/serial167.c | 2 +- drivers/isdn/sc/hardware.h | 2 +- drivers/message/i2o/iop.c | 2 +- drivers/net/ks8851.c | 2 +- drivers/platform/x86/thinkpad_acpi.c | 4 ++-- drivers/scsi/libfc/fc_fcp.c | 2 +- drivers/serial/samsung.c | 2 +- drivers/usb/serial/opticon.c | 2 +- drivers/usb/serial/symbolserial.c | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/platform') diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 4ec900af332f..b1dbd9ee87cc 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -47,7 +47,7 @@ #include "mmu_decl.h" #if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL) -/* The ammount of lowmem must be within 0xF0000000 - KERNELBASE. */ +/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */ #if (CONFIG_LOWMEM_SIZE > (0xF0000000 - PAGE_OFFSET)) #error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL" #endif diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 452370af95de..aee3c0d1759f 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1990,7 +1990,7 @@ void mvme167_serial_console_setup(int cflag) /* * Attempt to set up all channels to something reasonable, and * bang out a INIT_CHAN command. We should then be able to limit - * the ammount of fiddling we have to do in normal running. + * the amount of fiddling we have to do in normal running. */ for (ch = 3; ch >= 0; ch--) { diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index 9e6d5302bf8e..627324856ead 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h @@ -87,7 +87,7 @@ #define BRI_CHANNELS 2 /* Number of B channels */ #define BRI_BASEPG_VAL 0x98 #define BRI_MAGIC 0x60000 /* Magic Number */ -#define BRI_MEMSIZE 0x10000 /* Ammount of RAM (64K) */ +#define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */ #define BRI_PARTNO "72-029" #define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; /* diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index e5ab62141503..ef5ce2676f05 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -539,7 +539,7 @@ static int i2o_iop_reset(struct i2o_controller *c) * which is indeterminate. We need to wait until the IOP has * rebooted before we can let the system talk to it. We read * the inbound Free_List until a message is available. If we - * can't read one in the given ammount of time, we assume the + * can't read one in the given amount of time, we assume the * IOP could not reboot properly. */ osm_debug("%s: Reset in progress, waiting for reboot...\n", diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 6d3ac65bc35c..cfebe0e218fc 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -407,7 +407,7 @@ static irqreturn_t ks8851_irq(int irq, void *pw) * @buff: The buffer address * @len: The length of the data to read * - * Issue an RXQ FIFO read command and read the @len ammount of data from + * Issue an RXQ FIFO read command and read the @len amount of data from * the FIFO into the buffer specified by @buff. */ static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e67e4feb35cb..215621c31c5f 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1667,7 +1667,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) * Table of recommended minimum BIOS versions * * Reasons for listing: - * 1. Stable BIOS, listed because the unknown ammount of + * 1. Stable BIOS, listed because the unknown amount of * bugs and bad ACPI behaviour on older versions * * 2. BIOS or EC fw with known bugs that trigger on Linux @@ -7070,7 +7070,7 @@ static struct ibm_struct volume_driver_data = { * * Fan speed changes of any sort (including those caused by the * disengaged mode) are usually done slowly by the firmware as the - * maximum ammount of fan duty cycle change per second seems to be + * maximum amount of fan duty cycle change per second seems to be * limited. * * Reading is not available if GFAN exists. diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 881d5dfe8c74..96ee599d9a05 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -522,7 +522,7 @@ crc_err: * * Called after receiving a Transfer Ready data descriptor. * If the LLD is capable of sequence offload then send down the - * seq_blen ammount of data in single frame, otherwise send + * seq_blen amount of data in single frame, otherwise send * multiple frames of the maximum frame payload supported by * the target port. */ diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 52e3df113ec0..03c010af966b 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -1271,7 +1271,7 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) unsigned long ufstat, utrstat; if (ufcon & S3C2410_UFCON_FIFOMODE) { - /* fifo mode - check ammount of data in fifo registers... */ + /* fifo mode - check amount of data in fifo registers... */ ufstat = rd_regl(port, S3C2410_UFSTAT); return (ufstat & info->tx_fifofull) ? 0 : 1; diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 4cdb975caa89..96937f1b8b97 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -120,7 +120,7 @@ static void opticon_bulk_callback(struct urb *urb) } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index b282c0f2d8e5..aebfcf699644 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -100,7 +100,7 @@ static void symbol_int_callback(struct urb *urb) } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } -- cgit v1.2.3-70-g09d2 From f04d5e012d73ea441bd39804ace39fd6d1ce5611 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 14:37:58 -0800 Subject: thinkpad-acpi: wrong thermal attribute_group removed in thermal_exit() sysfs_remove_group() removed the wrong attribute_group for thermal_read_mode TPEC_8, ACPI_TMP07 and ACPI_UPDT Signed-off-by: Roel Kluin Acked-by: Henrique de Moraes Holschuh Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e67e4feb35cb..eb603f1d55ca 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -5771,7 +5771,7 @@ static void thermal_exit(void) case TPACPI_THERMAL_ACPI_TMP07: case TPACPI_THERMAL_ACPI_UPDT: sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, - &thermal_temp_input16_group); + &thermal_temp_input8_group); break; case TPACPI_THERMAL_NONE: default: -- cgit v1.2.3-70-g09d2 From 6f6ef82cc9de24153ba7d5cedab5970e276aefa1 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 26 Dec 2009 19:24:31 +0000 Subject: acer-wmi: Respect current backlight level when loading Set the backlight to use the current brightness when loaded, rather than always resetting the backlight to maximum brightness. Fixes kernel bugzilla #14207 Signed-off-by: Carlos Corbacho Reported-by: Denis Mukhin Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 07d14dfdf0b4..226b3e93498c 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -934,7 +934,7 @@ static int __devinit acer_backlight_init(struct device *dev) acer_backlight_device = bd; bd->props.power = FB_BLANK_UNBLANK; - bd->props.brightness = max_brightness; + bd->props.brightness = read_brightness(bd); bd->props.max_brightness = max_brightness; backlight_update_status(bd); return 0; -- cgit v1.2.3-70-g09d2 From 34325b9d2a7d36e2ba74a6652f2e3e8d57dfb145 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 24 Aug 2009 16:00:47 -0500 Subject: compal-laptop: Add support for known Compal made Dell laptops The following Dell laptops are known to have been manufacturer by Compal and are supported by the compal-laptop platform driver - Mini 9 - Mini 10 - Mini 12 - Mini 10v - Inspiron 11z Signed-off-by: Mario Limonciello Signed-off-by: Tim Gardner Signed-off-by: Matthew Garrett Cc: Cezary Jackiewicz --- drivers/platform/x86/compal-laptop.c | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 1a387e79f719..c78d254303bc 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -310,6 +310,47 @@ static struct dmi_system_id __initdata compal_dmi_table[] = { }, .callback = dmi_check_cb }, + { + .ident = "Dell Mini 9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), + }, + .callback = dmi_check_cb + }, + { + .ident = "Dell Mini 10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), + }, + .callback = dmi_check_cb + }, + { + .ident = "Dell Mini 10v", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), + }, + .callback = dmi_check_cb + }, + { + .ident = "Dell Inspiron 11z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), + }, + .callback = dmi_check_cb + }, + { + .ident = "Dell Mini 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), + }, + .callback = dmi_check_cb + }, + { } }; @@ -403,3 +444,8 @@ MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*"); MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*"); MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*"); MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*"); +MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*"); -- cgit v1.2.3-70-g09d2 From 493e91433e966a50964e221db92756eeb90dd54e Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 25 Aug 2009 10:30:13 -0500 Subject: compal-laptop: Replace sysfs support with rfkill support This drops the support for manually groking the files in sysfs to turn on and off the WLAN and BT for Compal laptops in favor of platform rfkill support. It has been combined into a single patch to not introduce regressions in the process of simply adding rfkill support Signed-off-by: Mario Limonciello Signed-off-by: Tim Gardner Signed-off-by: Matthew Garrett Cc: Cezary Jackiewicz --- drivers/platform/x86/compal-laptop.c | 201 +++++++++++------------------------ 1 file changed, 63 insertions(+), 138 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index c78d254303bc..2740b40aad9b 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -26,17 +26,8 @@ /* * comapl-laptop.c - Compal laptop support. * - * This driver exports a few files in /sys/devices/platform/compal-laptop/: - * - * wlan - wlan subsystem state: contains 0 or 1 (rw) - * - * bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw) - * - * raw - raw value taken from embedded controller register (ro) - * - * In addition to these platform device attributes the driver - * registers itself in the Linux backlight control subsystem and is - * available to userspace under /sys/class/backlight/compal-laptop/. + * The driver registers itself with the rfkill subsystem and + * the Linux backlight control subsystem. * * This driver might work on other laptops produced by Compal. If you * want to try it you can pass force=1 as argument to the module which @@ -51,6 +42,7 @@ #include #include #include +#include #define COMPAL_DRIVER_VERSION "0.2.6" @@ -63,6 +55,10 @@ #define WLAN_MASK 0x01 #define BT_MASK 0x02 +static struct rfkill *wifi_rfkill; +static struct rfkill *bt_rfkill; +static struct platform_device *compal_device; + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -88,65 +84,75 @@ static int get_lcd_level(void) return (int) result; } -static int set_wlan_state(int state) +static int compal_rfkill_set(void *data, bool blocked) { + unsigned long radio = (unsigned long) data; u8 result, value; ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); - if ((result & KILLSWITCH_MASK) == 0) - return -EINVAL; - else { - if (state) - value = (u8) (result | WLAN_MASK); - else - value = (u8) (result & ~WLAN_MASK); - ec_write(COMPAL_EC_COMMAND_WIRELESS, value); - } + if (!blocked) + value = (u8) (result | radio); + else + value = (u8) (result & ~radio); + ec_write(COMPAL_EC_COMMAND_WIRELESS, value); return 0; } -static int set_bluetooth_state(int state) +static void compal_rfkill_poll(struct rfkill *rfkill, void *data) { - u8 result, value; + u8 result; + bool hw_blocked; ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); - if ((result & KILLSWITCH_MASK) == 0) - return -EINVAL; - else { - if (state) - value = (u8) (result | BT_MASK); - else - value = (u8) (result & ~BT_MASK); - ec_write(COMPAL_EC_COMMAND_WIRELESS, value); - } - - return 0; + hw_blocked = !(result & KILLSWITCH_MASK); + rfkill_set_hw_state(rfkill, hw_blocked); } -static int get_wireless_state(int *wlan, int *bluetooth) +static const struct rfkill_ops compal_rfkill_ops = { + .poll = compal_rfkill_poll, + .set_block = compal_rfkill_set, +}; + +static int setup_rfkill(void) { - u8 result; + int ret; - ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); + wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev, + RFKILL_TYPE_WLAN, &compal_rfkill_ops, + (void *) WLAN_MASK); + if (!wifi_rfkill) + return -ENOMEM; - if (wlan) { - if ((result & KILLSWITCH_MASK) == 0) - *wlan = 0; - else - *wlan = result & WLAN_MASK; - } + ret = rfkill_register(wifi_rfkill); + if (ret) + goto err_wifi; - if (bluetooth) { - if ((result & KILLSWITCH_MASK) == 0) - *bluetooth = 0; - else - *bluetooth = (result & BT_MASK) >> 1; + bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev, + RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops, + (void *) BT_MASK); + if (!bt_rfkill) { + ret = -ENOMEM; + goto err_allocate_bt; } + ret = rfkill_register(bt_rfkill); + if (ret) + goto err_register_bt; return 0; + +err_register_bt: + rfkill_destroy(bt_rfkill); + +err_allocate_bt: + rfkill_unregister(wifi_rfkill); + +err_wifi: + rfkill_destroy(wifi_rfkill); + + return ret; } /* Backlight device stuff */ @@ -169,86 +175,6 @@ static struct backlight_ops compalbl_ops = { static struct backlight_device *compalbl_device; -/* Platform device */ - -static ssize_t show_wlan(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret, enabled; - - ret = get_wireless_state(&enabled, NULL); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", enabled); -} - -static ssize_t show_raw(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u8 result; - - ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); - - return sprintf(buf, "%i\n", result); -} - -static ssize_t show_bluetooth(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret, enabled; - - ret = get_wireless_state(NULL, &enabled); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", enabled); -} - -static ssize_t store_wlan_state(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int state, ret; - - if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1)) - return -EINVAL; - - ret = set_wlan_state(state); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t store_bluetooth_state(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int state, ret; - - if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1)) - return -EINVAL; - - ret = set_bluetooth_state(state); - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state); -static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state); -static DEVICE_ATTR(raw, 0444, show_raw, NULL); - -static struct attribute *compal_attributes[] = { - &dev_attr_bluetooth.attr, - &dev_attr_wlan.attr, - &dev_attr_raw.attr, - NULL -}; - -static struct attribute_group compal_attribute_group = { - .attrs = compal_attributes -}; static struct platform_driver compal_driver = { .driver = { @@ -257,8 +183,6 @@ static struct platform_driver compal_driver = { } }; -static struct platform_device *compal_device; - /* Initialization */ static int dmi_check_cb(const struct dmi_system_id *id) @@ -389,23 +313,21 @@ static int __init compal_init(void) ret = platform_device_add(compal_device); if (ret) - goto fail_platform_device1; + goto fail_platform_device; - ret = sysfs_create_group(&compal_device->dev.kobj, - &compal_attribute_group); + ret = setup_rfkill(); if (ret) - goto fail_platform_device2; + goto fail_rfkill; printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION " successfully loaded.\n"); return 0; -fail_platform_device2: - +fail_rfkill: platform_device_del(compal_device); -fail_platform_device1: +fail_platform_device: platform_device_put(compal_device); @@ -423,10 +345,13 @@ fail_backlight: static void __exit compal_cleanup(void) { - sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group); platform_device_unregister(compal_device); platform_driver_unregister(&compal_driver); backlight_device_unregister(compalbl_device); + rfkill_unregister(wifi_rfkill); + rfkill_destroy(wifi_rfkill); + rfkill_unregister(bt_rfkill); + rfkill_destroy(bt_rfkill); printk(KERN_INFO "compal-laptop: driver unloaded.\n"); } -- cgit v1.2.3-70-g09d2 From 814cb8adbe2fb49302ac65bc31fa749143823860 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 9 Dec 2009 18:23:36 +0000 Subject: dell-laptop: Update rfkill state on kill switch The rfkill interface on Dells only sends a notification that the switch has been changed via the keyboard controller. Add a filter so we can pick these notifications up and update the rfkill state appropriately. Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/dell-laptop.c | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f526e735c5ab..6848f213eb53 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -79,6 +79,7 @@ config DELL_LAPTOP depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL || RFKILL = n depends on POWER_SUPPLY + depends on SERIO_I8042 default n ---help--- This driver adds support for rfkill and backlight control to Dell diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 3780994dc8f2..9d7e0be6bb0f 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "../../firmware/dcdbas.h" #define BRIGHTNESS_TOKEN 0x7d @@ -214,6 +215,18 @@ static const struct rfkill_ops dell_rfkill_ops = { .query = dell_rfkill_query, }; +static void dell_update_rfkill(struct work_struct *ignored) +{ + if (wifi_rfkill) + dell_rfkill_query(wifi_rfkill, (void *)1); + if (bluetooth_rfkill) + dell_rfkill_query(bluetooth_rfkill, (void *)2); + if (wwan_rfkill) + dell_rfkill_query(wwan_rfkill, (void *)3); +} +static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + + static int __init dell_setup_rfkill(void) { struct calling_interface_buffer buffer; @@ -338,6 +351,30 @@ static struct backlight_ops dell_ops = { .update_status = dell_send_intensity, }; +bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, + round_jiffies_relative(HZ)); + break; + } + extended = false; + } + + return false; +} + static int __init dell_init(void) { struct calling_interface_buffer buffer; @@ -373,6 +410,13 @@ static int __init dell_init(void) goto fail_rfkill; } + ret = i8042_install_filter(dell_laptop_i8042_filter); + if (ret) { + printk(KERN_WARNING + "dell-laptop: Unable to install key filter\n"); + goto fail_filter; + } + #ifdef CONFIG_ACPI /* In the event of an ACPI backlight being available, don't * register the platform controller. @@ -410,6 +454,8 @@ static int __init dell_init(void) return 0; fail_backlight: + i8042_remove_filter(dell_laptop_i8042_filter); +fail_filter: dell_cleanup_rfkill(); fail_rfkill: platform_device_del(platform_device); @@ -424,6 +470,8 @@ fail_platform_driver: static void __exit dell_exit(void) { + cancel_delayed_work_sync(&dell_rfkill_work); + i8042_remove_filter(dell_laptop_i8042_filter); backlight_device_unregister(dell_backlight_device); dell_cleanup_rfkill(); } -- cgit v1.2.3-70-g09d2 From facd61d7b70d9c061f08e0b76976f7f833888a70 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 9 Feb 2010 14:03:04 -0500 Subject: dell-laptop: Fix platform device unregistration dell-laptop currently fails to clean up its platform device correctly. Make sure that it's unregistered. Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 9d7e0be6bb0f..b4c2190e89f9 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -474,6 +474,10 @@ static void __exit dell_exit(void) i8042_remove_filter(dell_laptop_i8042_filter); backlight_device_unregister(dell_backlight_device); dell_cleanup_rfkill(); + if (platform_device) { + platform_device_del(platform_device); + platform_driver_unregister(&platform_driver); + } } module_init(dell_init); -- cgit v1.2.3-70-g09d2 From e551260b233e8dcbdc9d5f238ad4aa1200dc2ea7 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 9 Feb 2010 14:05:01 -0500 Subject: dell-laptop: Fix small memory leak da_tokens was not being freed by dell-laptop on unload. Fix that. Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index b4c2190e89f9..b13eb6a2cb51 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -478,6 +478,7 @@ static void __exit dell_exit(void) platform_device_del(platform_device); platform_driver_unregister(&platform_driver); } + kfree(da_tokens); } module_init(dell_init); -- cgit v1.2.3-70-g09d2 From ec1722a21491e4c354bc3bbc704fef9a8fa811fb Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 9 Feb 2010 14:11:05 -0500 Subject: dell-laptop: Block software state changes when rfkill hard blocked The "hardware" switch is tied directly to a BIOS interface that will connect and disconnect the hardware from the bus. If you use the software interface to request the BIOS to make these changes, the HW switch will be in an inconsistent state and LEDs may not reflect the state of the HW. Signed-off-by: Mario Limonciello --- drivers/platform/x86/dell-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index b13eb6a2cb51..81213e815400 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -190,6 +190,10 @@ static int dell_rfkill_set(void *data, bool blocked) unsigned long radio = (unsigned long)data; memset(&buffer, 0, sizeof(struct calling_interface_buffer)); + dell_send_request(&buffer, 17, 11); + if (!(buffer.output[1] & BIT(16))) + return -EINVAL; + buffer.input[0] = (1 | (radio<<8) | (disable << 16)); dell_send_request(&buffer, 17, 11); -- cgit v1.2.3-70-g09d2 From e5fefd0c8c4e6bd11742625230d1c5026e2afb35 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 9 Feb 2010 17:41:03 -0500 Subject: dell-laptop: Blacklist machines not supporting dell-laptop The Mini family doesn't support smbios 17,11 although it reports it does. Signed-off-by: Mario Limonciello Signed-off-by: Tim Gardner --- drivers/platform/x86/dell-laptop.c | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 81213e815400..d8b1b39aa9db 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -83,6 +83,46 @@ static const struct dmi_system_id __initdata dell_device_table[] = { { } }; +static struct dmi_system_id __devinitdata dell_blacklist[] = { + /* Supported by compal-laptop */ + { + .ident = "Dell Mini 9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), + }, + }, + { + .ident = "Dell Mini 10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), + }, + }, + { + .ident = "Dell Mini 10v", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), + }, + }, + { + .ident = "Dell Inspiron 11z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), + }, + }, + { + .ident = "Dell Mini 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), + }, + }, + {} +}; + static void __init parse_da_table(const struct dmi_header *dm) { /* Final token is a terminator, so we don't want to copy it */ @@ -237,6 +277,12 @@ static int __init dell_setup_rfkill(void) int status; int ret; + if (dmi_check_system(dell_blacklist)) { + printk(KERN_INFO "dell-laptop: Blacklisted hardware detected - " + "not enabling rfkill\n"); + return 0; + } + memset(&buffer, 0, sizeof(struct calling_interface_buffer)); dell_send_request(&buffer, 17, 11); status = buffer.output[1]; -- cgit v1.2.3-70-g09d2 From 116ee77b2858d9c89c0327f3a47c8ba864bf4a96 Mon Sep 17 00:00:00 2001 From: Stuart Hayes Date: Wed, 10 Feb 2010 14:12:13 -0500 Subject: dell-laptop: Use buffer with 32-bit physical address Calls to communicate with system firmware via a SMI (using dcdbas) need to use a buffer that has a physical address of 4GB or less. Currently the dell-laptop driver does not guarantee this, and when the buffer address is higher than 4GB, the address is truncated to 32 bits and the SMI handler writes to the wrong memory address. Signed-off-by: Stuart Hayes Acked-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 122 +++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 39 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index d8b1b39aa9db..1a0bfd43f8f0 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "../../firmware/dcdbas.h" @@ -123,6 +124,21 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = { {} }; +static struct calling_interface_buffer *buffer; +struct page *bufferpage; +DEFINE_MUTEX(buffer_mutex); + +static void get_buffer(void) +{ + mutex_lock(&buffer_mutex); + memset(buffer, 0, sizeof(struct calling_interface_buffer)); +} + +static void release_buffer(void) +{ + mutex_unlock(&buffer_mutex); +} + static void __init parse_da_table(const struct dmi_header *dm) { /* Final token is a terminator, so we don't want to copy it */ @@ -225,30 +241,35 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, static int dell_rfkill_set(void *data, bool blocked) { - struct calling_interface_buffer buffer; int disable = blocked ? 1 : 0; unsigned long radio = (unsigned long)data; + int ret = 0; - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - dell_send_request(&buffer, 17, 11); - if (!(buffer.output[1] & BIT(16))) - return -EINVAL; + get_buffer(); + dell_send_request(buffer, 17, 11); - buffer.input[0] = (1 | (radio<<8) | (disable << 16)); - dell_send_request(&buffer, 17, 11); + if (!(buffer->output[1] & BIT(16))) { + ret = -EINVAL; + goto out; + } - return 0; + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); + dell_send_request(buffer, 17, 11); + +out: + release_buffer(); + return ret; } static void dell_rfkill_query(struct rfkill *rfkill, void *data) { - struct calling_interface_buffer buffer; int status; int bit = (unsigned long)data + 16; - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - dell_send_request(&buffer, 17, 11); - status = buffer.output[1]; + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + release_buffer(); rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); rfkill_set_hw_state(rfkill, !(status & BIT(16))); @@ -273,7 +294,6 @@ static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); static int __init dell_setup_rfkill(void) { - struct calling_interface_buffer buffer; int status; int ret; @@ -283,9 +303,10 @@ static int __init dell_setup_rfkill(void) return 0; } - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - dell_send_request(&buffer, 17, 11); - status = buffer.output[1]; + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + release_buffer(); if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, @@ -361,39 +382,49 @@ static void dell_cleanup_rfkill(void) static int dell_send_intensity(struct backlight_device *bd) { - struct calling_interface_buffer buffer; + int ret = 0; - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); - buffer.input[1] = bd->props.brightness; + get_buffer(); + buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); + buffer->input[1] = bd->props.brightness; - if (buffer.input[0] == -1) - return -ENODEV; + if (buffer->input[0] == -1) { + ret = -ENODEV; + goto out; + } if (power_supply_is_system_supplied() > 0) - dell_send_request(&buffer, 1, 2); + dell_send_request(buffer, 1, 2); else - dell_send_request(&buffer, 1, 1); + dell_send_request(buffer, 1, 1); +out: + release_buffer(); return 0; } static int dell_get_intensity(struct backlight_device *bd) { - struct calling_interface_buffer buffer; + int ret = 0; - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); + get_buffer(); + buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); - if (buffer.input[0] == -1) - return -ENODEV; + if (buffer->input[0] == -1) { + ret = -ENODEV; + goto out; + } if (power_supply_is_system_supplied() > 0) - dell_send_request(&buffer, 0, 2); + dell_send_request(buffer, 0, 2); else - dell_send_request(&buffer, 0, 1); + dell_send_request(buffer, 0, 1); - return buffer.output[1]; +out: + release_buffer(); + if (ret) + return ret; + return buffer->output[1]; } static struct backlight_ops dell_ops = { @@ -427,7 +458,6 @@ bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, static int __init dell_init(void) { - struct calling_interface_buffer buffer; int max_intensity = 0; int ret; @@ -453,6 +483,17 @@ static int __init dell_init(void) if (ret) goto fail_platform_device2; + /* + * Allocate buffer below 4GB for SMI data--only 32-bit physical addr + * is passed to SMI handler. + */ + bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32); + + if (!bufferpage) + goto fail_buffer; + buffer = page_address(bufferpage); + mutex_init(&buffer_mutex); + ret = dell_setup_rfkill(); if (ret) { @@ -475,13 +516,13 @@ static int __init dell_init(void) return 0; #endif - memset(&buffer, 0, sizeof(struct calling_interface_buffer)); - buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN); - - if (buffer.input[0] != -1) { - dell_send_request(&buffer, 0, 2); - max_intensity = buffer.output[3]; + get_buffer(); + buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); + if (buffer->input[0] != -1) { + dell_send_request(buffer, 0, 2); + max_intensity = buffer->output[3]; } + release_buffer(); if (max_intensity) { dell_backlight_device = backlight_device_register( @@ -508,6 +549,8 @@ fail_backlight: fail_filter: dell_cleanup_rfkill(); fail_rfkill: + free_page((unsigned long)bufferpage); +fail_buffer: platform_device_del(platform_device); fail_platform_device2: platform_device_put(platform_device); @@ -529,6 +572,7 @@ static void __exit dell_exit(void) platform_driver_unregister(&platform_driver); } kfree(da_tokens); + free_page((unsigned long)buffer); } module_init(dell_init); -- cgit v1.2.3-70-g09d2 From c6760ac4268b6dbe03d74e5faef35bc862a82542 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 10 Feb 2010 14:44:03 -0500 Subject: dell-laptop: Pay attention to which devices the hardware switch controls Right now, we assume that the hardware rfkill switch on Dells toggles all radio devices. In fact, this can be configured in the BIOS and so right now we may mark a device as hardware killed even when it isn't. Add code to query the devices controlled by the switch, and use this when determining the hardware kill state of a radio. Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 1a0bfd43f8f0..04b2ddbe63d2 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -128,6 +128,8 @@ static struct calling_interface_buffer *buffer; struct page *bufferpage; DEFINE_MUTEX(buffer_mutex); +static int hwswitch_state; + static void get_buffer(void) { mutex_lock(&buffer_mutex); @@ -217,6 +219,8 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, /* Derived from information in DellWirelessCtl.cpp: Class 17, select 11 is radio control. It returns an array of 32-bit values. + Input byte 0 = 0: Wireless information + result[0]: return code result[1]: Bit 0: Hardware switch supported @@ -237,18 +241,35 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, Bits 20-31: Reserved result[2]: NVRAM size in bytes result[3]: NVRAM format version number + + Input byte 0 = 2: Wireless switch configuration + result[0]: return code + result[1]: + Bit 0: Wifi controlled by switch + Bit 1: Bluetooth controlled by switch + Bit 2: WWAN controlled by switch + Bits 3-6: Reserved + Bit 7: Wireless switch config locked + Bit 8: Wifi locator enabled + Bits 9-14: Reserved + Bit 15: Wifi locator setting locked + Bits 16-31: Reserved */ static int dell_rfkill_set(void *data, bool blocked) { int disable = blocked ? 1 : 0; unsigned long radio = (unsigned long)data; + int hwswitch_bit = (unsigned long)data - 1; int ret = 0; get_buffer(); dell_send_request(buffer, 17, 11); - if (!(buffer->output[1] & BIT(16))) { + /* If the hardware switch controls this radio, and the hardware + switch is disabled, don't allow changing the software state */ + if ((hwswitch_state & BIT(hwswitch_bit)) && + !(buffer->output[1] & BIT(16))) { ret = -EINVAL; goto out; } @@ -265,6 +286,7 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) { int status; int bit = (unsigned long)data + 16; + int hwswitch_bit = (unsigned long)data - 1; get_buffer(); dell_send_request(buffer, 17, 11); @@ -272,7 +294,9 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) release_buffer(); rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); - rfkill_set_hw_state(rfkill, !(status & BIT(16))); + + if (hwswitch_state & (BIT(hwswitch_bit))) + rfkill_set_hw_state(rfkill, !(status & BIT(16))); } static const struct rfkill_ops dell_rfkill_ops = { @@ -306,6 +330,9 @@ static int __init dell_setup_rfkill(void) get_buffer(); dell_send_request(buffer, 17, 11); status = buffer->output[1]; + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_state = buffer->output[1]; release_buffer(); if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { -- cgit v1.2.3-70-g09d2 From 02e77a55f7b7e36888e39c62439fedb90ae4e808 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 9 Feb 2010 17:37:27 -0500 Subject: classmate-laptop: use a single MODULE_DEVICE_TABLE to get correct aliases Instead of a MODULE_DEVICE_TABLE for every acpi_driver ids table, we create a table containing all ids to export to get a module alias for each one. This will fix automatic loading of the driver when one of the ACPI devices is not present (like the accelerometer, which is not present in some models). Signed-off-by: Thadeu Lima de Souza Cascardo --- drivers/platform/x86/classmate-laptop.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index ed90082cdf1d..8cb20e45bad6 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -34,6 +34,11 @@ struct cmpc_accel { #define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_HID "ACCE0000" +#define CMPC_TABLET_HID "TBLT0000" +#define CMPC_BL_HID "IPML200" +#define CMPC_KEYS_HID "FnBT0000" + /* * Generic input device code. */ @@ -282,10 +287,9 @@ static int cmpc_accel_remove(struct acpi_device *acpi, int type) } static const struct acpi_device_id cmpc_accel_device_ids[] = { - {"ACCE0000", 0}, + {CMPC_ACCEL_HID, 0}, {"", 0} }; -MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids); static struct acpi_driver cmpc_accel_acpi_driver = { .owner = THIS_MODULE, @@ -366,10 +370,9 @@ static int cmpc_tablet_resume(struct acpi_device *acpi) } static const struct acpi_device_id cmpc_tablet_device_ids[] = { - {"TBLT0000", 0}, + {CMPC_TABLET_HID, 0}, {"", 0} }; -MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids); static struct acpi_driver cmpc_tablet_acpi_driver = { .owner = THIS_MODULE, @@ -477,17 +480,16 @@ static int cmpc_bl_remove(struct acpi_device *acpi, int type) return 0; } -static const struct acpi_device_id cmpc_device_ids[] = { - {"IPML200", 0}, +static const struct acpi_device_id cmpc_bl_device_ids[] = { + {CMPC_BL_HID, 0}, {"", 0} }; -MODULE_DEVICE_TABLE(acpi, cmpc_device_ids); static struct acpi_driver cmpc_bl_acpi_driver = { .owner = THIS_MODULE, .name = "cmpc", .class = "cmpc", - .ids = cmpc_device_ids, + .ids = cmpc_bl_device_ids, .ops = { .add = cmpc_bl_add, .remove = cmpc_bl_remove @@ -540,10 +542,9 @@ static int cmpc_keys_remove(struct acpi_device *acpi, int type) } static const struct acpi_device_id cmpc_keys_device_ids[] = { - {"FnBT0000", 0}, + {CMPC_KEYS_HID, 0}, {"", 0} }; -MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids); static struct acpi_driver cmpc_keys_acpi_driver = { .owner = THIS_MODULE, @@ -607,3 +608,13 @@ static void cmpc_exit(void) module_init(cmpc_init); module_exit(cmpc_exit); + +static const struct acpi_device_id cmpc_device_ids[] = { + {CMPC_ACCEL_HID, 0}, + {CMPC_TABLET_HID, 0}, + {CMPC_BL_HID, 0}, + {CMPC_KEYS_HID, 0}, + {"", 0} +}; + +MODULE_DEVICE_TABLE(acpi, cmpc_device_ids); -- cgit v1.2.3-70-g09d2 From cb6a7937f4328a267e0806680ade500ed2c3c01a Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Sun, 14 Feb 2010 11:53:23 -0500 Subject: dell-laptop: Add another Dell laptop to the DMI whitelist The Latitude C640 has another variation of dell in its DMI vendor entry. Add it to the whitelist in order to enjoy the sweet fruits of software backlight toggling. Signed-off-by: Erik Andren --- drivers/platform/x86/dell-laptop.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 04b2ddbe63d2..b7f4d2705916 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -81,6 +81,13 @@ static const struct dmi_system_id __initdata dell_device_table[] = { DMI_MATCH(DMI_CHASSIS_TYPE, "8"), }, }, + { + .ident = "Dell Computer Corporation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), + }, + }, { } }; @@ -609,3 +616,4 @@ MODULE_AUTHOR("Matthew Garrett "); MODULE_DESCRIPTION("Dell laptop driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); +MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*"); -- cgit v1.2.3-70-g09d2 From caeacf59af3d114a3121bb04f8057109bbf289ea Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 17 Feb 2010 10:29:39 -0500 Subject: hp-wmi: Add support for tablet rotation key The HP touchsmart tablet has a key for rotating the UI from landscape to portrait. Add support for it. Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index ad4c414dbfbc..3aa57da8b43b 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -89,6 +89,7 @@ static struct key_entry hp_wmi_keymap[] = { {KE_KEY, 0x20e6, KEY_PROG1}, {KE_KEY, 0x2142, KEY_MEDIA}, {KE_KEY, 0x213b, KEY_INFO}, + {KE_KEY, 0x2169, KEY_DIRECTION}, {KE_KEY, 0x231b, KEY_HELP}, {KE_END, 0} }; -- cgit v1.2.3-70-g09d2 From 6335e4d56681f6f08f24f4b812a72d402793d393 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 25 Feb 2010 15:20:54 -0500 Subject: toshiba_acpi: Add full hotkey support Calling the ENAB method on Toshiba laptops results in notifications being sent when laptop hotkeys are pressed. This patch simply calls that method and sets up an input device if it's successful. Signed-off-by: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/toshiba_acpi.c | 206 ++++++++++++++++++++++++++++++++++-- 1 file changed, 199 insertions(+), 7 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 77bf5d8f893a..26c211724acf 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -62,9 +63,10 @@ MODULE_LICENSE("GPL"); /* Toshiba ACPI method paths */ #define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM" -#define METHOD_HCI_1 "\\_SB_.VALD.GHCI" -#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI" +#define TOSH_INTERFACE_1 "\\_SB_.VALD" +#define TOSH_INTERFACE_2 "\\_SB_.VALZ" #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX" +#define GHCI_METHOD ".GHCI" /* Toshiba HCI interface definitions * @@ -116,6 +118,36 @@ static const struct acpi_device_id toshiba_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); +struct key_entry { + char type; + u16 code; + u16 keycode; +}; + +enum {KE_KEY, KE_END}; + +static struct key_entry toshiba_acpi_keymap[] = { + {KE_KEY, 0x101, KEY_MUTE}, + {KE_KEY, 0x13b, KEY_COFFEE}, + {KE_KEY, 0x13c, KEY_BATTERY}, + {KE_KEY, 0x13d, KEY_SLEEP}, + {KE_KEY, 0x13e, KEY_SUSPEND}, + {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN}, + {KE_KEY, 0x141, KEY_BRIGHTNESSUP}, + {KE_KEY, 0x142, KEY_WLAN}, + {KE_KEY, 0x143, KEY_PROG1}, + {KE_KEY, 0xb05, KEY_PROG2}, + {KE_KEY, 0xb06, KEY_WWW}, + {KE_KEY, 0xb07, KEY_MAIL}, + {KE_KEY, 0xb30, KEY_STOP}, + {KE_KEY, 0xb31, KEY_PREVIOUSSONG}, + {KE_KEY, 0xb32, KEY_NEXTSONG}, + {KE_KEY, 0xb33, KEY_PLAYPAUSE}, + {KE_KEY, 0xb5a, KEY_MEDIA}, + {KE_END, 0, 0}, +}; + /* utility */ @@ -251,6 +283,8 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) struct toshiba_acpi_dev { struct platform_device *p_dev; struct rfkill *bt_rfk; + struct input_dev *hotkey_dev; + acpi_handle handle; const char *bt_name; @@ -711,8 +745,159 @@ static struct backlight_ops toshiba_backlight_data = { .update_status = set_lcd_status, }; +static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = toshiba_acpi_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) +{ + struct key_entry *key; + + for (key = toshiba_acpi_keymap; key->type != KE_END; key++) + if (code == key->keycode && key->type == KE_KEY) + return key; + + return NULL; +} + +static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, + int *keycode) +{ + struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode, + int keycode) +{ + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = toshiba_acpi_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!toshiba_acpi_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + +static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) +{ + u32 hci_result, value; + struct key_entry *key; + + if (event != 0x80) + return; + do { + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); + if (hci_result == HCI_SUCCESS) { + if (value == 0x100) + continue; + else if (value & 0x80) { + key = toshiba_acpi_get_entry_by_scancode + (value & ~0x80); + if (!key) { + printk(MY_INFO "Unknown key %x\n", + value & ~0x80); + continue; + } + input_report_key(toshiba_acpi.hotkey_dev, + key->keycode, 1); + input_sync(toshiba_acpi.hotkey_dev); + input_report_key(toshiba_acpi.hotkey_dev, + key->keycode, 0); + input_sync(toshiba_acpi.hotkey_dev); + } + } else if (hci_result == HCI_NOT_SUPPORTED) { + /* This is a workaround for an unresolved issue on + * some machines where system events sporadically + * become disabled. */ + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); + printk(MY_NOTICE "Re-enabled hotkeys\n"); + } + } while (hci_result != HCI_EMPTY); +} + +static int toshiba_acpi_setup_keyboard(char *device) +{ + acpi_status status; + acpi_handle handle; + int result; + const struct key_entry *key; + + status = acpi_get_handle(NULL, device, &handle); + if (ACPI_FAILURE(status)) { + printk(MY_INFO "Unable to get notification device\n"); + return -ENODEV; + } + + toshiba_acpi.handle = handle; + + status = acpi_evaluate_object(handle, "ENAB", NULL, NULL); + if (ACPI_FAILURE(status)) { + printk(MY_INFO "Unable to enable hotkeys\n"); + return -ENODEV; + } + + status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY, + toshiba_acpi_notify, NULL); + if (ACPI_FAILURE(status)) { + printk(MY_INFO "Unable to install hotkey notification\n"); + return -ENODEV; + } + + toshiba_acpi.hotkey_dev = input_allocate_device(); + if (!toshiba_acpi.hotkey_dev) { + printk(MY_INFO "Unable to register input device\n"); + return -ENOMEM; + } + + toshiba_acpi.hotkey_dev->name = "Toshiba input device"; + toshiba_acpi.hotkey_dev->phys = device; + toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; + toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode; + toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode; + + for (key = toshiba_acpi_keymap; key->type != KE_END; key++) { + set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit); + set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit); + } + + result = input_register_device(toshiba_acpi.hotkey_dev); + if (result) { + printk(MY_INFO "Unable to register input device\n"); + return result; + } + + return 0; +} + static void toshiba_acpi_exit(void) { + if (toshiba_acpi.hotkey_dev) + input_unregister_device(toshiba_acpi.hotkey_dev); + if (toshiba_acpi.bt_rfk) { rfkill_unregister(toshiba_acpi.bt_rfk); rfkill_destroy(toshiba_acpi.bt_rfk); @@ -726,6 +911,9 @@ static void toshiba_acpi_exit(void) if (toshiba_proc_dir) remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); + acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY, + toshiba_acpi_notify); + platform_device_unregister(toshiba_acpi.p_dev); return; @@ -742,11 +930,15 @@ static int __init toshiba_acpi_init(void) return -ENODEV; /* simple device detection: look for HCI method */ - if (is_valid_acpi_path(METHOD_HCI_1)) - method_hci = METHOD_HCI_1; - else if (is_valid_acpi_path(METHOD_HCI_2)) - method_hci = METHOD_HCI_2; - else + if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) { + method_hci = TOSH_INTERFACE_1 GHCI_METHOD; + if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1)) + printk(MY_INFO "Unable to activate hotkeys\n"); + } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) { + method_hci = TOSH_INTERFACE_2 GHCI_METHOD; + if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2)) + printk(MY_INFO "Unable to activate hotkeys\n"); + } else return -ENODEV; printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n", -- cgit v1.2.3-70-g09d2 From bf8b29c8f7f8269e99eca8b19048ed5b34b51810 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 21:28:56 -0300 Subject: thinkpad-acpi: document HKEY event 3006 Event 0x3006 is used to help power management of the ODD in the UltraBay. The EC generates this event when the ODD eject button is pressed (even if the bay is powered down). Normally, Linux doesn't need this as we keep the SATA link powered up (which wastes power). The EC powers up the bay by itself when the ODD eject button is pressed, and the SATA PHY reports the hotplug. However, we could also power that SATA link down (and for that matter, also power down the Ultrabay) if the ODD is left idle for a while with no disk inside, and use event 0x3006 to know when we need that SATA link powered back up. For now, just stop asking for more information when event 0x3006 is seen, there is no point in pestering users about it anymore. Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index eb603f1d55ca..049041a47f8d 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3655,13 +3655,19 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) break; case 3: /* 0x3000-0x3FFF: bay-related wakeups */ - if (hkey == TP_HKEY_EV_BAYEJ_ACK) { + switch (hkey) { + case TP_HKEY_EV_BAYEJ_ACK: hotkey_autosleep_ack = 1; printk(TPACPI_INFO "bay ejected\n"); hotkey_wakeup_hotunplug_complete_notify_change(); known_ev = true; - } else { + break; + case TP_HKEY_EV_OPTDRV_EJ: + /* FIXME: kick libata if SATA link offline */ + known_ev = true; + break; + default: known_ev = false; } break; -- cgit v1.2.3-70-g09d2 From 7d1894d8d1c411d2dad95abfe0f65bacf68c4afa Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 21:28:56 -0300 Subject: thinkpad-acpi: R52 brightness_mode has been confirmed We can stop pestering users for confirmation of the brightness_mode default for firmware TP-76. While at it, add a few missing comments in that quirk table. Reported-by: Whoopie Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 049041a47f8d..06657b71171c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6139,13 +6139,13 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ /* Models with ATI GPUs that can use ECNVRAM */ - TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), + TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), /* R50,51 T40-42 */ TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), - TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), + TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC), /* R52 */ TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), /* Models with Intel Extreme Graphics 2 */ - TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), + TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), /* X40 */ TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), -- cgit v1.2.3-70-g09d2 From b589ea4c44170d3f7a845684e2d1b3b9571663af Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 21:28:58 -0300 Subject: thinkpad-acpi: fix poll thread auto-start The driver was not starting the NVRAM polling thread if the input device was bound immediately after registration. This fixes: http://bugzilla.kernel.org/show_bug.cgi?id=15118 Reported-by: Florian Zumbiehl Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 06657b71171c..933bcc477f4a 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -2607,16 +2607,11 @@ static int hotkey_inputdev_open(struct input_dev *dev) { switch (tpacpi_lifecycle) { case TPACPI_LIFE_INIT: - /* - * hotkey_init will call hotkey_poll_setup_safe - * at the appropriate moment - */ - return 0; - case TPACPI_LIFE_EXITING: - return -EBUSY; case TPACPI_LIFE_RUNNING: hotkey_poll_setup_safe(false); return 0; + case TPACPI_LIFE_EXITING: + return -EBUSY; } /* Should only happen if tpacpi_lifecycle is corrupt */ @@ -2627,7 +2622,7 @@ static int hotkey_inputdev_open(struct input_dev *dev) static void hotkey_inputdev_close(struct input_dev *dev) { /* disable hotkey polling when possible */ - if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING && + if (tpacpi_lifecycle != TPACPI_LIFE_EXITING && !(hotkey_source_mask & hotkey_driver_mask)) hotkey_poll_setup_safe(false); } @@ -9038,6 +9033,9 @@ static int __init thinkpad_acpi_module_init(void) return ret; } } + + tpacpi_lifecycle = TPACPI_LIFE_RUNNING; + ret = input_register_device(tpacpi_inputdev); if (ret < 0) { printk(TPACPI_ERR "unable to register input device\n"); @@ -9047,7 +9045,6 @@ static int __init thinkpad_acpi_module_init(void) tp_features.input_device_registered = 1; } - tpacpi_lifecycle = TPACPI_LIFE_RUNNING; return 0; } -- cgit v1.2.3-70-g09d2 From 7f0cf712a74fcc3ad21f0bde95bd32c2f2cc3888 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 21:29:00 -0300 Subject: thinkpad-acpi: make driver events work in NVRAM poll mode Thadeu Lima de Souza Cascardo reports this: Brightness notification does not work until the user writes to hotkey_mask attribute. That's because the polling thread will only run if hotkey_user_mask is set and someone is reading the input device or if hotkey_driver_mask is set. In this second case, this condition is not tested after the mask is changed, because the brightness and volume drivers are started after the hotkey drivers. Fix tpacpi_hotkey_driver_mask_set() to call hotkey_poll_setup(), so that the poller kthread will be started when needed. Reported-by: Thadeu Lima de Souza Cascardo Tested-by: Thadeu Lima de Souza Cascardo Signed-off-by: Henrique de Moraes Holschuh Cc: Andrew Morton Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 933bcc477f4a..5f450831e5f0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -2082,6 +2082,7 @@ static struct attribute_set *hotkey_dev_attributes; static void tpacpi_driver_event(const unsigned int hkey_event); static void hotkey_driver_event(const unsigned int scancode); +static void hotkey_poll_setup(const bool may_warn); /* HKEY.MHKG() return bits */ #define TP_HOTKEY_TABLET_MASK (1 << 3) @@ -2264,6 +2265,8 @@ static int tpacpi_hotkey_driver_mask_set(const u32 mask) rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) & ~hotkey_source_mask); + hotkey_poll_setup(true); + mutex_unlock(&hotkey_mutex); return rc; @@ -2548,7 +2551,7 @@ static void hotkey_poll_stop_sync(void) } /* call with hotkey_mutex held */ -static void hotkey_poll_setup(bool may_warn) +static void hotkey_poll_setup(const bool may_warn) { const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask; const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask; @@ -2579,7 +2582,7 @@ static void hotkey_poll_setup(bool may_warn) } } -static void hotkey_poll_setup_safe(bool may_warn) +static void hotkey_poll_setup_safe(const bool may_warn) { mutex_lock(&hotkey_mutex); hotkey_poll_setup(may_warn); @@ -2597,7 +2600,11 @@ static void hotkey_poll_set_freq(unsigned int freq) #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ -static void hotkey_poll_setup_safe(bool __unused) +static void hotkey_poll_setup(const bool __unused) +{ +} + +static void hotkey_poll_setup_safe(const bool __unused) { } -- cgit v1.2.3-70-g09d2 From 08fedfc903c78e380b0baa7b57c52d367794d0a5 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 22:22:07 -0300 Subject: thinkpad-acpi: fix bluetooth/wwan resume Studying the DSDTs of various thinkpads, it looks like bit 3 of the argument to SBDC and SWAN is not "set radio to last state on resume". Rather, it seems to be "if this bit is set, enable radio on resume, otherwise disable it on resume". So, the proper way to prepare the radios for S3 suspend is: disable radio and clear bit 3 on the SBDC/SWAN call to to resume with radio disabled, and enable radio and set bit 3 on the SBDC/SWAN call to resume with the radio enabled. Also, for persistent devices, the rfkill core does not restore state, so we really need to get the firmware to do the right thing. We don't sync the radio state on suspend, instead we trust the BIOS to not do anything weird if we never touched the radio state since boot. Time will tell if that's a wise way of doing things... Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 5f450831e5f0..3af4628d7dd1 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3878,7 +3878,7 @@ enum { TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume: - off / last state */ + 0 = disable, 1 = enable */ }; enum { @@ -3924,10 +3924,11 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state) } #endif - /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ - status = TP_ACPI_BLUETOOTH_RESUMECTRL; if (state == TPACPI_RFK_RADIO_ON) - status |= TP_ACPI_BLUETOOTH_RADIOSSW; + status = TP_ACPI_BLUETOOTH_RADIOSSW + | TP_ACPI_BLUETOOTH_RESUMECTRL; + else + status = 0; if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) return -EIO; @@ -4078,7 +4079,7 @@ enum { TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume: - off / last state */ + 0 = disable, 1 = enable */ }; #define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" @@ -4115,10 +4116,11 @@ static int wan_set_status(enum tpacpi_rfkill_state state) } #endif - /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */ - status = TP_ACPI_WANCARD_RESUMECTRL; if (state == TPACPI_RFK_RADIO_ON) - status |= TP_ACPI_WANCARD_RADIOSSW; + status = TP_ACPI_WANCARD_RADIOSSW + | TP_ACPI_WANCARD_RESUMECTRL; + else + status = 0; if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) return -EIO; -- cgit v1.2.3-70-g09d2 From b525c06cdbd8a3963f0173ccd23f9147d4c384b5 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 25 Feb 2010 22:22:22 -0300 Subject: thinkpad-acpi: lock down video output state access Given the right combination of ThinkPad and X.org, just reading the video output control state is enough to hard-crash X.org. Until the day I somehow find out a model or BIOS cut date to not provide this feature to ThinkPads that can do video switching through X RandR, change permissions so that only processes with CAP_SYS_ADMIN can access any sort of video output control state. This bug could be considered a local DoS I suppose, as it allows any non-privledged local user to cause some versions of X.org to hard-crash some ThinkPads. Reported-by: Jidanni Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- Documentation/laptops/thinkpad-acpi.txt | 4 ++++ drivers/platform/x86/Kconfig | 10 ++++++++-- drivers/platform/x86/thinkpad_acpi.c | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 75afa1229fd7..39c0a09d0105 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -650,6 +650,10 @@ LCD, CRT or DVI (if available). The following commands are available: echo expand_toggle > /proc/acpi/ibm/video echo video_switch > /proc/acpi/ibm/video +NOTE: Access to this feature is restricted to processes owning the +CAP_SYS_ADMIN capability for safety reasons, as it can interact badly +enough with some versions of X.org to crash it. + Each video output device can be enabled or disabled individually. Reading /proc/acpi/ibm/video shows the status of each device. diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f526e735c5ab..11fce79b61d1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -319,9 +319,15 @@ config THINKPAD_ACPI_VIDEO server running, phase of the moon, and the current mood of Schroedinger's cat. If you can use X.org's RandR to control your ThinkPad's video output ports instead of this feature, - don't think twice: do it and say N here to save some memory. + don't think twice: do it and say N here to save memory and avoid + bad interactions with X.org. - If you are not sure, say Y here. + NOTE: access to this feature is limited to processes with the + CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms + where it interacts badly with X.org. + + If you are not sure, say Y here but do try to check if you could + be using X.org RandR instead. config THINKPAD_ACPI_HOTKEY_POLL bool "Support NVRAM polling for hot keys" diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 3af4628d7dd1..5d02cc06d1a7 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -286,6 +286,7 @@ struct ibm_init_struct { char param[32]; int (*init) (struct ibm_init_struct *); + mode_t base_procfs_mode; struct ibm_struct *data; }; @@ -4629,6 +4630,10 @@ static int video_read(struct seq_file *m) return 0; } + /* Even reads can crash X.org, so... */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + status = video_outputsw_get(); if (status < 0) return status; @@ -4662,6 +4667,10 @@ static int video_write(char *buf) if (video_supported == TPACPI_VIDEO_NONE) return -ENODEV; + /* Even reads can crash X.org, let alone writes... */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + enable = 0; disable = 0; @@ -8487,9 +8496,10 @@ static int __init ibm_init(struct ibm_init_struct *iibm) "%s installed\n", ibm->name); if (ibm->read) { - mode_t mode; + mode_t mode = iibm->base_procfs_mode; - mode = S_IRUGO; + if (!mode) + mode = S_IRUGO; if (ibm->write) mode |= S_IWUSR; entry = proc_create_data(ibm->name, mode, proc_dir, @@ -8680,6 +8690,7 @@ static struct ibm_init_struct ibms_init[] __initdata = { #ifdef CONFIG_THINKPAD_ACPI_VIDEO { .init = video_init, + .base_procfs_mode = S_IRUSR, .data = &video_driver_data, }, #endif -- cgit v1.2.3-70-g09d2 From 88cc83772a3c7756b9f2b4ba835545ad90a08409 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 27 Feb 2010 18:45:29 -0300 Subject: thinkpad-acpi: fix ALSA callback return status Clemens Ladisch reports that thinkpad-acpi improperly implements the ALSA API, and always returns 0 for success for the "put" callbacks while the API requires it to return "1" when the control value has been changed in the hardware/firmware. Rework the volume subdriver to be able to properly implement the ALSA API. Based on a patch by Clemens Ladisch . This fix is also needed on 2.6.33. Reported-by: Clemens Ladisch Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 39 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 5d02cc06d1a7..e7b0c3bcef89 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6541,7 +6541,8 @@ static int volume_set_status(const u8 status) return volume_set_status_ec(status); } -static int volume_set_mute_ec(const bool mute) +/* returns < 0 on error, 0 on no change, 1 on change */ +static int __volume_set_mute_ec(const bool mute) { int rc; u8 s, n; @@ -6556,22 +6557,37 @@ static int volume_set_mute_ec(const bool mute) n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK : s & ~TP_EC_AUDIO_MUTESW_MSK; - if (n != s) + if (n != s) { rc = volume_set_status_ec(n); + if (!rc) + rc = 1; + } unlock: mutex_unlock(&volume_mutex); return rc; } +static int volume_alsa_set_mute(const bool mute) +{ + dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n", + (mute) ? "" : "un"); + return __volume_set_mute_ec(mute); +} + static int volume_set_mute(const bool mute) { + int rc; + dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n", (mute) ? "" : "un"); - return volume_set_mute_ec(mute); + + rc = __volume_set_mute_ec(mute); + return (rc < 0) ? rc : 0; } -static int volume_set_volume_ec(const u8 vol) +/* returns < 0 on error, 0 on no change, 1 on change */ +static int __volume_set_volume_ec(const u8 vol) { int rc; u8 s, n; @@ -6588,19 +6604,22 @@ static int volume_set_volume_ec(const u8 vol) n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol; - if (n != s) + if (n != s) { rc = volume_set_status_ec(n); + if (!rc) + rc = 1; + } unlock: mutex_unlock(&volume_mutex); return rc; } -static int volume_set_volume(const u8 vol) +static int volume_alsa_set_volume(const u8 vol) { dbg_printk(TPACPI_DBG_MIXER, - "trying to set volume level to %hu\n", vol); - return volume_set_volume_ec(vol); + "ALSA: trying to set volume level to %hu\n", vol); + return __volume_set_volume_ec(vol); } static void volume_alsa_notify_change(void) @@ -6647,7 +6666,7 @@ static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol, static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - return volume_set_volume(ucontrol->value.integer.value[0]); + return volume_alsa_set_volume(ucontrol->value.integer.value[0]); } #define volume_alsa_mute_info snd_ctl_boolean_mono_info @@ -6670,7 +6689,7 @@ static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol, static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - return volume_set_mute(!ucontrol->value.integer.value[0]); + return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); } static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = { -- cgit v1.2.3-70-g09d2 From ced69c59811f05b2f8378467cbb82ac6ed3c6a5a Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sat, 20 Feb 2010 11:02:24 +0000 Subject: eeepc-laptop: disable wireless hotplug for 1005PE The wireless hotplug code is not needed on this model, and it disables the wired ethernet card. (Like on the 1005HA and 1201N). References: Signed-off-by: Alan Jenkins Reported-by: Ansgar Burchardt CC: stable@kernel.org --- drivers/platform/x86/eeepc-laptop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e2be6bb33d92..6a47bb7066d8 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1277,7 +1277,8 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * hotplug code. In fact, current hotplug code seems to unplug another * device... */ - if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { + if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 || + strcmp(model, "1005PE") == 0) { eeepc->hotplug_disabled = true; pr_info("wlan hotplug disabled\n"); } -- cgit v1.2.3-70-g09d2 From bc9d24a3aeb1532fc3e234907a8b6d671f7ed68f Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Mon, 22 Feb 2010 16:03:58 +0000 Subject: eeepc-laptop: check wireless hotplug events Before we mark the wireless device as unplugged, check PCI config space to see whether the wireless device is really disabled (and vice versa). This works around newer models which don't want the hotplug code, where we end up disabling the wired network device. My old 701 still works correctly with this. I can also simulate an afflicted model by changing the hardcoded PCI bus/slot number in the driver, and it seems to work nicely (although it is a bit noisy). In future this type of hotplug support will be implemented by the PCI core. The existing blacklist and the new warning message will be removed at that point. Signed-off-by: Alan Jenkins Signed-off-by: Corentin Chary --- drivers/platform/x86/eeepc-laptop.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 6a47bb7066d8..9a844caa3756 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -578,6 +578,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) struct pci_dev *dev; struct pci_bus *bus; bool blocked = eeepc_wlan_rfkill_blocked(eeepc); + bool absent; + u32 l; if (eeepc->wlan_rfkill) rfkill_set_sw_state(eeepc->wlan_rfkill, blocked); @@ -591,6 +593,22 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) goto out_unlock; } + if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { + pr_err("Unable to read PCI config space?\n"); + goto out_unlock; + } + absent = (l == 0xffffffff); + + if (blocked != absent) { + pr_warning("BIOS says wireless lan is %s, " + "but the pci device is %s\n", + blocked ? "blocked" : "unblocked", + absent ? "absent" : "present"); + pr_warning("skipped wireless hotplug as probably " + "inappropriate for this model\n"); + goto out_unlock; + } + if (!blocked) { dev = pci_get_slot(bus, 0); if (dev) { -- cgit v1.2.3-70-g09d2 From 0e875f4905817c03ba49447b49af093552e66e95 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 10 Jan 2010 20:49:26 +0100 Subject: asus-laptop: add wireless and bluetooth status parameter These to parameter allow to set the status of wlan and bluetooth device when the module load. On some models, the device will always be down on boot, so the default behavior is to always enable these devices. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 61a1c7503658..1d799b3fc4e8 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -113,6 +113,19 @@ static uint wapf = 1; module_param(wapf, uint, 0644); MODULE_PARM_DESC(wapf, "WAPF value"); +static uint wireless_status = 1; +static uint bluetooth_status = 1; + +module_param(wireless_status, uint, 0644); +MODULE_PARM_DESC(wireless_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " + "default is 1"); + +module_param(bluetooth_status, uint, 0644); +MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " + "default is 1"); + #define ASUS_HANDLE(object, paths...) \ static acpi_handle object##_handle = NULL; \ static char *object##_paths[] = { paths } @@ -1272,8 +1285,10 @@ static int asus_hotk_add(struct acpi_device *device) asus_hotk_found = 1; /* WLED and BLED are on by default */ - write_status(bt_switch_handle, 1, BT_ON); - write_status(wl_switch_handle, 1, WL_ON); + if (bluetooth_status != -1) + write_status(bt_switch_handle, !!bluetooth_status, BT_ON); + if (wireless_status != -1) + write_status(wl_switch_handle, !!wireless_status, WL_ON); /* If the h/w switch is off, we need to check the real status */ write_status(NULL, read_status(BT_ON), BT_ON); -- cgit v1.2.3-70-g09d2 From e5b50f6a2b00de266f03c2c7219b798648124ea5 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sat, 28 Nov 2009 10:19:55 +0100 Subject: asus-laptop: no need to check argument of set_brightness() We already tell the backlight class our maximum brightness value; it will validate the user requested values for us. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 1d799b3fc4e8..013ab86b1c8d 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -571,17 +571,11 @@ static int read_brightness(struct backlight_device *bd) static int set_brightness(struct backlight_device *bd, int value) { - int ret = 0; - - value = (0 < value) ? ((15 < value) ? 15 : value) : 0; - /* 0 <= value <= 15 */ - if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { pr_warning("Error changing brightness\n"); - ret = -EIO; + return -EIO; } - - return ret; + return 0; } static int update_bl_status(struct backlight_device *bd) -- cgit v1.2.3-70-g09d2 From d8c6732382a24d2ef23665207263a17f04e3d75a Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sat, 28 Nov 2009 10:27:51 +0100 Subject: asus-laptop: simplify write_acpi_int We only need a buffer for "INIT". Adds write_acpi_init_ret for it. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 013ab86b1c8d..7058cb56f338 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -352,8 +352,8 @@ static struct key_entry asus_keymap[] = { * * returns 0 if write is successful, -1 else. */ -static int write_acpi_int(acpi_handle handle, const char *method, int val, - struct acpi_buffer *output) +static int write_acpi_int_ret(acpi_handle handle, const char *method, int val, + struct acpi_buffer *output) { struct acpi_object_list params; /* list of input parameters (an int) */ union acpi_object in_obj; /* the only param we use */ @@ -374,6 +374,11 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, return -1; } +static int write_acpi_int(acpi_handle handle, const char *method, int val) +{ + return write_acpi_int_ret(handle, method, val, NULL); +} + static int read_wireless_status(int mask) { unsigned long long status; @@ -437,7 +442,7 @@ static void write_status(acpi_handle handle, int out, int mask) break; } - if (write_acpi_int(handle, NULL, out, NULL)) + if (write_acpi_int(handle, NULL, out)) pr_warning(" write failed %x\n", mask); } @@ -496,7 +501,7 @@ static int set_kled_lvl(int kblv) else kblv = 0; - if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { + if (write_acpi_int(kled_set_handle, NULL, kblv)) { pr_warning("Keyboard LED display write failed\n"); return -EINVAL; } @@ -571,7 +576,7 @@ static int read_brightness(struct backlight_device *bd) static int set_brightness(struct backlight_device *bd, int value) { - if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { + if (write_acpi_int(brightness_set_handle, NULL, value)) { pr_warning("Error changing brightness\n"); return -EIO; } @@ -710,7 +715,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) { - if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) + if (write_acpi_int(ledd_set_handle, NULL, value)) pr_warning("LED display write failed\n"); else hotk->ledd_status = (u32) value; @@ -755,7 +760,7 @@ static ssize_t store_bluetooth(struct device *dev, static void set_display(int value) { /* no sanity check needed for now */ - if (write_acpi_int(display_set_handle, NULL, value, NULL)) + if (write_acpi_int(display_set_handle, NULL, value)) pr_warning("Error setting display\n"); return; } @@ -814,7 +819,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, */ static void set_light_sens_switch(int value) { - if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) + if (write_acpi_int(ls_switch_handle, NULL, value)) pr_warning("Error setting light sensor switch\n"); hotk->light_switch = value; } @@ -839,7 +844,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, static void set_light_sens_level(int value) { - if (write_acpi_int(ls_level_handle, NULL, value, NULL)) + if (write_acpi_int(ls_level_handle, NULL, value)) pr_warning("Error setting light sensor level\n"); hotk->light_level = value; } @@ -1104,7 +1109,7 @@ static int asus_hotk_get_info(void) pr_warning("Couldn't get the DSDT table header\n"); /* We have to write 0 on init this far for all ASUS models */ - if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { + if (write_acpi_int_ret(hotk->handle, "INIT", 0, &buffer)) { pr_err("Hotkey initialization failed\n"); return -ENODEV; } @@ -1119,7 +1124,7 @@ static int asus_hotk_get_info(void) (uint) bsts_result); /* This too ... */ - write_acpi_int(hotk->handle, "CWAP", wapf, NULL); + write_acpi_int(hotk->handle, "CWAP", wapf); /* * Try to match the object returned by INIT to the specific model. -- cgit v1.2.3-70-g09d2 From 91687cc89af4c447483ec65097809c38c8622639 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sat, 28 Nov 2009 10:32:34 +0100 Subject: asus-laptop: use tabs to indent macros and remove unused ones Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 51 ++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 7058cb56f338..5889bda5a03b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -50,50 +50,43 @@ #include #include -#define ASUS_LAPTOP_VERSION "0.42" +#define ASUS_LAPTOP_VERSION "0.42" -#define ASUS_HOTK_NAME "Asus Laptop Support" -#define ASUS_HOTK_CLASS "hotkey" -#define ASUS_HOTK_DEVICE_NAME "Hotkey" -#define ASUS_HOTK_FILE KBUILD_MODNAME -#define ASUS_HOTK_PREFIX "\\_SB.ATKD." +#define ASUS_HOTK_NAME "Asus Laptop Support" +#define ASUS_HOTK_CLASS "hotkey" +#define ASUS_HOTK_DEVICE_NAME "Hotkey" +#define ASUS_HOTK_FILE KBUILD_MODNAME +#define ASUS_HOTK_PREFIX "\\_SB.ATKD." /* * Some events we use, same for all Asus */ -#define ATKD_BR_UP 0x10 -#define ATKD_BR_DOWN 0x20 -#define ATKD_LCD_ON 0x33 -#define ATKD_LCD_OFF 0x34 +#define ATKD_BR_UP 0x10 +#define ATKD_BR_DOWN 0x20 +#define ATKD_LCD_ON 0x33 +#define ATKD_LCD_OFF 0x34 /* * Known bits returned by \_SB.ATKD.HWRS */ -#define WL_HWRS 0x80 -#define BT_HWRS 0x100 +#define WL_HWRS 0x80 +#define BT_HWRS 0x100 /* * Flags for hotk status * WL_ON and BT_ON are also used for wireless_status() */ -#define WL_ON 0x01 /* internal Wifi */ -#define BT_ON 0x02 /* internal Bluetooth */ -#define MLED_ON 0x04 /* mail LED */ -#define TLED_ON 0x08 /* touchpad LED */ -#define RLED_ON 0x10 /* Record LED */ -#define PLED_ON 0x20 /* Phone LED */ -#define GLED_ON 0x40 /* Gaming LED */ -#define LCD_ON 0x80 /* LCD backlight */ -#define GPS_ON 0x100 /* GPS */ -#define KEY_ON 0x200 /* Keyboard backlight */ - -#define ASUS_LOG ASUS_HOTK_FILE ": " -#define ASUS_ERR KERN_ERR ASUS_LOG -#define ASUS_WARNING KERN_WARNING ASUS_LOG -#define ASUS_NOTICE KERN_NOTICE ASUS_LOG -#define ASUS_INFO KERN_INFO ASUS_LOG -#define ASUS_DEBUG KERN_DEBUG ASUS_LOG +#define WL_ON 0x01 /* internal Wifi */ +#define BT_ON 0x02 /* internal Bluetooth */ +#define MLED_ON 0x04 /* mail LED */ +#define TLED_ON 0x08 /* touchpad LED */ +#define RLED_ON 0x10 /* Record LED */ +#define PLED_ON 0x20 /* Phone LED */ +#define GLED_ON 0x40 /* Gaming LED */ +#define LCD_ON 0x80 /* LCD backlight */ +#define GPS_ON 0x100 /* GPS */ +#define KEY_ON 0x200 /* Keyboard backlight */ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); MODULE_DESCRIPTION(ASUS_HOTK_NAME); -- cgit v1.2.3-70-g09d2 From 619d8b1187f2e13f6f848b1b2a4d83c2c9e2a140 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sat, 28 Nov 2009 10:35:37 +0100 Subject: asus-laptop: remove unecessary hotk != NULL check Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 5889bda5a03b..74463a07d48b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -941,10 +941,6 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event) static struct key_entry *key; u16 count; - /* TODO Find a better way to handle events count. */ - if (!hotk) - return; - /* * We need to tell the backlight device when the backlight power is * switched @@ -957,6 +953,7 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event) lcd_blank(FB_BLANK_POWERDOWN); } + /* TODO Find a better way to handle events count. */ count = hotk->event_count[event % 128]++; acpi_bus_generate_proc_event(hotk->device, event, count); acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, -- cgit v1.2.3-70-g09d2 From 600ad5201d3b9b87159ede7359adccb98635fd48 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 30 Nov 2009 21:42:42 +0100 Subject: asus-laptop: change initialization order Clean asus-laptop initialization to match new eeepc-laptop code. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 369 ++++++++++++++++++------------------- 1 file changed, 180 insertions(+), 189 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 74463a07d48b..8834405be1fd 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -201,6 +201,8 @@ ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); */ struct asus_hotk { char *name; /* laptop name */ + + struct platform_device *platform_device; struct acpi_device *device; /* the device we are in */ acpi_handle handle; /* the handle of the hotk device */ char status; /* status of the hotk, for LEDs, ... */ @@ -222,33 +224,6 @@ static struct acpi_table_header *asus_info; /* The actual device the driver binds to */ static struct asus_hotk *hotk; -/* - * The hotkey driver declaration - */ -static const struct acpi_device_id asus_device_ids[] = { - {"ATK0100", 0}, - {"ATK0101", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, asus_device_ids); - -static int asus_hotk_add(struct acpi_device *device); -static int asus_hotk_remove(struct acpi_device *device, int type); -static void asus_hotk_notify(struct acpi_device *device, u32 event); - -static struct acpi_driver asus_hotk_driver = { - .name = ASUS_HOTK_NAME, - .class = ASUS_HOTK_CLASS, - .owner = THIS_MODULE, - .ids = asus_device_ids, - .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, - .ops = { - .add = asus_hotk_add, - .remove = asus_hotk_remove, - .notify = asus_hotk_notify, - }, -}; - /* The backlight device /sys/class/backlight */ static struct backlight_device *asus_backlight_device; @@ -936,7 +911,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) return -EINVAL; } -static void asus_hotk_notify(struct acpi_device *device, u32 event) +static void asus_acpi_notify(struct acpi_device *device, u32 event) { static struct key_entry *key; u16 count; @@ -1013,19 +988,49 @@ static struct attribute *asuspf_attributes[] = { NULL }; -static struct attribute_group asuspf_attribute_group = { +static struct attribute_group platform_attribute_group = { .attrs = asuspf_attributes }; -static struct platform_driver asuspf_driver = { +static int asus_platform_init(void) +{ + int result; + + hotk->platform_device = platform_device_alloc(ASUS_HOTK_FILE, -1); + if (!hotk->platform_device) + return -ENOMEM; + + result = platform_device_add(hotk->platform_device); + if (result) + goto fail_platform_device; + + result = sysfs_create_group(&hotk->platform_device->dev.kobj, + &platform_attribute_group); + if (result) + goto fail_sysfs; + return 0; + +fail_sysfs: + platform_device_del(hotk->platform_device); +fail_platform_device: + platform_device_put(hotk->platform_device); + return result; +} + +static void asus_platform_exit(void) +{ + sysfs_remove_group(&hotk->platform_device->dev.kobj, + &platform_attribute_group); + platform_device_unregister(hotk->platform_device); +} + +static struct platform_driver platform_driver = { .driver = { .name = ASUS_HOTK_FILE, .owner = THIS_MODULE, } }; -static struct platform_device *asuspf_device; - static void asus_hotk_add_fs(void) { ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); @@ -1196,7 +1201,7 @@ static int asus_hotk_get_info(void) return AE_OK; } -static int asus_input_init(void) +static int asus_input_init(struct device *dev) { const struct key_entry *key; int result; @@ -1207,6 +1212,7 @@ static int asus_input_init(void) return 0; } hotk->inputdev->name = "Asus Laptop extra buttons"; + hotk->inputdev->dev.parent = dev; hotk->inputdev->phys = ASUS_HOTK_FILE "/input0"; hotk->inputdev->id.bustype = BUS_HOST; hotk->inputdev->getkeycode = asus_getkeycode; @@ -1228,101 +1234,6 @@ static int asus_input_init(void) return result; } -static int asus_hotk_check(void) -{ - int result = 0; - - result = acpi_bus_get_status(hotk->device); - if (result) - return result; - - if (hotk->device->status.present) { - result = asus_hotk_get_info(); - } else { - pr_err("Hotkey device not present, aborting\n"); - return -EINVAL; - } - - return result; -} - -static int asus_hotk_found; - -static int asus_hotk_add(struct acpi_device *device) -{ - int result; - - pr_notice("Asus Laptop Support version %s\n", - ASUS_LAPTOP_VERSION); - - hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); - if (!hotk) - return -ENOMEM; - - hotk->handle = device->handle; - strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); - strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); - device->driver_data = hotk; - hotk->device = device; - - result = asus_hotk_check(); - if (result) - goto end; - - asus_hotk_add_fs(); - - asus_hotk_found = 1; - - /* WLED and BLED are on by default */ - if (bluetooth_status != -1) - write_status(bt_switch_handle, !!bluetooth_status, BT_ON); - if (wireless_status != -1) - write_status(wl_switch_handle, !!wireless_status, WL_ON); - - /* If the h/w switch is off, we need to check the real status */ - write_status(NULL, read_status(BT_ON), BT_ON); - write_status(NULL, read_status(WL_ON), WL_ON); - - /* LCD Backlight is on by default */ - write_status(NULL, 1, LCD_ON); - - /* Keyboard Backlight is on by default */ - if (kled_set_handle) - set_kled_lvl(1); - - /* LED display is off by default */ - hotk->ledd_status = 0xFFF; - - /* Set initial values of light sensor and level */ - hotk->light_switch = 0; /* Default to light sensor disabled */ - hotk->light_level = 5; /* level 5 for sensor sensitivity */ - - if (ls_switch_handle) - set_light_sens_switch(hotk->light_switch); - - if (ls_level_handle) - set_light_sens_level(hotk->light_level); - - /* GPS is on by default */ - write_status(NULL, 1, GPS_ON); - -end: - if (result) { - kfree(hotk->name); - kfree(hotk); - } - - return result; -} - -static int asus_hotk_remove(struct acpi_device *device, int type) -{ - kfree(hotk->name); - kfree(hotk); - - return 0; -} - static void asus_backlight_exit(void) { if (asus_backlight_device) @@ -1350,18 +1261,6 @@ static void asus_input_exit(void) input_unregister_device(hotk->inputdev); } -static void __exit asus_laptop_exit(void) -{ - asus_backlight_exit(); - asus_led_exit(); - asus_input_exit(); - - acpi_bus_unregister_driver(&asus_hotk_driver); - sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); - platform_device_unregister(asuspf_device); - platform_driver_unregister(&asuspf_driver); -} - static int asus_backlight_init(struct device *dev) { struct backlight_device *bd; @@ -1448,87 +1347,179 @@ out: return rv; } -static int __init asus_laptop_init(void) + +static bool asus_device_present; + +static int __devinit asus_acpi_init(struct acpi_device *device) { - int result; + int result = 0; - result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 0) + result = acpi_bus_get_status(hotk->device); + if (result) return result; - - /* - * This is a bit of a kludge. We only want this module loaded - * for ASUS systems, but there's currently no way to probe the - * ACPI namespace for ASUS HIDs. So we just return failure if - * we didn't find one, which will cause the module to be - * unloaded. - */ - if (!asus_hotk_found) { - acpi_bus_unregister_driver(&asus_hotk_driver); + if (!hotk->device->status.present) { + pr_err("Hotkey device not present, aborting\n"); return -ENODEV; } - result = asus_input_init(); + result = asus_hotk_get_info(); if (result) - goto fail_input; + return result; - /* Register platform stuff */ - result = platform_driver_register(&asuspf_driver); - if (result) - goto fail_platform_driver; + asus_hotk_add_fs(); - asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1); - if (!asuspf_device) { - result = -ENOMEM; - goto fail_platform_device1; - } + /* WLED and BLED are on by default */ + write_status(bt_switch_handle, 1, BT_ON); + write_status(wl_switch_handle, 1, WL_ON); - result = platform_device_add(asuspf_device); - if (result) - goto fail_platform_device2; + /* If the h/w switch is off, we need to check the real status */ + write_status(NULL, read_status(BT_ON), BT_ON); + write_status(NULL, read_status(WL_ON), WL_ON); + + /* LCD Backlight is on by default */ + write_status(NULL, 1, LCD_ON); - result = sysfs_create_group(&asuspf_device->dev.kobj, - &asuspf_attribute_group); + /* Keyboard Backlight is on by default */ + if (kled_set_handle) + set_kled_lvl(1); + + /* LED display is off by default */ + hotk->ledd_status = 0xFFF; + + /* Set initial values of light sensor and level */ + hotk->light_switch = 0; /* Default to light sensor disabled */ + hotk->light_level = 5; /* level 5 for sensor sensitivity */ + + if (ls_switch_handle) + set_light_sens_switch(hotk->light_switch); + + if (ls_level_handle) + set_light_sens_level(hotk->light_level); + + /* GPS is on by default */ + write_status(NULL, 1, GPS_ON); + return result; +} + +static int __devinit asus_acpi_add(struct acpi_device *device) +{ + int result; + + pr_notice("Asus Laptop Support version %s\n", + ASUS_LAPTOP_VERSION); + hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); + if (!hotk) + return -ENOMEM; + hotk->handle = device->handle; + strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); + strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); + device->driver_data = hotk; + hotk->device = device; + + result = asus_acpi_init(device); if (result) - goto fail_sysfs; + goto fail_platform; - result = asus_led_init(&asuspf_device->dev); + /* + * Register the platform device first. It is used as a parent for the + * sub-devices below. + */ + result = asus_platform_init(); if (result) - goto fail_led; + goto fail_platform; if (!acpi_video_backlight_support()) { - result = asus_backlight_init(&asuspf_device->dev); + result = asus_backlight_init(&hotk->platform_device->dev); if (result) goto fail_backlight; } else - pr_info("Brightness ignored, must be controlled by " - "ACPI video driver\n"); + pr_info("Backlight controlled by ACPI video driver\n"); + result = asus_input_init(&hotk->platform_device->dev); + if (result) + goto fail_input; + + result = asus_led_init(&hotk->platform_device->dev); + if (result) + goto fail_led; + + asus_device_present = true; return 0; +fail_led: + asus_input_exit(); +fail_input: + asus_backlight_exit(); fail_backlight: - asus_led_exit(); + asus_platform_exit(); +fail_platform: + kfree(hotk->name); + kfree(hotk); -fail_led: - sysfs_remove_group(&asuspf_device->dev.kobj, - &asuspf_attribute_group); + return result; +} -fail_sysfs: - platform_device_del(asuspf_device); +static int asus_acpi_remove(struct acpi_device *device, int type) +{ + asus_backlight_exit(); + asus_led_exit(); + asus_input_exit(); + asus_platform_exit(); + + kfree(hotk->name); + kfree(hotk); + return 0; +} + +static const struct acpi_device_id asus_device_ids[] = { + {"ATK0100", 0}, + {"ATK0101", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, asus_device_ids); -fail_platform_device2: - platform_device_put(asuspf_device); +static struct acpi_driver asus_acpi_driver = { + .name = ASUS_HOTK_NAME, + .class = ASUS_HOTK_CLASS, + .owner = THIS_MODULE, + .ids = asus_device_ids, + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, + .ops = { + .add = asus_acpi_add, + .remove = asus_acpi_remove, + .notify = asus_acpi_notify, + }, +}; -fail_platform_device1: - platform_driver_unregister(&asuspf_driver); +static int __init asus_laptop_init(void) +{ + int result; -fail_platform_driver: - asus_input_exit(); + result = platform_driver_register(&platform_driver); + if (result < 0) + return result; -fail_input: + result = acpi_bus_register_driver(&asus_acpi_driver); + if (result < 0) + goto fail_acpi_driver; + if (!asus_device_present) { + result = -ENODEV; + goto fail_no_device; + } + return 0; +fail_no_device: + acpi_bus_unregister_driver(&asus_acpi_driver); +fail_acpi_driver: + platform_driver_unregister(&platform_driver); return result; } +static void __exit asus_laptop_exit(void) +{ + acpi_bus_unregister_driver(&asus_acpi_driver); + platform_driver_unregister(&platform_driver); +} + module_init(asus_laptop_init); module_exit(asus_laptop_exit); -- cgit v1.2.3-70-g09d2 From 50a90c4d953fe4bb5a87ee5207c4243d25278189 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 30 Nov 2009 21:55:12 +0100 Subject: asus-laptop: revise names asus-laptop now does a lot more than just hotkeys. Replace the "hotk" names used throughout the driver with some slightly more appropriate names. The actual strings used in kernel messages and sysfs are left unchanged. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 221 +++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 110 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8834405be1fd..2505f15cbe6b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -52,11 +52,11 @@ #define ASUS_LAPTOP_VERSION "0.42" -#define ASUS_HOTK_NAME "Asus Laptop Support" -#define ASUS_HOTK_CLASS "hotkey" -#define ASUS_HOTK_DEVICE_NAME "Hotkey" -#define ASUS_HOTK_FILE KBUILD_MODNAME -#define ASUS_HOTK_PREFIX "\\_SB.ATKD." +#define ASUS_LAPTOP_NAME "Asus Laptop Support" +#define ASUS_LAPTOP_CLASS "hotkey" +#define ASUS_LAPTOP_DEVICE_NAME "Hotkey" +#define ASUS_LAPTOP_FILE KBUILD_MODNAME +#define ASUS_LAPTOP_PREFIX "\\_SB.ATKD." /* @@ -89,7 +89,7 @@ #define KEY_ON 0x200 /* Keyboard backlight */ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); -MODULE_DESCRIPTION(ASUS_HOTK_NAME); +MODULE_DESCRIPTION(ASUS_LAPTOP_NAME); MODULE_LICENSE("GPL"); /* @@ -124,27 +124,27 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " static char *object##_paths[] = { paths } /* LED */ -ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED"); -ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED"); -ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */ -ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */ -ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */ +ASUS_HANDLE(mled_set, ASUS_LAPTOP_PREFIX "MLED"); +ASUS_HANDLE(tled_set, ASUS_LAPTOP_PREFIX "TLED"); +ASUS_HANDLE(rled_set, ASUS_LAPTOP_PREFIX "RLED"); /* W1JC */ +ASUS_HANDLE(pled_set, ASUS_LAPTOP_PREFIX "PLED"); /* A7J */ +ASUS_HANDLE(gled_set, ASUS_LAPTOP_PREFIX "GLED"); /* G1, G2 (probably) */ /* LEDD */ -ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); +ASUS_HANDLE(ledd_set, ASUS_LAPTOP_PREFIX "SLCM"); /* * Bluetooth and WLAN * WLED and BLED are not handled like other XLED, because in some dsdt * they also control the WLAN/Bluetooth device. */ -ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED"); -ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED"); -ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS"); /* All new models */ +ASUS_HANDLE(wl_switch, ASUS_LAPTOP_PREFIX "WLED"); +ASUS_HANDLE(bt_switch, ASUS_LAPTOP_PREFIX "BLED"); +ASUS_HANDLE(wireless_status, ASUS_LAPTOP_PREFIX "RSTS"); /* All new models */ /* Brightness */ -ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV"); -ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV"); +ASUS_HANDLE(brightness_set, ASUS_LAPTOP_PREFIX "SPLV"); +ASUS_HANDLE(brightness_get, ASUS_LAPTOP_PREFIX "GPLV"); /* Backlight */ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ @@ -157,7 +157,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ "\\Q10"); /* A2x, L2D, L3D, M2E */ /* Display */ -ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); +ASUS_HANDLE(display_set, ASUS_LAPTOP_PREFIX "SDSP"); ASUS_HANDLE(display_get, /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ "\\_SB.PCI0.P0P1.VGA.GETD", @@ -182,24 +182,24 @@ ASUS_HANDLE(display_get, /* A3F A6F A3N A3L M6N W3N W6A */ "\\SSTE"); -ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ -ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ +ASUS_HANDLE(ls_switch, ASUS_LAPTOP_PREFIX "ALSC"); /* Z71A Z71V */ +ASUS_HANDLE(ls_level, ASUS_LAPTOP_PREFIX "ALSL"); /* Z71A Z71V */ /* GPS */ /* R2H use different handle for GPS on/off */ -ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ -ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ -ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); +ASUS_HANDLE(gps_on, ASUS_LAPTOP_PREFIX "SDON"); /* R2H */ +ASUS_HANDLE(gps_off, ASUS_LAPTOP_PREFIX "SDOF"); /* R2H */ +ASUS_HANDLE(gps_status, ASUS_LAPTOP_PREFIX "GPST"); /* Keyboard light */ -ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); -ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); +ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB"); +ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); /* * This is the main structure, we can use it to store anything interesting * about the hotk device */ -struct asus_hotk { +struct asus_laptop { char *name; /* laptop name */ struct platform_device *platform_device; @@ -216,13 +216,13 @@ struct asus_hotk { /* * This header is made available to allow proper configuration given model, - * revision number , ... this info cannot go in struct asus_hotk because it is + * revision number , ... this info cannot go in struct asus_laptop because it is * available before the hotk */ static struct acpi_table_header *asus_info; /* The actual device the driver binds to */ -static struct asus_hotk *hotk; +static struct asus_laptop *asus; /* The backlight device /sys/class/backlight */ static struct backlight_device *asus_backlight_device; @@ -353,7 +353,7 @@ static int read_wireless_status(int mask) acpi_status rv = AE_OK; if (!wireless_status_handle) - return (hotk->status & mask) ? 1 : 0; + return (asus->status & mask) ? 1 : 0; rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); if (ACPI_FAILURE(rv)) @@ -361,7 +361,7 @@ static int read_wireless_status(int mask) else return (status & mask) ? 1 : 0; - return (hotk->status & mask) ? 1 : 0; + return (asus->status & mask) ? 1 : 0; } static int read_gps_status(void) @@ -375,7 +375,7 @@ static int read_gps_status(void) else return status ? 1 : 0; - return (hotk->status & GPS_ON) ? 1 : 0; + return (asus->status & GPS_ON) ? 1 : 0; } /* Generic LED functions */ @@ -387,12 +387,12 @@ static int read_status(int mask) else if (mask == GPS_ON) return read_gps_status(); - return (hotk->status & mask) ? 1 : 0; + return (asus->status & mask) ? 1 : 0; } static void write_status(acpi_handle handle, int out, int mask) { - hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask); + asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); switch (mask) { case MLED_ON: @@ -586,15 +586,15 @@ static ssize_t show_infos(struct device *dev, * to 1 */ - len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n"); - len += sprintf(page + len, "Model reference : %s\n", hotk->name); + len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n"); + len += sprintf(page + len, "Model reference : %s\n", asus->name); /* * The SFUN method probably allows the original driver to get the list * of features supported by a given model. For now, 0x0100 or 0x0800 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. * The significance of others is yet to be found. */ - rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "SFUN", NULL, &temp); if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "SFUN value : %#x\n", (uint) temp); @@ -604,7 +604,7 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "HRWS value : %#x\n", (uint) temp); @@ -615,7 +615,7 @@ static ssize_t show_infos(struct device *dev, * Note: since not all the laptops provide this method, errors are * silently ignored. */ - rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "ASYM", NULL, &temp); if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "ASYM value : %#x\n", (uint) temp); @@ -673,7 +673,7 @@ static ssize_t store_status(const char *buf, size_t count, static ssize_t show_ledd(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "0x%08x\n", hotk->ledd_status); + return sprintf(buf, "0x%08x\n", asus->ledd_status); } static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, @@ -686,7 +686,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, if (write_acpi_int(ledd_set_handle, NULL, value)) pr_warning("LED display write failed\n"); else - hotk->ledd_status = (u32) value; + asus->ledd_status = (u32) value; } return rv; } @@ -789,13 +789,13 @@ static void set_light_sens_switch(int value) { if (write_acpi_int(ls_switch_handle, NULL, value)) pr_warning("Error setting light sensor switch\n"); - hotk->light_switch = value; + asus->light_switch = value; } static ssize_t show_lssw(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", hotk->light_switch); + return sprintf(buf, "%d\n", asus->light_switch); } static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, @@ -814,13 +814,13 @@ static void set_light_sens_level(int value) { if (write_acpi_int(ls_level_handle, NULL, value)) pr_warning("Error setting light sensor level\n"); - hotk->light_level = value; + asus->light_level = value; } static ssize_t show_lslvl(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", hotk->light_level); + return sprintf(buf, "%d\n", asus->light_level); } static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, @@ -929,23 +929,23 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) } /* TODO Find a better way to handle events count. */ - count = hotk->event_count[event % 128]++; - acpi_bus_generate_proc_event(hotk->device, event, count); - acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, - dev_name(&hotk->device->dev), event, + count = asus->event_count[event % 128]++; + acpi_bus_generate_proc_event(asus->device, event, count); + acpi_bus_generate_netlink_event(asus->device->pnp.device_class, + dev_name(&asus->device->dev), event, count); - if (hotk->inputdev) { + if (asus->inputdev) { key = asus_get_entry_by_scancode(event); if (!key) return ; switch (key->type) { case KE_KEY: - input_report_key(hotk->inputdev, key->keycode, 1); - input_sync(hotk->inputdev); - input_report_key(hotk->inputdev, key->keycode, 0); - input_sync(hotk->inputdev); + input_report_key(asus->inputdev, key->keycode, 1); + input_sync(asus->inputdev); + input_report_key(asus->inputdev, key->keycode, 0); + input_sync(asus->inputdev); break; } } @@ -996,42 +996,42 @@ static int asus_platform_init(void) { int result; - hotk->platform_device = platform_device_alloc(ASUS_HOTK_FILE, -1); - if (!hotk->platform_device) + asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); + if (!asus->platform_device) return -ENOMEM; - result = platform_device_add(hotk->platform_device); + result = platform_device_add(asus->platform_device); if (result) goto fail_platform_device; - result = sysfs_create_group(&hotk->platform_device->dev.kobj, + result = sysfs_create_group(&asus->platform_device->dev.kobj, &platform_attribute_group); if (result) goto fail_sysfs; return 0; fail_sysfs: - platform_device_del(hotk->platform_device); + platform_device_del(asus->platform_device); fail_platform_device: - platform_device_put(hotk->platform_device); + platform_device_put(asus->platform_device); return result; } static void asus_platform_exit(void) { - sysfs_remove_group(&hotk->platform_device->dev.kobj, + sysfs_remove_group(&asus->platform_device->dev.kobj, &platform_attribute_group); - platform_device_unregister(hotk->platform_device); + platform_device_unregister(asus->platform_device); } static struct platform_driver platform_driver = { .driver = { - .name = ASUS_HOTK_FILE, + .name = ASUS_LAPTOP_FILE, .owner = THIS_MODULE, } }; -static void asus_hotk_add_fs(void) +static void asus_laptop_add_fs(void) { ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); @@ -1080,10 +1080,11 @@ static int asus_handle_init(char *name, acpi_handle * handle, ARRAY_SIZE(object##_paths)) /* - * This function is used to initialize the hotk with right values. In this - * method, we can make all the detection we want, and modify the hotk struct + * This function is used to initialize the context with right values. In this + * method, we can make all the detection we want, and modify the asus_laptop + * struct */ -static int asus_hotk_get_info(void) +static int asus_laptop_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; @@ -1104,14 +1105,14 @@ static int asus_hotk_get_info(void) pr_warning("Couldn't get the DSDT table header\n"); /* We have to write 0 on init this far for all ASUS models */ - if (write_acpi_int_ret(hotk->handle, "INIT", 0, &buffer)) { + if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { pr_err("Hotkey initialization failed\n"); return -ENODEV; } /* This needs to be called for some laptops to init properly */ status = - acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); + acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); if (ACPI_FAILURE(status)) pr_warning("Error calling BSTS\n"); else if (bsts_result) @@ -1119,7 +1120,7 @@ static int asus_hotk_get_info(void) (uint) bsts_result); /* This too ... */ - write_acpi_int(hotk->handle, "CWAP", wapf); + write_acpi_int(asus->handle, "CWAP", wapf); /* * Try to match the object returned by INIT to the specific model. @@ -1141,8 +1142,8 @@ static int asus_hotk_get_info(void) break; } } - hotk->name = kstrdup(string, GFP_KERNEL); - if (!hotk->name) + asus->name = kstrdup(string, GFP_KERNEL); + if (!asus->name) return -ENOMEM; if (*string) @@ -1166,7 +1167,7 @@ static int asus_hotk_get_info(void) * If we don't find the method, we assume the device are present. */ status = - acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); if (ACPI_FAILURE(status)) hwrs_result = WL_HWRS | BT_HWRS; @@ -1206,30 +1207,30 @@ static int asus_input_init(struct device *dev) const struct key_entry *key; int result; - hotk->inputdev = input_allocate_device(); - if (!hotk->inputdev) { + asus->inputdev = input_allocate_device(); + if (!asus->inputdev) { pr_info("Unable to allocate input device\n"); return 0; } - hotk->inputdev->name = "Asus Laptop extra buttons"; - hotk->inputdev->dev.parent = dev; - hotk->inputdev->phys = ASUS_HOTK_FILE "/input0"; - hotk->inputdev->id.bustype = BUS_HOST; - hotk->inputdev->getkeycode = asus_getkeycode; - hotk->inputdev->setkeycode = asus_setkeycode; + asus->inputdev->name = "Asus Laptop extra buttons"; + asus->inputdev->dev.parent = dev; + asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; + asus->inputdev->id.bustype = BUS_HOST; + asus->inputdev->getkeycode = asus_getkeycode; + asus->inputdev->setkeycode = asus_setkeycode; for (key = asus_keymap; key->type != KE_END; key++) { switch (key->type) { case KE_KEY: - set_bit(EV_KEY, hotk->inputdev->evbit); - set_bit(key->keycode, hotk->inputdev->keybit); + set_bit(EV_KEY, asus->inputdev->evbit); + set_bit(key->keycode, asus->inputdev->keybit); break; } } - result = input_register_device(hotk->inputdev); + result = input_register_device(asus->inputdev); if (result) { pr_info("Unable to register input device\n"); - input_free_device(hotk->inputdev); + input_free_device(asus->inputdev); } return result; } @@ -1257,8 +1258,8 @@ static void asus_led_exit(void) static void asus_input_exit(void) { - if (hotk->inputdev) - input_unregister_device(hotk->inputdev); + if (asus->inputdev) + input_unregister_device(asus->inputdev); } static int asus_backlight_init(struct device *dev) @@ -1266,7 +1267,7 @@ static int asus_backlight_init(struct device *dev) struct backlight_device *bd; if (brightness_set_handle && lcd_switch_handle) { - bd = backlight_device_register(ASUS_HOTK_FILE, dev, + bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, NULL, &asusbl_ops); if (IS_ERR(bd)) { pr_err("Could not register asus backlight device\n"); @@ -1354,19 +1355,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device) { int result = 0; - result = acpi_bus_get_status(hotk->device); + result = acpi_bus_get_status(asus->device); if (result) return result; - if (!hotk->device->status.present) { + if (!asus->device->status.present) { pr_err("Hotkey device not present, aborting\n"); return -ENODEV; } - result = asus_hotk_get_info(); + result = asus_laptop_get_info(); if (result) return result; - asus_hotk_add_fs(); + asus_laptop_add_fs(); /* WLED and BLED are on by default */ write_status(bt_switch_handle, 1, BT_ON); @@ -1384,17 +1385,17 @@ static int __devinit asus_acpi_init(struct acpi_device *device) set_kled_lvl(1); /* LED display is off by default */ - hotk->ledd_status = 0xFFF; + asus->ledd_status = 0xFFF; /* Set initial values of light sensor and level */ hotk->light_switch = 0; /* Default to light sensor disabled */ hotk->light_level = 5; /* level 5 for sensor sensitivity */ if (ls_switch_handle) - set_light_sens_switch(hotk->light_switch); + set_light_sens_switch(asus->light_switch); if (ls_level_handle) - set_light_sens_level(hotk->light_level); + set_light_sens_level(asus->light_level); /* GPS is on by default */ write_status(NULL, 1, GPS_ON); @@ -1407,14 +1408,14 @@ static int __devinit asus_acpi_add(struct acpi_device *device) pr_notice("Asus Laptop Support version %s\n", ASUS_LAPTOP_VERSION); - hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); - if (!hotk) + asus = kzalloc(sizeof(struct asus_laptop), GFP_KERNEL); + if (!asus) return -ENOMEM; - hotk->handle = device->handle; - strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); - strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); - device->driver_data = hotk; - hotk->device = device; + asus->handle = device->handle; + strcpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME); + strcpy(acpi_device_class(device), ASUS_LAPTOP_CLASS); + device->driver_data = asus; + asus->device = device; result = asus_acpi_init(device); if (result) @@ -1429,17 +1430,17 @@ static int __devinit asus_acpi_add(struct acpi_device *device) goto fail_platform; if (!acpi_video_backlight_support()) { - result = asus_backlight_init(&hotk->platform_device->dev); + result = asus_backlight_init(&asus->platform_device->dev); if (result) goto fail_backlight; } else pr_info("Backlight controlled by ACPI video driver\n"); - result = asus_input_init(&hotk->platform_device->dev); + result = asus_input_init(&asus->platform_device->dev); if (result) goto fail_input; - result = asus_led_init(&hotk->platform_device->dev); + result = asus_led_init(&asus->platform_device->dev); if (result) goto fail_led; @@ -1453,8 +1454,8 @@ fail_input: fail_backlight: asus_platform_exit(); fail_platform: - kfree(hotk->name); - kfree(hotk); + kfree(asus->name); + kfree(asus); return result; } @@ -1466,8 +1467,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type) asus_input_exit(); asus_platform_exit(); - kfree(hotk->name); - kfree(hotk); + kfree(asus->name); + kfree(asus); return 0; } @@ -1479,8 +1480,8 @@ static const struct acpi_device_id asus_device_ids[] = { MODULE_DEVICE_TABLE(acpi, asus_device_ids); static struct acpi_driver asus_acpi_driver = { - .name = ASUS_HOTK_NAME, - .class = ASUS_HOTK_CLASS, + .name = ASUS_LAPTOP_NAME, + .class = ASUS_LAPTOP_CLASS, .owner = THIS_MODULE, .ids = asus_device_ids, .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, -- cgit v1.2.3-70-g09d2 From 7c247645f305da2bb309fa439fd6cc0aa26f8722 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 30 Nov 2009 22:13:54 +0100 Subject: asus-laptop: move backlight and dsdt info inside asus_laptop struct Prepare the use of "driver data" for callbacks. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 69 +++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 39 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 2505f15cbe6b..4ff30ca4df12 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -202,30 +202,24 @@ ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); struct asus_laptop { char *name; /* laptop name */ + struct acpi_table_header *dsdt_info; struct platform_device *platform_device; - struct acpi_device *device; /* the device we are in */ + struct acpi_device *device; /* the device we are in */ + struct backlight_device *backlight_device; + struct input_dev *inputdev; + acpi_handle handle; /* the handle of the hotk device */ char status; /* status of the hotk, for LEDs, ... */ u32 ledd_status; /* status of the LED display */ u8 light_level; /* light sensor level */ u8 light_switch; /* light sensor switch value */ u16 event_count[128]; /* count for each event TODO make this better */ - struct input_dev *inputdev; u16 *keycode_map; }; -/* - * This header is made available to allow proper configuration given model, - * revision number , ... this info cannot go in struct asus_laptop because it is - * available before the hotk - */ -static struct acpi_table_header *asus_info; - -/* The actual device the driver binds to */ static struct asus_laptop *asus; -/* The backlight device /sys/class/backlight */ -static struct backlight_device *asus_backlight_device; +static struct workqueue_struct *led_workqueue; /* * The backlight class declaration @@ -237,14 +231,6 @@ static struct backlight_ops asusbl_ops = { .update_status = update_bl_status, }; -/* - * 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 struct workqueue_struct *led_workqueue; - #define ASUS_LED(object, ledname, max) \ static void object##_led_set(struct led_classdev *led_cdev, \ enum led_brightness value); \ @@ -522,7 +508,7 @@ static int set_lcd_state(int value) static void lcd_blank(int blank) { - struct backlight_device *bd = asus_backlight_device; + struct backlight_device *bd = asus->backlight_device; if (bd) { bd->props.power = blank; @@ -619,22 +605,22 @@ static ssize_t show_infos(struct device *dev, if (!ACPI_FAILURE(rv)) len += sprintf(page + len, "ASYM value : %#x\n", (uint) temp); - if (asus_info) { - snprintf(buf, 16, "%d", asus_info->length); + if (asus->dsdt_info) { + snprintf(buf, 16, "%d", asus->dsdt_info->length); len += sprintf(page + len, "DSDT length : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->checksum); + snprintf(buf, 16, "%d", asus->dsdt_info->checksum); len += sprintf(page + len, "DSDT checksum : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->revision); + snprintf(buf, 16, "%d", asus->dsdt_info->revision); len += sprintf(page + len, "DSDT revision : %s\n", buf); - snprintf(buf, 7, "%s", asus_info->oem_id); + snprintf(buf, 7, "%s", asus->dsdt_info->oem_id); len += sprintf(page + len, "OEM id : %s\n", buf); - snprintf(buf, 9, "%s", asus_info->oem_table_id); + snprintf(buf, 9, "%s", asus->dsdt_info->oem_table_id); len += sprintf(page + len, "OEM table id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->oem_revision); + snprintf(buf, 16, "%x", asus->dsdt_info->oem_revision); len += sprintf(page + len, "OEM revision : 0x%s\n", buf); - snprintf(buf, 5, "%s", asus_info->asl_compiler_id); + snprintf(buf, 5, "%s", asus->dsdt_info->asl_compiler_id); len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); + snprintf(buf, 16, "%x", asus->dsdt_info->asl_compiler_revision); len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); } @@ -1084,7 +1070,7 @@ static int asus_handle_init(char *name, acpi_handle * handle, * method, we can make all the detection we want, and modify the asus_laptop * struct */ -static int asus_laptop_get_info(void) +static int asus_laptop_get_info(struct asus_laptop *asus) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; @@ -1097,10 +1083,9 @@ static int asus_laptop_get_info(void) * models, but late enough to allow acpi_bus_register_driver() to fail * before doing anything ACPI-specific. Should we encounter a machine, * which needs special handling (i.e. its hotkey device has a different - * HID), this bit will be moved. A global variable asus_info contains - * the DSDT header. + * HID), this bit will be moved. */ - status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); + status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); if (ACPI_FAILURE(status)) pr_warning("Couldn't get the DSDT table header\n"); @@ -1237,8 +1222,8 @@ static int asus_input_init(struct device *dev) static void asus_backlight_exit(void) { - if (asus_backlight_device) - backlight_device_unregister(asus_backlight_device); + if (asus->backlight_device) + backlight_device_unregister(asus->backlight_device); } #define ASUS_LED_UNREGISTER(object) \ @@ -1271,11 +1256,11 @@ static int asus_backlight_init(struct device *dev) NULL, &asusbl_ops); if (IS_ERR(bd)) { pr_err("Could not register asus backlight device\n"); - asus_backlight_device = NULL; + asus->backlight_device = NULL; return PTR_ERR(bd); } - asus_backlight_device = bd; + asus->backlight_device = bd; bd->props.max_brightness = 15; bd->props.brightness = read_brightness(NULL); @@ -1326,6 +1311,12 @@ static int asus_led_init(struct device *dev) if (rv) goto out5; + /* + * Functions that actually update the LED's 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. + */ led_workqueue = create_singlethread_workqueue("led_workqueue"); if (!led_workqueue) goto out6; @@ -1363,7 +1354,7 @@ static int __devinit asus_acpi_init(struct acpi_device *device) return -ENODEV; } - result = asus_laptop_get_info(); + result = asus_laptop_get_info(asus); if (result) return result; -- cgit v1.2.3-70-g09d2 From 9129d14d297e78bc21caffa44d55a5920a74862c Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 1 Dec 2009 22:39:41 +0100 Subject: asus-laptop: callbacks should use "driver data" parameter or field (Changelog stolen from Alan's patch for eeepc-laptop, but this patch does the same thing for asus-laptop) Callback methods should not refer to a variable like "asus" (formally "hotk"). Instead, they should extract the data they need either from a "driver data" parameter, or the "driver data" field of the object which they operate on. The "asus" variable can then be removed. In practice, drivers under "drivers/platform" can get away without using driver data, because it doesn't make sense to have more than one instance of them. However this makes it harder to review them for correctness. This is especially true for core ACPI developers who have not previously been exposed to this anti-pattern :-). This will serve as an example of best practice for new driver writers (whether they find it themselves, or have it pointed out during review :-). Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 362 +++++++++++++++++++++---------------- 1 file changed, 209 insertions(+), 153 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 4ff30ca4df12..58a4864096d9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -195,6 +195,34 @@ ASUS_HANDLE(gps_status, ASUS_LAPTOP_PREFIX "GPST"); ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB"); ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); +/* + * Define a specific led structure to keep the main structure clean + */ +#define ASUS_DEFINE_LED(object) \ + int object##_wk; \ + struct work_struct object##_work; \ + struct led_classdev object; + + +#define led_to_asus(led_cdev, led) \ + container_of(container_of(led_cdev, struct asus_laptop_leds, \ + led), \ + struct asus_laptop, leds) +#define work_to_asus(work, led) \ + container_of(container_of(work, struct asus_laptop_leds, \ + led##_work), \ + struct asus_laptop, leds) + +struct asus_laptop_leds { + ASUS_DEFINE_LED(mled) + ASUS_DEFINE_LED(tled) + ASUS_DEFINE_LED(rled) + ASUS_DEFINE_LED(pled) + ASUS_DEFINE_LED(gled) + ASUS_DEFINE_LED(kled) + struct workqueue_struct *workqueue; +}; + /* * This is the main structure, we can use it to store anything interesting * about the hotk device @@ -206,7 +234,11 @@ struct asus_laptop { struct platform_device *platform_device; struct acpi_device *device; /* the device we are in */ struct backlight_device *backlight_device; + struct input_dev *inputdev; + struct key_entry *keymap; + + struct asus_laptop_leds leds; acpi_handle handle; /* the handle of the hotk device */ char status; /* status of the hotk, for LEDs, ... */ @@ -217,10 +249,6 @@ struct asus_laptop { u16 *keycode_map; }; -static struct asus_laptop *asus; - -static struct workqueue_struct *led_workqueue; - /* * The backlight class declaration */ @@ -237,8 +265,6 @@ static struct backlight_ops asusbl_ops = { static enum led_brightness object##_led_get( \ struct led_classdev *led_cdev); \ static void object##_led_update(struct work_struct *ignored); \ - static int object##_led_wk; \ - static DECLARE_WORK(object##_led_work, object##_led_update); \ static struct led_classdev object##_led = { \ .name = "asus::" ledname, \ .brightness_set = object##_led_set, \ @@ -261,7 +287,7 @@ struct key_entry { enum { KE_KEY, KE_END }; -static struct key_entry asus_keymap[] = { +static const struct key_entry asus_keymap[] = { {KE_KEY, 0x02, KEY_SCREENLOCK}, {KE_KEY, 0x05, KEY_WLAN}, {KE_KEY, 0x08, KEY_F13}, @@ -333,7 +359,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) return write_acpi_int_ret(handle, method, val, NULL); } -static int read_wireless_status(int mask) +static int read_wireless_status(struct asus_laptop *asus, int mask) { unsigned long long status; acpi_status rv = AE_OK; @@ -350,7 +376,7 @@ static int read_wireless_status(int mask) return (asus->status & mask) ? 1 : 0; } -static int read_gps_status(void) +static int read_gps_status(struct asus_laptop *asus) { unsigned long long status; acpi_status rv = AE_OK; @@ -365,18 +391,19 @@ static int read_gps_status(void) } /* Generic LED functions */ -static int read_status(int mask) +static int read_status(struct asus_laptop *asus, int mask) { /* There is a special method for both wireless devices */ if (mask == BT_ON || mask == WL_ON) - return read_wireless_status(mask); + return read_wireless_status(asus, mask); else if (mask == GPS_ON) - return read_gps_status(); + return read_gps_status(asus); return (asus->status & mask) ? 1 : 0; } -static void write_status(acpi_handle handle, int out, int mask) +static void write_status(struct asus_laptop *asus, acpi_handle handle, + int out, int mask) { asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); @@ -405,13 +432,19 @@ static void write_status(acpi_handle handle, int out, int mask) static void object##_led_set(struct led_classdev *led_cdev, \ enum led_brightness value) \ { \ - object##_led_wk = (value > 0) ? 1 : 0; \ - queue_work(led_workqueue, &object##_led_work); \ + struct asus_laptop *asus = \ + led_to_asus(led_cdev, object); \ + \ + asus->leds.object##_wk = (value > 0) ? 1 : 0; \ + queue_work(asus->leds.workqueue, \ + &asus->leds.object##_work); \ } \ - static void object##_led_update(struct work_struct *ignored) \ + static void object##_led_update(struct work_struct *work) \ { \ - int value = object##_led_wk; \ - write_status(object##_set_handle, value, (mask)); \ + struct asus_laptop *asus = work_to_asus(work, object); \ + \ + int value = asus->leds.object##_wk; \ + write_status(asus, object##_set_handle, value, (mask)); \ } \ static enum led_brightness object##_led_get( \ struct led_classdev *led_cdev) \ @@ -448,7 +481,7 @@ static int get_kled_lvl(void) return kblv; } -static int set_kled_lvl(int kblv) +static int set_kled_lvl(struct asus_laptop *asus, int kblv) { if (kblv > 0) kblv = (1 << 7) | (kblv & 0x7F); @@ -465,13 +498,17 @@ static int set_kled_lvl(int kblv) static void kled_led_set(struct led_classdev *led_cdev, enum led_brightness value) { - kled_led_wk = value; - queue_work(led_workqueue, &kled_led_work); + struct asus_laptop *asus = led_to_asus(led_cdev, kled); + + asus->leds.kled_wk = value; + queue_work(asus->leds.workqueue, &asus->leds.kled_work); } -static void kled_led_update(struct work_struct *ignored) +static void kled_led_update(struct work_struct *work) { - set_kled_lvl(kled_led_wk); + struct asus_laptop *asus = work_to_asus(work, kled); + + set_kled_lvl(asus, asus->leds.kled_wk); } static enum led_brightness kled_led_get(struct led_classdev *led_cdev) @@ -479,19 +516,19 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev) return get_kled_lvl(); } -static int get_lcd_state(void) +static int get_lcd_state(struct asus_laptop *asus) { - return read_status(LCD_ON); + return read_status(asus, LCD_ON); } -static int set_lcd_state(int value) +static int set_lcd_state(struct asus_laptop *asus, int value) { int lcd = 0; acpi_status status = 0; lcd = value ? 1 : 0; - if (lcd == get_lcd_state()) + if (lcd == get_lcd_state(asus)) return 0; if (lcd_switch_handle) { @@ -502,11 +539,11 @@ static int set_lcd_state(int value) pr_warning("Error switching LCD\n"); } - write_status(NULL, lcd, LCD_ON); + write_status(asus, NULL, lcd, LCD_ON); return 0; } -static void lcd_blank(int blank) +static void lcd_blank(struct asus_laptop *asus, int blank) { struct backlight_device *bd = asus->backlight_device; @@ -539,6 +576,7 @@ static int set_brightness(struct backlight_device *bd, int value) static int update_bl_status(struct backlight_device *bd) { + struct asus_laptop *asus = bl_get_data(bd); int rv; int value = bd->props.brightness; @@ -547,7 +585,7 @@ static int update_bl_status(struct backlight_device *bd) return rv; value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; - return set_lcd_state(value); + return set_lcd_state(asus, value); } /* @@ -562,6 +600,7 @@ static int update_bl_status(struct backlight_device *bd) static ssize_t show_infos(struct device *dev, struct device_attribute *attr, char *page) { + struct asus_laptop *asus = dev_get_drvdata(dev); int len = 0; unsigned long long temp; char buf[16]; /* enough for all info */ @@ -638,7 +677,8 @@ static int parse_arg(const char *buf, unsigned long count, int *val) return count; } -static ssize_t store_status(const char *buf, size_t count, +static ssize_t store_status(struct asus_laptop *asus, + const char *buf, size_t count, acpi_handle handle, int mask) { int rv, value; @@ -648,7 +688,7 @@ static ssize_t store_status(const char *buf, size_t count, if (rv > 0) out = value ? 1 : 0; - write_status(handle, out, mask); + write_status(asus, handle, out, mask); return rv; } @@ -659,12 +699,15 @@ static ssize_t store_status(const char *buf, size_t count, static ssize_t show_ledd(struct device *dev, struct device_attribute *attr, char *buf) { + struct asus_laptop *asus = dev_get_drvdata(dev); + return sprintf(buf, "0x%08x\n", asus->ledd_status); } static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct asus_laptop *asus = dev_get_drvdata(dev); int rv, value; rv = parse_arg(buf, count, &value); @@ -683,13 +726,17 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, static ssize_t show_wlan(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", read_status(WL_ON)); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", read_status(asus, WL_ON)); } static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return store_status(buf, count, wl_switch_handle, WL_ON); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return store_status(asus, buf, count, wl_switch_handle, WL_ON); } /* @@ -698,20 +745,24 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", read_status(BT_ON)); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", read_status(asus, BT_ON)); } static ssize_t store_bluetooth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return store_status(buf, count, bt_switch_handle, BT_ON); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return store_status(asus, buf, count, bt_switch_handle, BT_ON); } /* * Display */ -static void set_display(int value) +static void set_display(struct asus_laptop *asus, int value) { /* no sanity check needed for now */ if (write_acpi_int(display_set_handle, NULL, value)) @@ -719,7 +770,7 @@ static void set_display(int value) return; } -static int read_display(void) +static int read_display(struct asus_laptop *asus) { unsigned long long value = 0; acpi_status rv = AE_OK; @@ -747,7 +798,9 @@ static int read_display(void) static ssize_t show_disp(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", read_display()); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", read_display(asus)); } /* @@ -760,18 +813,19 @@ static ssize_t show_disp(struct device *dev, static ssize_t store_disp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct asus_laptop *asus = dev_get_drvdata(dev); int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) - set_display(value); + set_display(asus, value); return rv; } /* * Light Sens */ -static void set_light_sens_switch(int value) +static void set_light_sens_switch(struct asus_laptop *asus, int value) { if (write_acpi_int(ls_switch_handle, NULL, value)) pr_warning("Error setting light sensor switch\n"); @@ -781,22 +835,25 @@ static void set_light_sens_switch(int value) static ssize_t show_lssw(struct device *dev, struct device_attribute *attr, char *buf) { + struct asus_laptop *asus = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", asus->light_switch); } static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct asus_laptop *asus = dev_get_drvdata(dev); int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) - set_light_sens_switch(value ? 1 : 0); + set_light_sens_switch(asus, value ? 1 : 0); return rv; } -static void set_light_sens_level(int value) +static void set_light_sens_level(struct asus_laptop *asus, int value) { if (write_acpi_int(ls_level_handle, NULL, value)) pr_warning("Error setting light sensor level\n"); @@ -806,19 +863,22 @@ static void set_light_sens_level(int value) static ssize_t show_lslvl(struct device *dev, struct device_attribute *attr, char *buf) { + struct asus_laptop *asus = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", asus->light_level); } static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct asus_laptop *asus = dev_get_drvdata(dev); int rv, value; rv = parse_arg(buf, count, &value); if (rv > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ - set_light_sens_level(value); + set_light_sens_level(asus, value); } return rv; @@ -830,34 +890,40 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, static ssize_t show_gps(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", read_status(GPS_ON)); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", read_status(asus, GPS_ON)); } static ssize_t store_gps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return store_status(buf, count, NULL, GPS_ON); + struct asus_laptop *asus = dev_get_drvdata(dev); + + return store_status(asus, buf, count, NULL, GPS_ON); } /* * Hotkey functions */ -static struct key_entry *asus_get_entry_by_scancode(int code) +static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus, + int code) { struct key_entry *key; - for (key = asus_keymap; key->type != KE_END; key++) + for (key = asus->keymap; key->type != KE_END; key++) if (code == key->code) return key; return NULL; } -static struct key_entry *asus_get_entry_by_keycode(int code) +static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus, + int code) { struct key_entry *key; - for (key = asus_keymap; key->type != KE_END; key++) + for (key = asus->keymap; key->type != KE_END; key++) if (code == key->keycode && key->type == KE_KEY) return key; @@ -866,7 +932,8 @@ static struct key_entry *asus_get_entry_by_keycode(int code) static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) { - struct key_entry *key = asus_get_entry_by_scancode(scancode); + struct asus_laptop *asus = input_get_drvdata(dev); + struct key_entry *key = asus_get_entry_by_scancode(asus, scancode); if (key && key->type == KE_KEY) { *keycode = key->keycode; @@ -878,18 +945,19 @@ static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) { + struct asus_laptop *asus = input_get_drvdata(dev); struct key_entry *key; int old_keycode; if (keycode < 0 || keycode > KEY_MAX) return -EINVAL; - key = asus_get_entry_by_scancode(scancode); + key = asus_get_entry_by_scancode(asus, scancode); if (key && key->type == KE_KEY) { old_keycode = key->keycode; key->keycode = keycode; set_bit(keycode, dev->keybit); - if (!asus_get_entry_by_keycode(old_keycode)) + if (!asus_get_entry_by_keycode(asus, old_keycode)) clear_bit(old_keycode, dev->keybit); return 0; } @@ -899,6 +967,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) static void asus_acpi_notify(struct acpi_device *device, u32 event) { + struct asus_laptop *asus = acpi_driver_data(device); static struct key_entry *key; u16 count; @@ -907,11 +976,11 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) * switched */ if (event == ATKD_LCD_ON) { - write_status(NULL, 1, LCD_ON); - lcd_blank(FB_BLANK_UNBLANK); + write_status(asus, NULL, 1, LCD_ON); + lcd_blank(asus, FB_BLANK_UNBLANK); } else if (event == ATKD_LCD_OFF) { - write_status(NULL, 0, LCD_ON); - lcd_blank(FB_BLANK_POWERDOWN); + write_status(asus, NULL, 0, LCD_ON); + lcd_blank(asus, FB_BLANK_POWERDOWN); } /* TODO Find a better way to handle events count. */ @@ -922,7 +991,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) count); if (asus->inputdev) { - key = asus_get_entry_by_scancode(event); + key = asus_get_entry_by_scancode(asus, event); if (!key) return ; @@ -978,13 +1047,14 @@ static struct attribute_group platform_attribute_group = { .attrs = asuspf_attributes }; -static int asus_platform_init(void) +static int asus_platform_init(struct asus_laptop *asus) { int result; asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); if (!asus->platform_device) return -ENOMEM; + platform_set_drvdata(asus->platform_device, asus); result = platform_device_add(asus->platform_device); if (result) @@ -1003,7 +1073,7 @@ fail_platform_device: return result; } -static void asus_platform_exit(void) +static void asus_platform_exit(struct asus_laptop *asus) { sysfs_remove_group(&asus->platform_device->dev.kobj, &platform_attribute_group); @@ -1012,12 +1082,12 @@ static void asus_platform_exit(void) static struct platform_driver platform_driver = { .driver = { - .name = ASUS_LAPTOP_FILE, - .owner = THIS_MODULE, - } + .name = ASUS_LAPTOP_FILE, + .owner = THIS_MODULE, + } }; -static void asus_laptop_add_fs(void) +static void asus_laptop_add_fs(struct asus_laptop *asus) { ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); @@ -1187,7 +1257,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) return AE_OK; } -static int asus_input_init(struct device *dev) +static int asus_input_init(struct asus_laptop *asus) { const struct key_entry *key; int result; @@ -1198,13 +1268,16 @@ static int asus_input_init(struct device *dev) return 0; } asus->inputdev->name = "Asus Laptop extra buttons"; - asus->inputdev->dev.parent = dev; + asus->inputdev->dev.parent = &asus->platform_device->dev; asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; asus->inputdev->id.bustype = BUS_HOST; asus->inputdev->getkeycode = asus_getkeycode; asus->inputdev->setkeycode = asus_setkeycode; + input_set_drvdata(asus->inputdev, asus); - for (key = asus_keymap; key->type != KE_END; key++) { + asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap), + GFP_KERNEL); + for (key = asus->keymap; key->type != KE_END; key++) { switch (key->type) { case KE_KEY: set_bit(EV_KEY, asus->inputdev->evbit); @@ -1220,40 +1293,44 @@ static int asus_input_init(struct device *dev) return result; } -static void asus_backlight_exit(void) +static void asus_backlight_exit(struct asus_laptop *asus) { if (asus->backlight_device) backlight_device_unregister(asus->backlight_device); } -#define ASUS_LED_UNREGISTER(object) \ +#define ASUS_LED_UNREGISTER(object) \ if (object##_led.dev) \ led_classdev_unregister(&object##_led) -static void asus_led_exit(void) +static void asus_led_exit(struct asus_laptop *asus) { - destroy_workqueue(led_workqueue); ASUS_LED_UNREGISTER(mled); ASUS_LED_UNREGISTER(tled); ASUS_LED_UNREGISTER(pled); ASUS_LED_UNREGISTER(rled); ASUS_LED_UNREGISTER(gled); ASUS_LED_UNREGISTER(kled); + if (asus->leds.workqueue) { + destroy_workqueue(asus->leds.workqueue); + asus->leds.workqueue = NULL; + } } -static void asus_input_exit(void) +static void asus_input_exit(struct asus_laptop *asus) { if (asus->inputdev) input_unregister_device(asus->inputdev); } -static int asus_backlight_init(struct device *dev) +static int asus_backlight_init(struct asus_laptop *asus) { struct backlight_device *bd; + struct device *dev = &asus->platform_device->dev; if (brightness_set_handle && lcd_switch_handle) { bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, - NULL, &asusbl_ops); + asus, &asusbl_ops); if (IS_ERR(bd)) { pr_err("Could not register asus backlight device\n"); asus->backlight_device = NULL; @@ -1270,79 +1347,55 @@ static int asus_backlight_init(struct device *dev) return 0; } -static int asus_led_register(acpi_handle handle, - struct led_classdev *ldev, struct device *dev) -{ - if (!handle) - return 0; - - return led_classdev_register(dev, ldev); -} - -#define ASUS_LED_REGISTER(object, device) \ - asus_led_register(object##_set_handle, &object##_led, device) - -static int asus_led_init(struct device *dev) +/* + * Ugly macro, need to fix that later + */ +#define ASUS_LED_REGISTER(asus, object, _name, max) \ + do { \ + struct led_classdev *ldev = &asus->leds.object; \ + if (!object##_set_handle) \ + break ; \ + \ + INIT_WORK(&asus->leds.object##_work, object##_led_update); \ + ldev->name = "asus::" _name; \ + ldev->brightness_set = object##_led_set; \ + ldev->max_brightness = max; \ + rv = led_classdev_register(&asus->platform_device->dev, ldev); \ + if (rv) \ + goto error; \ + } while (0) + +static int asus_led_init(struct asus_laptop *asus) { int rv; - rv = ASUS_LED_REGISTER(mled, dev); - if (rv) - goto out; - - rv = ASUS_LED_REGISTER(tled, dev); - if (rv) - goto out1; - - rv = ASUS_LED_REGISTER(rled, dev); - if (rv) - goto out2; - - rv = ASUS_LED_REGISTER(pled, dev); - if (rv) - goto out3; - - rv = ASUS_LED_REGISTER(gled, dev); - if (rv) - goto out4; - - if (kled_set_handle && kled_get_handle) - rv = ASUS_LED_REGISTER(kled, dev); - if (rv) - goto out5; - /* * Functions that actually update the LED's 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. */ - led_workqueue = create_singlethread_workqueue("led_workqueue"); - if (!led_workqueue) - goto out6; + asus->leds.workqueue = create_singlethread_workqueue("led_workqueue"); + if (!asus->leds.workqueue) + return -ENOMEM; - return 0; -out6: - rv = -ENOMEM; - ASUS_LED_UNREGISTER(kled); -out5: - ASUS_LED_UNREGISTER(gled); -out4: - ASUS_LED_UNREGISTER(pled); -out3: - ASUS_LED_UNREGISTER(rled); -out2: - ASUS_LED_UNREGISTER(tled); -out1: - ASUS_LED_UNREGISTER(mled); -out: + ASUS_LED_REGISTER(asus, mled, "mail", 1); + ASUS_LED_REGISTER(asus, tled, "touchpad", 1); + ASUS_LED_REGISTER(asus, rled, "record", 1); + ASUS_LED_REGISTER(asus, pled, "phone", 1); + ASUS_LED_REGISTER(asus, gled, "gaming", 1); + if (kled_set_handle && kled_get_handle) + ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3); +error: + if (rv) + asus_led_exit(asus); return rv; } static bool asus_device_present; -static int __devinit asus_acpi_init(struct acpi_device *device) +static int __devinit asus_acpi_init(struct asus_laptop *asus) { int result = 0; @@ -1358,22 +1411,22 @@ static int __devinit asus_acpi_init(struct acpi_device *device) if (result) return result; - asus_laptop_add_fs(); + asus_laptop_add_fs(asus); /* WLED and BLED are on by default */ - write_status(bt_switch_handle, 1, BT_ON); - write_status(wl_switch_handle, 1, WL_ON); + write_status(asus, bt_switch_handle, 1, BT_ON); + write_status(asus, wl_switch_handle, 1, WL_ON); /* If the h/w switch is off, we need to check the real status */ - write_status(NULL, read_status(BT_ON), BT_ON); - write_status(NULL, read_status(WL_ON), WL_ON); + write_status(asus, NULL, read_status(asus, BT_ON), BT_ON); + write_status(asus, NULL, read_status(asus, WL_ON), WL_ON); /* LCD Backlight is on by default */ - write_status(NULL, 1, LCD_ON); + write_status(asus, NULL, 1, LCD_ON); /* Keyboard Backlight is on by default */ if (kled_set_handle) - set_kled_lvl(1); + set_kled_lvl(asus, 1); /* LED display is off by default */ asus->ledd_status = 0xFFF; @@ -1383,18 +1436,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device) hotk->light_level = 5; /* level 5 for sensor sensitivity */ if (ls_switch_handle) - set_light_sens_switch(asus->light_switch); + set_light_sens_switch(asus, asus->light_switch); if (ls_level_handle) - set_light_sens_level(asus->light_level); + set_light_sens_level(asus, asus->light_level); /* GPS is on by default */ - write_status(NULL, 1, GPS_ON); + write_status(asus, NULL, 1, GPS_ON); return result; } static int __devinit asus_acpi_add(struct acpi_device *device) { + struct asus_laptop *asus; int result; pr_notice("Asus Laptop Support version %s\n", @@ -1408,7 +1462,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device) device->driver_data = asus; asus->device = device; - result = asus_acpi_init(device); + result = asus_acpi_init(asus); if (result) goto fail_platform; @@ -1416,22 +1470,22 @@ static int __devinit asus_acpi_add(struct acpi_device *device) * Register the platform device first. It is used as a parent for the * sub-devices below. */ - result = asus_platform_init(); + result = asus_platform_init(asus); if (result) goto fail_platform; if (!acpi_video_backlight_support()) { - result = asus_backlight_init(&asus->platform_device->dev); + result = asus_backlight_init(asus); if (result) goto fail_backlight; } else pr_info("Backlight controlled by ACPI video driver\n"); - result = asus_input_init(&asus->platform_device->dev); + result = asus_input_init(asus); if (result) goto fail_input; - result = asus_led_init(&asus->platform_device->dev); + result = asus_led_init(asus); if (result) goto fail_led; @@ -1439,11 +1493,11 @@ static int __devinit asus_acpi_add(struct acpi_device *device) return 0; fail_led: - asus_input_exit(); + asus_input_exit(asus); fail_input: - asus_backlight_exit(); + asus_backlight_exit(asus); fail_backlight: - asus_platform_exit(); + asus_platform_exit(asus); fail_platform: kfree(asus->name); kfree(asus); @@ -1453,10 +1507,12 @@ fail_platform: static int asus_acpi_remove(struct acpi_device *device, int type) { - asus_backlight_exit(); - asus_led_exit(); - asus_input_exit(); - asus_platform_exit(); + struct asus_laptop *asus = acpi_driver_data(device); + + asus_backlight_exit(asus); + asus_led_exit(asus); + asus_input_exit(asus); + asus_platform_exit(asus); kfree(asus->name); kfree(asus); -- cgit v1.2.3-70-g09d2 From be4ee82d3e44c5940a7f77cae5ed3e942e80a723 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 6 Dec 2009 16:27:09 +0100 Subject: asus-laptop: code movement The asus-laptop driver implements a number of interfaces like the backlight class driver. This change makes it easier to examine the implementation of one interface at at a time, without having to search through the file to find init() and exit() functions etc. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 440 +++++++++++++++++++------------------ 1 file changed, 223 insertions(+), 217 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 58a4864096d9..940ce3d63229 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -58,36 +58,6 @@ #define ASUS_LAPTOP_FILE KBUILD_MODNAME #define ASUS_LAPTOP_PREFIX "\\_SB.ATKD." - -/* - * Some events we use, same for all Asus - */ -#define ATKD_BR_UP 0x10 -#define ATKD_BR_DOWN 0x20 -#define ATKD_LCD_ON 0x33 -#define ATKD_LCD_OFF 0x34 - -/* - * Known bits returned by \_SB.ATKD.HWRS - */ -#define WL_HWRS 0x80 -#define BT_HWRS 0x100 - -/* - * Flags for hotk status - * WL_ON and BT_ON are also used for wireless_status() - */ -#define WL_ON 0x01 /* internal Wifi */ -#define BT_ON 0x02 /* internal Bluetooth */ -#define MLED_ON 0x04 /* mail LED */ -#define TLED_ON 0x08 /* touchpad LED */ -#define RLED_ON 0x10 /* Record LED */ -#define PLED_ON 0x20 /* Phone LED */ -#define GLED_ON 0x40 /* Gaming LED */ -#define LCD_ON 0x80 /* LCD backlight */ -#define GPS_ON 0x100 /* GPS */ -#define KEY_ON 0x200 /* Keyboard backlight */ - MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); MODULE_DESCRIPTION(ASUS_LAPTOP_NAME); MODULE_LICENSE("GPL"); @@ -119,6 +89,35 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " "(0 = disabled, 1 = enabled, -1 = don't do anything). " "default is 1"); +/* + * Some events we use, same for all Asus + */ +#define ATKD_BR_UP 0x10 +#define ATKD_BR_DOWN 0x20 +#define ATKD_LCD_ON 0x33 +#define ATKD_LCD_OFF 0x34 + +/* + * Known bits returned by \_SB.ATKD.HWRS + */ +#define WL_HWRS 0x80 +#define BT_HWRS 0x100 + +/* + * Flags for hotk status + * WL_ON and BT_ON are also used for wireless_status() + */ +#define WL_ON 0x01 /* internal Wifi */ +#define BT_ON 0x02 /* internal Bluetooth */ +#define MLED_ON 0x04 /* mail LED */ +#define TLED_ON 0x08 /* touchpad LED */ +#define RLED_ON 0x10 /* Record LED */ +#define PLED_ON 0x20 /* Phone LED */ +#define GLED_ON 0x40 /* Gaming LED */ +#define LCD_ON 0x80 /* LCD backlight */ +#define GPS_ON 0x100 /* GPS */ +#define KEY_ON 0x200 /* Keyboard backlight */ + #define ASUS_HANDLE(object, paths...) \ static acpi_handle object##_handle = NULL; \ static char *object##_paths[] = { paths } @@ -249,36 +248,6 @@ struct asus_laptop { u16 *keycode_map; }; -/* - * The backlight class declaration - */ -static int read_brightness(struct backlight_device *bd); -static int update_bl_status(struct backlight_device *bd); -static struct backlight_ops asusbl_ops = { - .get_brightness = read_brightness, - .update_status = update_bl_status, -}; - -#define ASUS_LED(object, ledname, max) \ - static void object##_led_set(struct led_classdev *led_cdev, \ - enum led_brightness value); \ - static enum led_brightness object##_led_get( \ - struct led_classdev *led_cdev); \ - static void object##_led_update(struct work_struct *ignored); \ - static struct led_classdev object##_led = { \ - .name = "asus::" ledname, \ - .brightness_set = object##_led_set, \ - .brightness_get = object##_led_get, \ - .max_brightness = max \ - } - -ASUS_LED(mled, "mail", 1); -ASUS_LED(tled, "touchpad", 1); -ASUS_LED(rled, "record", 1); -ASUS_LED(pled, "phone", 1); -ASUS_LED(gled, "gaming", 1); -ASUS_LED(kled, "kbd_backlight", 3); - struct key_entry { char type; u8 code; @@ -427,6 +396,29 @@ static void write_status(struct asus_laptop *asus, acpi_handle handle, pr_warning(" write failed %x\n", mask); } +/* + * LEDs + */ +#define ASUS_LED(object, ledname, max) \ + static void object##_led_set(struct led_classdev *led_cdev, \ + enum led_brightness value); \ + static enum led_brightness object##_led_get( \ + struct led_classdev *led_cdev); \ + static void object##_led_update(struct work_struct *ignored); \ + static struct led_classdev object##_led = { \ + .name = "asus::" ledname, \ + .brightness_set = object##_led_set, \ + .brightness_get = object##_led_get, \ + .max_brightness = max \ + } + +ASUS_LED(mled, "mail", 1); +ASUS_LED(tled, "touchpad", 1); +ASUS_LED(rled, "record", 1); +ASUS_LED(pled, "phone", 1); +ASUS_LED(gled, "gaming", 1); +ASUS_LED(kled, "kbd_backlight", 3); + /* /sys/class/led handlers */ #define ASUS_LED_HANDLER(object, mask) \ static void object##_led_set(struct led_classdev *led_cdev, \ @@ -459,7 +451,7 @@ ASUS_LED_HANDLER(tled, TLED_ON); ASUS_LED_HANDLER(gled, GLED_ON); /* - * Keyboard backlight + * Keyboard backlight (also a LED) */ static int get_kled_lvl(void) { @@ -516,6 +508,70 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev) return get_kled_lvl(); } +#define ASUS_LED_UNREGISTER(object) \ + if (object##_led.dev) \ + led_classdev_unregister(&object##_led) + +static void asus_led_exit(struct asus_laptop *asus) +{ + ASUS_LED_UNREGISTER(mled); + ASUS_LED_UNREGISTER(tled); + ASUS_LED_UNREGISTER(pled); + ASUS_LED_UNREGISTER(rled); + ASUS_LED_UNREGISTER(gled); + ASUS_LED_UNREGISTER(kled); + if (asus->leds.workqueue) { + destroy_workqueue(asus->leds.workqueue); + asus->leds.workqueue = NULL; + } +} + +/* Ugly macro, need to fix that later */ +#define ASUS_LED_REGISTER(asus, object, _name, max) \ + do { \ + struct led_classdev *ldev = &asus->leds.object; \ + if (!object##_set_handle) \ + break ; \ + \ + INIT_WORK(&asus->leds.object##_work, object##_led_update); \ + ldev->name = "asus::" _name; \ + ldev->brightness_set = object##_led_set; \ + ldev->max_brightness = max; \ + rv = led_classdev_register(&asus->platform_device->dev, ldev); \ + if (rv) \ + goto error; \ + } while (0) + +static int asus_led_init(struct asus_laptop *asus) +{ + int rv; + + /* + * Functions that actually update the LED's 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. + */ + asus->leds.workqueue = create_singlethread_workqueue("led_workqueue"); + if (!asus->leds.workqueue) + return -ENOMEM; + + ASUS_LED_REGISTER(asus, mled, "mail", 1); + ASUS_LED_REGISTER(asus, tled, "touchpad", 1); + ASUS_LED_REGISTER(asus, rled, "record", 1); + ASUS_LED_REGISTER(asus, pled, "phone", 1); + ASUS_LED_REGISTER(asus, gled, "gaming", 1); + if (kled_set_handle && kled_get_handle) + ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3); +error: + if (rv) + asus_led_exit(asus); + return rv; +} + +/* + * Backlight device + */ static int get_lcd_state(struct asus_laptop *asus) { return read_status(asus, LCD_ON); @@ -588,6 +644,41 @@ static int update_bl_status(struct backlight_device *bd) return set_lcd_state(asus, value); } +static struct backlight_ops asusbl_ops = { + .get_brightness = read_brightness, + .update_status = update_bl_status, +}; + +static int asus_backlight_init(struct asus_laptop *asus) +{ + struct backlight_device *bd; + struct device *dev = &asus->platform_device->dev; + + if (brightness_set_handle && lcd_switch_handle) { + bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, + asus, &asusbl_ops); + if (IS_ERR(bd)) { + pr_err("Could not register asus backlight device\n"); + asus->backlight_device = NULL; + return PTR_ERR(bd); + } + + asus->backlight_device = bd; + + bd->props.max_brightness = 15; + bd->props.brightness = read_brightness(NULL); + bd->props.power = FB_BLANK_UNBLANK; + backlight_update_status(bd); + } + return 0; +} + +static void asus_backlight_exit(struct asus_laptop *asus) +{ + if (asus->backlight_device) + backlight_device_unregister(asus->backlight_device); +} + /* * Platform device handlers */ @@ -904,7 +995,7 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, } /* - * Hotkey functions + * Input device (i.e. hotkeys) */ static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus, int code) @@ -965,10 +1056,72 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) return -EINVAL; } +static void asus_input_notify(struct asus_laptop *asus, int event) +{ + struct key_entry *key; + + key = asus_get_entry_by_scancode(asus, event); + if (!key) + return ; + + switch (key->type) { + case KE_KEY: + input_report_key(asus->inputdev, key->keycode, 1); + input_sync(asus->inputdev); + input_report_key(asus->inputdev, key->keycode, 0); + input_sync(asus->inputdev); + break; + } +} + +static int asus_input_init(struct asus_laptop *asus) +{ + const struct key_entry *key; + int result; + + asus->inputdev = input_allocate_device(); + if (!asus->inputdev) { + pr_info("Unable to allocate input device\n"); + return 0; + } + asus->inputdev->name = "Asus Laptop extra buttons"; + asus->inputdev->dev.parent = &asus->platform_device->dev; + asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; + asus->inputdev->id.bustype = BUS_HOST; + asus->inputdev->getkeycode = asus_getkeycode; + asus->inputdev->setkeycode = asus_setkeycode; + input_set_drvdata(asus->inputdev, asus); + + asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap), + GFP_KERNEL); + for (key = asus->keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, asus->inputdev->evbit); + set_bit(key->keycode, asus->inputdev->keybit); + break; + } + } + result = input_register_device(asus->inputdev); + if (result) { + pr_info("Unable to register input device\n"); + input_free_device(asus->inputdev); + } + return result; +} + +static void asus_input_exit(struct asus_laptop *asus) +{ + if (asus->inputdev) + input_unregister_device(asus->inputdev); +} + +/* + * ACPI driver + */ static void asus_acpi_notify(struct acpi_device *device, u32 event) { struct asus_laptop *asus = acpi_driver_data(device); - static struct key_entry *key; u16 count; /* @@ -990,20 +1143,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) dev_name(&asus->device->dev), event, count); - if (asus->inputdev) { - key = asus_get_entry_by_scancode(asus, event); - if (!key) - return ; - - switch (key->type) { - case KE_KEY: - input_report_key(asus->inputdev, key->keycode, 1); - input_sync(asus->inputdev); - input_report_key(asus->inputdev, key->keycode, 0); - input_sync(asus->inputdev); - break; - } - } + asus_input_notify(asus, event); } #define ASUS_CREATE_DEVICE_ATTR(_name) \ @@ -1257,142 +1397,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus) return AE_OK; } -static int asus_input_init(struct asus_laptop *asus) -{ - const struct key_entry *key; - int result; - - asus->inputdev = input_allocate_device(); - if (!asus->inputdev) { - pr_info("Unable to allocate input device\n"); - return 0; - } - asus->inputdev->name = "Asus Laptop extra buttons"; - asus->inputdev->dev.parent = &asus->platform_device->dev; - asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; - asus->inputdev->id.bustype = BUS_HOST; - asus->inputdev->getkeycode = asus_getkeycode; - asus->inputdev->setkeycode = asus_setkeycode; - input_set_drvdata(asus->inputdev, asus); - - asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap), - GFP_KERNEL); - for (key = asus->keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, asus->inputdev->evbit); - set_bit(key->keycode, asus->inputdev->keybit); - break; - } - } - result = input_register_device(asus->inputdev); - if (result) { - pr_info("Unable to register input device\n"); - input_free_device(asus->inputdev); - } - return result; -} - -static void asus_backlight_exit(struct asus_laptop *asus) -{ - if (asus->backlight_device) - backlight_device_unregister(asus->backlight_device); -} - -#define ASUS_LED_UNREGISTER(object) \ - if (object##_led.dev) \ - led_classdev_unregister(&object##_led) - -static void asus_led_exit(struct asus_laptop *asus) -{ - ASUS_LED_UNREGISTER(mled); - ASUS_LED_UNREGISTER(tled); - ASUS_LED_UNREGISTER(pled); - ASUS_LED_UNREGISTER(rled); - ASUS_LED_UNREGISTER(gled); - ASUS_LED_UNREGISTER(kled); - if (asus->leds.workqueue) { - destroy_workqueue(asus->leds.workqueue); - asus->leds.workqueue = NULL; - } -} - -static void asus_input_exit(struct asus_laptop *asus) -{ - if (asus->inputdev) - input_unregister_device(asus->inputdev); -} - -static int asus_backlight_init(struct asus_laptop *asus) -{ - struct backlight_device *bd; - struct device *dev = &asus->platform_device->dev; - - if (brightness_set_handle && lcd_switch_handle) { - bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, - asus, &asusbl_ops); - if (IS_ERR(bd)) { - pr_err("Could not register asus backlight device\n"); - asus->backlight_device = NULL; - return PTR_ERR(bd); - } - - asus->backlight_device = bd; - - bd->props.max_brightness = 15; - bd->props.brightness = read_brightness(NULL); - bd->props.power = FB_BLANK_UNBLANK; - backlight_update_status(bd); - } - return 0; -} - -/* - * Ugly macro, need to fix that later - */ -#define ASUS_LED_REGISTER(asus, object, _name, max) \ - do { \ - struct led_classdev *ldev = &asus->leds.object; \ - if (!object##_set_handle) \ - break ; \ - \ - INIT_WORK(&asus->leds.object##_work, object##_led_update); \ - ldev->name = "asus::" _name; \ - ldev->brightness_set = object##_led_set; \ - ldev->max_brightness = max; \ - rv = led_classdev_register(&asus->platform_device->dev, ldev); \ - if (rv) \ - goto error; \ - } while (0) - -static int asus_led_init(struct asus_laptop *asus) -{ - int rv; - - /* - * Functions that actually update the LED's 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. - */ - asus->leds.workqueue = create_singlethread_workqueue("led_workqueue"); - if (!asus->leds.workqueue) - return -ENOMEM; - - ASUS_LED_REGISTER(asus, mled, "mail", 1); - ASUS_LED_REGISTER(asus, tled, "touchpad", 1); - ASUS_LED_REGISTER(asus, rled, "record", 1); - ASUS_LED_REGISTER(asus, pled, "phone", 1); - ASUS_LED_REGISTER(asus, gled, "gaming", 1); - if (kled_set_handle && kled_get_handle) - ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3); -error: - if (rv) - asus_led_exit(asus); - return rv; -} - - static bool asus_device_present; static int __devinit asus_acpi_init(struct asus_laptop *asus) @@ -1414,8 +1418,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) asus_laptop_add_fs(asus); /* WLED and BLED are on by default */ - write_status(asus, bt_switch_handle, 1, BT_ON); - write_status(asus, wl_switch_handle, 1, WL_ON); + if (bluetooth_status >= 0) + write_status(asus, bt_switch_handle, !!bluetooth_status, BT_ON); + if (wireless_status >= 0) + write_status(asus, wl_switch_handle, !!wireless_status, WL_ON); /* If the h/w switch is off, we need to check the real status */ write_status(asus, NULL, read_status(asus, BT_ON), BT_ON); @@ -1432,8 +1438,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) asus->ledd_status = 0xFFF; /* Set initial values of light sensor and level */ - hotk->light_switch = 0; /* Default to light sensor disabled */ - hotk->light_level = 5; /* level 5 for sensor sensitivity */ + asus->light_switch = 0; /* Default to light sensor disabled */ + asus->light_level = 5; /* level 5 for sensor sensitivity */ if (ls_switch_handle) set_light_sens_switch(asus, asus->light_switch); -- cgit v1.2.3-70-g09d2 From aa9df930d6eabbd8f2439eca6b2f77f81ce425f2 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 13 Jan 2010 21:49:10 +0100 Subject: asus-laptop: stop using read_status for bluetooth and wlan Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 55 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 940ce3d63229..cee751e301a6 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -239,6 +239,9 @@ struct asus_laptop { struct asus_laptop_leds leds; + int wireless_status; + bool have_rsts; + acpi_handle handle; /* the handle of the hotk device */ char status; /* status of the hotk, for LEDs, ... */ u32 ledd_status; /* status of the LED display */ @@ -328,23 +331,6 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) return write_acpi_int_ret(handle, method, val, NULL); } -static int read_wireless_status(struct asus_laptop *asus, int mask) -{ - unsigned long long status; - acpi_status rv = AE_OK; - - if (!wireless_status_handle) - return (asus->status & mask) ? 1 : 0; - - rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); - if (ACPI_FAILURE(rv)) - pr_warning("Error reading Wireless status\n"); - else - return (status & mask) ? 1 : 0; - - return (asus->status & mask) ? 1 : 0; -} - static int read_gps_status(struct asus_laptop *asus) { unsigned long long status; @@ -362,10 +348,7 @@ static int read_gps_status(struct asus_laptop *asus) /* Generic LED functions */ static int read_status(struct asus_laptop *asus, int mask) { - /* There is a special method for both wireless devices */ - if (mask == BT_ON || mask == WL_ON) - return read_wireless_status(asus, mask); - else if (mask == GPS_ON) + if (mask == GPS_ON) return read_gps_status(asus); return (asus->status & mask) ? 1 : 0; @@ -811,6 +794,25 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, return rv; } +/* + * Wireless + */ +static int asus_wireless_status(struct asus_laptop *asus, int mask) +{ + unsigned long long status; + acpi_status rv = AE_OK; + + if (!asus->have_rsts) + return (asus->wireless_status & mask) ? 1 : 0; + + rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); + if (ACPI_FAILURE(rv)) { + pr_warning("Error reading Wireless status\n"); + return -EINVAL; + } + return !!(status & mask); +} + /* * WLAN */ @@ -819,7 +821,7 @@ static ssize_t show_wlan(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", read_status(asus, WL_ON)); + return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_ON)); } static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, @@ -838,7 +840,7 @@ static ssize_t show_bluetooth(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", read_status(asus, BT_ON)); + return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_ON)); } static ssize_t store_bluetooth(struct device *dev, @@ -1371,7 +1373,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus) if (hwrs_result & BT_HWRS) ASUS_HANDLE_INIT(bt_switch); - ASUS_HANDLE_INIT(wireless_status); + if (!ASUS_HANDLE_INIT(wireless_status)) + asus->have_rsts = true; ASUS_HANDLE_INIT(brightness_set); ASUS_HANDLE_INIT(brightness_get); @@ -1424,8 +1427,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) write_status(asus, wl_switch_handle, !!wireless_status, WL_ON); /* If the h/w switch is off, we need to check the real status */ - write_status(asus, NULL, read_status(asus, BT_ON), BT_ON); - write_status(asus, NULL, read_status(asus, WL_ON), WL_ON); + write_status(asus, NULL, asus_wireless_status(asus, BT_ON), BT_ON); + write_status(asus, NULL, asus_wireless_status(asus, WL_ON), WL_ON); /* LCD Backlight is on by default */ write_status(asus, NULL, 1, LCD_ON); -- cgit v1.2.3-70-g09d2 From 6358bf2c4c309efc7c3cbc36466c32108c12c456 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 13 Jan 2010 21:55:44 +0100 Subject: asus-laptop: stop using read_status and store_status for GPS Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 56 ++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 21 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index cee751e301a6..ea51d7e4df21 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -331,26 +331,9 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) return write_acpi_int_ret(handle, method, val, NULL); } -static int read_gps_status(struct asus_laptop *asus) -{ - unsigned long long status; - acpi_status rv = AE_OK; - - rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); - if (ACPI_FAILURE(rv)) - pr_warning("Error reading GPS status\n"); - else - return status ? 1 : 0; - - return (asus->status & GPS_ON) ? 1 : 0; -} - /* Generic LED functions */ static int read_status(struct asus_laptop *asus, int mask) { - if (mask == GPS_ON) - return read_gps_status(asus); - return (asus->status & mask) ? 1 : 0; } @@ -979,21 +962,52 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, /* * GPS + * TODO: use rfkill */ +static int asus_gps_status(struct asus_laptop *asus) +{ + unsigned long long status; + acpi_status rv = AE_OK; + + rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); + if (ACPI_FAILURE(rv)) { + pr_warning("Error reading GPS status\n"); + return -ENODEV; + } + return !!status; +} + +static int asus_gps_switch(struct asus_laptop *asus, int status) +{ + acpi_handle handle = status ? gps_on_handle : gps_off_handle; + + if (write_acpi_int(handle, NULL, 0x02)) + return -ENODEV; + return 0; +} + static ssize_t show_gps(struct device *dev, struct device_attribute *attr, char *buf) { struct asus_laptop *asus = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", read_status(asus, GPS_ON)); + return sprintf(buf, "%d\n", asus_gps_status(asus)); } static ssize_t store_gps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct asus_laptop *asus = dev_get_drvdata(dev); + struct asus_laptop *asus = dev_get_drvdata(dev); + int rv, value; + int ret; - return store_status(asus, buf, count, NULL, GPS_ON); + rv = parse_arg(buf, count, &value); + if (rv <= 0) + return -EINVAL; + ret = asus_gps_switch(asus, !!value); + if (ret) + return ret; + return rv; } /* @@ -1451,7 +1465,7 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) set_light_sens_level(asus, asus->light_level); /* GPS is on by default */ - write_status(asus, NULL, 1, GPS_ON); + asus_gps_switch(asus, 1); return result; } -- cgit v1.2.3-70-g09d2 From 3e68ae7c2a9076a694e46f49ec26323a7757eaad Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 13 Jan 2010 22:10:39 +0100 Subject: asus-laptop: stop using read_status for lcd (anyway lcd code is scheduled for removal) Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ea51d7e4df21..d726db380e47 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -241,6 +241,7 @@ struct asus_laptop { int wireless_status; bool have_rsts; + int lcd_state; acpi_handle handle; /* the handle of the hotk device */ char status; /* status of the hotk, for LEDs, ... */ @@ -538,30 +539,33 @@ error: /* * Backlight device */ -static int get_lcd_state(struct asus_laptop *asus) +static int asus_lcd_status(struct asus_laptop *asus) { - return read_status(asus, LCD_ON); + return asus->lcd_state; } -static int set_lcd_state(struct asus_laptop *asus, int value) +static int asus_lcd_set(struct asus_laptop *asus, int value) { int lcd = 0; acpi_status status = 0; - lcd = value ? 1 : 0; + lcd = !!value; - if (lcd == get_lcd_state(asus)) + if (lcd == asus_lcd_status(asus)) return 0; - if (lcd_switch_handle) { - status = acpi_evaluate_object(lcd_switch_handle, - NULL, NULL, NULL); + if (!lcd_switch_handle) + return -ENODEV; + + status = acpi_evaluate_object(lcd_switch_handle, + NULL, NULL, NULL); - if (ACPI_FAILURE(status)) - pr_warning("Error switching LCD\n"); + if (ACPI_FAILURE(status)) { + pr_warning("Error switching LCD\n"); + return -ENODEV; } - write_status(asus, NULL, lcd, LCD_ON); + asus->lcd_state = lcd; return 0; } @@ -569,6 +573,8 @@ static void lcd_blank(struct asus_laptop *asus, int blank) { struct backlight_device *bd = asus->backlight_device; + asus->lcd_state = (blank == FB_BLANK_UNBLANK); + if (bd) { bd->props.power = blank; backlight_update_status(bd); @@ -607,7 +613,7 @@ static int update_bl_status(struct backlight_device *bd) return rv; value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; - return set_lcd_state(asus, value); + return asus_lcd_set(asus, value); } static struct backlight_ops asusbl_ops = { @@ -1144,13 +1150,10 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) * We need to tell the backlight device when the backlight power is * switched */ - if (event == ATKD_LCD_ON) { - write_status(asus, NULL, 1, LCD_ON); + if (event == ATKD_LCD_ON) lcd_blank(asus, FB_BLANK_UNBLANK); - } else if (event == ATKD_LCD_OFF) { - write_status(asus, NULL, 0, LCD_ON); + else if (event == ATKD_LCD_OFF) lcd_blank(asus, FB_BLANK_POWERDOWN); - } /* TODO Find a better way to handle events count. */ count = asus->event_count[event % 128]++; -- cgit v1.2.3-70-g09d2 From 17e78f6260fbc8f55c279cca081c26c88d96ec00 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 13 Jan 2010 22:21:33 +0100 Subject: asus-laptop: removing read_status/store_status/write_status and asus->status Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 81 +++++++++++--------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index d726db380e47..2349e88bbc75 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -107,16 +107,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " * Flags for hotk status * WL_ON and BT_ON are also used for wireless_status() */ -#define WL_ON 0x01 /* internal Wifi */ -#define BT_ON 0x02 /* internal Bluetooth */ -#define MLED_ON 0x04 /* mail LED */ -#define TLED_ON 0x08 /* touchpad LED */ -#define RLED_ON 0x10 /* Record LED */ -#define PLED_ON 0x20 /* Phone LED */ -#define GLED_ON 0x40 /* Gaming LED */ -#define LCD_ON 0x80 /* LCD backlight */ -#define GPS_ON 0x100 /* GPS */ -#define KEY_ON 0x200 /* Keyboard backlight */ +#define WL_RSTS 0x01 /* internal Wifi */ +#define BT_RSTS 0x02 /* internal Bluetooth */ #define ASUS_HANDLE(object, paths...) \ static acpi_handle object##_handle = NULL; \ @@ -244,7 +236,6 @@ struct asus_laptop { int lcd_state; acpi_handle handle; /* the handle of the hotk device */ - char status; /* status of the hotk, for LEDs, ... */ u32 ledd_status; /* status of the LED display */ u8 light_level; /* light sensor level */ u8 light_switch; /* light sensor switch value */ @@ -332,35 +323,18 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) return write_acpi_int_ret(handle, method, val, NULL); } -/* Generic LED functions */ -static int read_status(struct asus_laptop *asus, int mask) +/* Generic LED function */ +static void asus_led_set(struct asus_laptop *asus, acpi_handle handle, + int value) { - return (asus->status & mask) ? 1 : 0; -} - -static void write_status(struct asus_laptop *asus, acpi_handle handle, - int out, int mask) -{ - asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); - - switch (mask) { - case MLED_ON: - out = !(out & 0x1); - break; - case GLED_ON: - out = (out & 0x1) + 1; - break; - case GPS_ON: - handle = (out) ? gps_on_handle : gps_off_handle; - out = 0x02; - break; - default: - out &= 0x1; - break; - } + if (handle == mled_set_handle) + value = !value; + else if (handle == gled_set_handle) + value = !value + 1; + else + value = !!value; - if (write_acpi_int(handle, NULL, out)) - pr_warning(" write failed %x\n", mask); + write_acpi_int(handle, NULL, value); } /* @@ -403,7 +377,7 @@ ASUS_LED(kled, "kbd_backlight", 3); struct asus_laptop *asus = work_to_asus(work, object); \ \ int value = asus->leds.object##_wk; \ - write_status(asus, object##_set_handle, value, (mask)); \ + asus_led_set(asus, object##_set_handle, value); \ } \ static enum led_brightness object##_led_get( \ struct led_classdev *led_cdev) \ @@ -740,9 +714,9 @@ static int parse_arg(const char *buf, unsigned long count, int *val) return count; } -static ssize_t store_status(struct asus_laptop *asus, - const char *buf, size_t count, - acpi_handle handle, int mask) +static ssize_t sysfs_acpi_set(struct asus_laptop *asus, + const char *buf, size_t count, + acpi_handle handle) { int rv, value; int out = 0; @@ -751,8 +725,8 @@ static ssize_t store_status(struct asus_laptop *asus, if (rv > 0) out = value ? 1 : 0; - write_status(asus, handle, out, mask); - + if (write_acpi_int(handle, NULL, value)) + return -ENODEV; return rv; } @@ -810,7 +784,7 @@ static ssize_t show_wlan(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_ON)); + return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_RSTS)); } static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, @@ -818,7 +792,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, { struct asus_laptop *asus = dev_get_drvdata(dev); - return store_status(asus, buf, count, wl_switch_handle, WL_ON); + return sysfs_acpi_set(asus, buf, count, wl_switch_handle); } /* @@ -829,7 +803,7 @@ static ssize_t show_bluetooth(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_ON)); + return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_RSTS)); } static ssize_t store_bluetooth(struct device *dev, @@ -838,7 +812,7 @@ static ssize_t store_bluetooth(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return store_status(asus, buf, count, bt_switch_handle, BT_ON); + return sysfs_acpi_set(asus, buf, count, bt_switch_handle); } /* @@ -1439,16 +1413,9 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) /* WLED and BLED are on by default */ if (bluetooth_status >= 0) - write_status(asus, bt_switch_handle, !!bluetooth_status, BT_ON); + write_acpi_int(bt_switch_handle, NULL, !!bluetooth_status); if (wireless_status >= 0) - write_status(asus, wl_switch_handle, !!wireless_status, WL_ON); - - /* If the h/w switch is off, we need to check the real status */ - write_status(asus, NULL, asus_wireless_status(asus, BT_ON), BT_ON); - write_status(asus, NULL, asus_wireless_status(asus, WL_ON), WL_ON); - - /* LCD Backlight is on by default */ - write_status(asus, NULL, 1, LCD_ON); + write_acpi_int(wl_switch_handle, NULL, !!wireless_status); /* Keyboard Backlight is on by default */ if (kled_set_handle) -- cgit v1.2.3-70-g09d2 From 4d4415138060870670a18d0768fe1d597f505f98 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 13 Jan 2010 22:26:24 +0100 Subject: asus-laptop: rename function talking directly to acpi with asus_xxx scheme Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 2349e88bbc75..ae4f80886577 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -394,7 +394,7 @@ ASUS_LED_HANDLER(gled, GLED_ON); /* * Keyboard backlight (also a LED) */ -static int get_kled_lvl(void) +static int asus_kled_lvl(void) { unsigned long long kblv; struct acpi_object_list params; @@ -409,12 +409,12 @@ static int get_kled_lvl(void) rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); if (ACPI_FAILURE(rv)) { pr_warning("Error reading kled level\n"); - return 0; + return -ENODEV; } return kblv; } -static int set_kled_lvl(struct asus_laptop *asus, int kblv) +static int asus_kled_set(struct asus_laptop *asus, int kblv) { if (kblv > 0) kblv = (1 << 7) | (kblv & 0x7F); @@ -441,12 +441,12 @@ static void kled_led_update(struct work_struct *work) { struct asus_laptop *asus = work_to_asus(work, kled); - set_kled_lvl(asus, asus->leds.kled_wk); + asus_kled_set(asus, asus->leds.kled_wk); } static enum led_brightness kled_led_get(struct led_classdev *led_cdev) { - return get_kled_lvl(); + return asus_kled_lvl(); } #define ASUS_LED_UNREGISTER(object) \ @@ -555,7 +555,7 @@ static void lcd_blank(struct asus_laptop *asus, int blank) } } -static int read_brightness(struct backlight_device *bd) +static int asus_read_brightness(struct backlight_device *bd) { unsigned long long value; acpi_status rv = AE_OK; @@ -567,7 +567,7 @@ static int read_brightness(struct backlight_device *bd) return value; } -static int set_brightness(struct backlight_device *bd, int value) +static int asus_set_brightness(struct backlight_device *bd, int value) { if (write_acpi_int(brightness_set_handle, NULL, value)) { pr_warning("Error changing brightness\n"); @@ -582,7 +582,7 @@ static int update_bl_status(struct backlight_device *bd) int rv; int value = bd->props.brightness; - rv = set_brightness(bd, value); + rv = asus_set_brightness(bd, value); if (rv) return rv; @@ -591,7 +591,7 @@ static int update_bl_status(struct backlight_device *bd) } static struct backlight_ops asusbl_ops = { - .get_brightness = read_brightness, + .get_brightness = asus_read_brightness, .update_status = update_bl_status, }; @@ -612,7 +612,7 @@ static int asus_backlight_init(struct asus_laptop *asus) asus->backlight_device = bd; bd->props.max_brightness = 15; - bd->props.brightness = read_brightness(NULL); + bd->props.brightness = asus_read_brightness(NULL); bd->props.power = FB_BLANK_UNBLANK; backlight_update_status(bd); } @@ -818,7 +818,7 @@ static ssize_t store_bluetooth(struct device *dev, /* * Display */ -static void set_display(struct asus_laptop *asus, int value) +static void asus_set_display(struct asus_laptop *asus, int value) { /* no sanity check needed for now */ if (write_acpi_int(display_set_handle, NULL, value)) @@ -874,14 +874,14 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) - set_display(asus, value); + asus_set_display(asus, value); return rv; } /* * Light Sens */ -static void set_light_sens_switch(struct asus_laptop *asus, int value) +static void asus_als_switch(struct asus_laptop *asus, int value) { if (write_acpi_int(ls_switch_handle, NULL, value)) pr_warning("Error setting light sensor switch\n"); @@ -904,12 +904,12 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) - set_light_sens_switch(asus, value ? 1 : 0); + asus_als_switch(asus, value ? 1 : 0); return rv; } -static void set_light_sens_level(struct asus_laptop *asus, int value) +static void asus_als_level(struct asus_laptop *asus, int value) { if (write_acpi_int(ls_level_handle, NULL, value)) pr_warning("Error setting light sensor level\n"); @@ -934,7 +934,7 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, if (rv > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ - set_light_sens_level(asus, value); + asus_als_level(asus, value); } return rv; @@ -1419,7 +1419,7 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) /* Keyboard Backlight is on by default */ if (kled_set_handle) - set_kled_lvl(asus, 1); + asus_kled_set(asus, 1); /* LED display is off by default */ asus->ledd_status = 0xFFF; @@ -1429,10 +1429,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) asus->light_level = 5; /* level 5 for sensor sensitivity */ if (ls_switch_handle) - set_light_sens_switch(asus, asus->light_switch); + asus_als_switch(asus, asus->light_switch); if (ls_level_handle) - set_light_sens_level(asus, asus->light_level); + asus_als_level(asus, asus->light_level); /* GPS is on by default */ asus_gps_switch(asus, 1); -- cgit v1.2.3-70-g09d2 From d99b577c729c4a29679fb1f605f9ccace154e0e5 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Fri, 22 Jan 2010 21:20:57 +0100 Subject: asus-laptop: stop using ASUS_HANDLE and use relative methods instead Stop using ASUS_HANDLE because most of the time it is not needed. This macro was introduced to display_get and lcd_switch which are not part of the interface provided by Asus, and are scheduled for removal. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 240 ++++++++++++++++++++----------------- 1 file changed, 129 insertions(+), 111 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ae4f80886577..671fad96c275 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -115,27 +115,27 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " static char *object##_paths[] = { paths } /* LED */ -ASUS_HANDLE(mled_set, ASUS_LAPTOP_PREFIX "MLED"); -ASUS_HANDLE(tled_set, ASUS_LAPTOP_PREFIX "TLED"); -ASUS_HANDLE(rled_set, ASUS_LAPTOP_PREFIX "RLED"); /* W1JC */ -ASUS_HANDLE(pled_set, ASUS_LAPTOP_PREFIX "PLED"); /* A7J */ -ASUS_HANDLE(gled_set, ASUS_LAPTOP_PREFIX "GLED"); /* G1, G2 (probably) */ +#define METHOD_MLED "MLED" +#define METHOD_TLED "TLED" +#define METHOD_RLED "RLED" /* W1JC */ +#define METHOD_PLED "PLED" /* A7J */ +#define METHOD_GLED "GLED" /* G1, G2 (probably) */ /* LEDD */ -ASUS_HANDLE(ledd_set, ASUS_LAPTOP_PREFIX "SLCM"); +#define METHOD_LEDD "SLCM" /* * Bluetooth and WLAN * WLED and BLED are not handled like other XLED, because in some dsdt * they also control the WLAN/Bluetooth device. */ -ASUS_HANDLE(wl_switch, ASUS_LAPTOP_PREFIX "WLED"); -ASUS_HANDLE(bt_switch, ASUS_LAPTOP_PREFIX "BLED"); -ASUS_HANDLE(wireless_status, ASUS_LAPTOP_PREFIX "RSTS"); /* All new models */ +#define METHOD_WLAN "WLED" +#define METHOD_BLUETOOTH "BLED" +#define METHOD_WL_STATUS "RSTS" /* Brightness */ -ASUS_HANDLE(brightness_set, ASUS_LAPTOP_PREFIX "SPLV"); -ASUS_HANDLE(brightness_get, ASUS_LAPTOP_PREFIX "GPLV"); +#define METHOD_BRIGHTNESS_SET "SPLV" +#define METHOD_BRIGHTNESS_GET "GPLV" /* Backlight */ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ @@ -148,7 +148,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ "\\Q10"); /* A2x, L2D, L3D, M2E */ /* Display */ -ASUS_HANDLE(display_set, ASUS_LAPTOP_PREFIX "SDSP"); +#define METHOD_SWITCH_DISPLAY "SDSP" ASUS_HANDLE(display_get, /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ "\\_SB.PCI0.P0P1.VGA.GETD", @@ -173,18 +173,18 @@ ASUS_HANDLE(display_get, /* A3F A6F A3N A3L M6N W3N W6A */ "\\SSTE"); -ASUS_HANDLE(ls_switch, ASUS_LAPTOP_PREFIX "ALSC"); /* Z71A Z71V */ -ASUS_HANDLE(ls_level, ASUS_LAPTOP_PREFIX "ALSL"); /* Z71A Z71V */ +#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */ +#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */ /* GPS */ /* R2H use different handle for GPS on/off */ -ASUS_HANDLE(gps_on, ASUS_LAPTOP_PREFIX "SDON"); /* R2H */ -ASUS_HANDLE(gps_off, ASUS_LAPTOP_PREFIX "SDOF"); /* R2H */ -ASUS_HANDLE(gps_status, ASUS_LAPTOP_PREFIX "GPST"); +#define METHOD_GPS_ON "SDON" +#define METHOD_GPS_OFF "SDOF" +#define METHOD_GPS_STATUS "GPST" /* Keyboard light */ -ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB"); -ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); +#define METHOD_KBD_LIGHT_SET "SLKB" +#define METHOD_KBD_LIGHT_GET "GLKB" /* * Define a specific led structure to keep the main structure clean @@ -323,18 +323,44 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) return write_acpi_int_ret(handle, method, val, NULL); } +static int acpi_check_handle(acpi_handle handle, const char *method, + acpi_handle *ret) +{ + acpi_status status; + + if (method == NULL) + return -ENODEV; + + if (ret) + status = acpi_get_handle(handle, (char *)method, + ret); + else { + acpi_handle dummy; + + status = acpi_get_handle(handle, (char *)method, + &dummy); + } + + if (status != AE_OK) { + if (ret) + pr_warning("Error finding %s\n", method); + return -ENODEV; + } + return 0; +} + /* Generic LED function */ -static void asus_led_set(struct asus_laptop *asus, acpi_handle handle, +static void asus_led_set(struct asus_laptop *asus, char *method, int value) { - if (handle == mled_set_handle) + if (!strcmp(method, METHOD_MLED)) value = !value; - else if (handle == gled_set_handle) + else if (!strcmp(method, METHOD_GLED)) value = !value + 1; else value = !!value; - write_acpi_int(handle, NULL, value); + write_acpi_int(asus->handle, method, value); } /* @@ -361,7 +387,7 @@ ASUS_LED(gled, "gaming", 1); ASUS_LED(kled, "kbd_backlight", 3); /* /sys/class/led handlers */ -#define ASUS_LED_HANDLER(object, mask) \ +#define ASUS_LED_HANDLER(object, method) \ static void object##_led_set(struct led_classdev *led_cdev, \ enum led_brightness value) \ { \ @@ -377,7 +403,7 @@ ASUS_LED(kled, "kbd_backlight", 3); struct asus_laptop *asus = work_to_asus(work, object); \ \ int value = asus->leds.object##_wk; \ - asus_led_set(asus, object##_set_handle, value); \ + asus_led_set(asus, method, value); \ } \ static enum led_brightness object##_led_get( \ struct led_classdev *led_cdev) \ @@ -385,16 +411,16 @@ ASUS_LED(kled, "kbd_backlight", 3); return led_cdev->brightness; \ } -ASUS_LED_HANDLER(mled, MLED_ON); -ASUS_LED_HANDLER(pled, PLED_ON); -ASUS_LED_HANDLER(rled, RLED_ON); -ASUS_LED_HANDLER(tled, TLED_ON); -ASUS_LED_HANDLER(gled, GLED_ON); +ASUS_LED_HANDLER(mled, METHOD_MLED); +ASUS_LED_HANDLER(pled, METHOD_PLED); +ASUS_LED_HANDLER(rled, METHOD_RLED); +ASUS_LED_HANDLER(tled, METHOD_TLED); +ASUS_LED_HANDLER(gled, METHOD_GLED); /* * Keyboard backlight (also a LED) */ -static int asus_kled_lvl(void) +static int asus_kled_lvl(struct asus_laptop *asus) { unsigned long long kblv; struct acpi_object_list params; @@ -406,7 +432,8 @@ static int asus_kled_lvl(void) in_obj.type = ACPI_TYPE_INTEGER; in_obj.integer.value = 2; - rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); + rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET, + ¶ms, &kblv); if (ACPI_FAILURE(rv)) { pr_warning("Error reading kled level\n"); return -ENODEV; @@ -421,7 +448,7 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv) else kblv = 0; - if (write_acpi_int(kled_set_handle, NULL, kblv)) { + if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) { pr_warning("Keyboard LED display write failed\n"); return -EINVAL; } @@ -446,7 +473,9 @@ static void kled_led_update(struct work_struct *work) static enum led_brightness kled_led_get(struct led_classdev *led_cdev) { - return asus_kled_lvl(); + struct asus_laptop *asus = led_to_asus(led_cdev, kled); + + return asus_kled_lvl(asus); } #define ASUS_LED_UNREGISTER(object) \ @@ -468,10 +497,11 @@ static void asus_led_exit(struct asus_laptop *asus) } /* Ugly macro, need to fix that later */ -#define ASUS_LED_REGISTER(asus, object, _name, max) \ +#define ASUS_LED_REGISTER(asus, object, _name, max, method) \ do { \ struct led_classdev *ldev = &asus->leds.object; \ - if (!object##_set_handle) \ + \ + if (method && acpi_check_handle(asus->handle, method, NULL)) \ break ; \ \ INIT_WORK(&asus->leds.object##_work, object##_led_update); \ @@ -497,13 +527,14 @@ static int asus_led_init(struct asus_laptop *asus) if (!asus->leds.workqueue) return -ENOMEM; - ASUS_LED_REGISTER(asus, mled, "mail", 1); - ASUS_LED_REGISTER(asus, tled, "touchpad", 1); - ASUS_LED_REGISTER(asus, rled, "record", 1); - ASUS_LED_REGISTER(asus, pled, "phone", 1); - ASUS_LED_REGISTER(asus, gled, "gaming", 1); - if (kled_set_handle && kled_get_handle) - ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3); + ASUS_LED_REGISTER(asus, mled, "mail", 1, METHOD_MLED); + ASUS_LED_REGISTER(asus, tled, "touchpad", 1, METHOD_TLED); + ASUS_LED_REGISTER(asus, rled, "record", 1, METHOD_RLED); + ASUS_LED_REGISTER(asus, pled, "phone", 1, METHOD_PLED); + ASUS_LED_REGISTER(asus, gled, "gaming", 1, METHOD_GLED); + if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) && + !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) + ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3, NULL); error: if (rv) asus_led_exit(asus); @@ -557,10 +588,12 @@ static void lcd_blank(struct asus_laptop *asus, int blank) static int asus_read_brightness(struct backlight_device *bd) { + struct asus_laptop *asus = bl_get_data(bd); unsigned long long value; acpi_status rv = AE_OK; - rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); + rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, + NULL, &value); if (ACPI_FAILURE(rv)) pr_warning("Error reading brightness\n"); @@ -569,7 +602,9 @@ static int asus_read_brightness(struct backlight_device *bd) static int asus_set_brightness(struct backlight_device *bd, int value) { - if (write_acpi_int(brightness_set_handle, NULL, value)) { + struct asus_laptop *asus = bl_get_data(bd); + + if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) { pr_warning("Error changing brightness\n"); return -EIO; } @@ -600,7 +635,9 @@ static int asus_backlight_init(struct asus_laptop *asus) struct backlight_device *bd; struct device *dev = &asus->platform_device->dev; - if (brightness_set_handle && lcd_switch_handle) { + if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) && + !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) && + lcd_switch_handle) { bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, asus, &asusbl_ops); if (IS_ERR(bd)) { @@ -612,8 +649,8 @@ static int asus_backlight_init(struct asus_laptop *asus) asus->backlight_device = bd; bd->props.max_brightness = 15; - bd->props.brightness = asus_read_brightness(NULL); bd->props.power = FB_BLANK_UNBLANK; + bd->props.brightness = asus_read_brightness(bd); backlight_update_status(bd); } return 0; @@ -716,7 +753,7 @@ static int parse_arg(const char *buf, unsigned long count, int *val) static ssize_t sysfs_acpi_set(struct asus_laptop *asus, const char *buf, size_t count, - acpi_handle handle) + const char *method) { int rv, value; int out = 0; @@ -725,7 +762,7 @@ static ssize_t sysfs_acpi_set(struct asus_laptop *asus, if (rv > 0) out = value ? 1 : 0; - if (write_acpi_int(handle, NULL, value)) + if (write_acpi_int(asus->handle, method, value)) return -ENODEV; return rv; } @@ -749,7 +786,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) { - if (write_acpi_int(ledd_set_handle, NULL, value)) + if (write_acpi_int(asus->handle, METHOD_LEDD, value)) pr_warning("LED display write failed\n"); else asus->ledd_status = (u32) value; @@ -768,7 +805,8 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask) if (!asus->have_rsts) return (asus->wireless_status & mask) ? 1 : 0; - rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); + rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS, + NULL, &status); if (ACPI_FAILURE(rv)) { pr_warning("Error reading Wireless status\n"); return -EINVAL; @@ -792,7 +830,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sysfs_acpi_set(asus, buf, count, wl_switch_handle); + return sysfs_acpi_set(asus, buf, count, METHOD_WLAN); } /* @@ -812,7 +850,7 @@ static ssize_t store_bluetooth(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); - return sysfs_acpi_set(asus, buf, count, bt_switch_handle); + return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH); } /* @@ -821,7 +859,7 @@ static ssize_t store_bluetooth(struct device *dev, static void asus_set_display(struct asus_laptop *asus, int value) { /* no sanity check needed for now */ - if (write_acpi_int(display_set_handle, NULL, value)) + if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value)) pr_warning("Error setting display\n"); return; } @@ -883,7 +921,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, */ static void asus_als_switch(struct asus_laptop *asus, int value) { - if (write_acpi_int(ls_switch_handle, NULL, value)) + if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) pr_warning("Error setting light sensor switch\n"); asus->light_switch = value; } @@ -911,7 +949,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, static void asus_als_level(struct asus_laptop *asus, int value) { - if (write_acpi_int(ls_level_handle, NULL, value)) + if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value)) pr_warning("Error setting light sensor level\n"); asus->light_level = value; } @@ -949,7 +987,8 @@ static int asus_gps_status(struct asus_laptop *asus) unsigned long long status; acpi_status rv = AE_OK; - rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); + rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS, + NULL, &status); if (ACPI_FAILURE(rv)) { pr_warning("Error reading GPS status\n"); return -ENODEV; @@ -959,9 +998,9 @@ static int asus_gps_status(struct asus_laptop *asus) static int asus_gps_switch(struct asus_laptop *asus, int status) { - acpi_handle handle = status ? gps_on_handle : gps_off_handle; + const char *meth = status ? METHOD_GPS_ON : METHOD_GPS_OFF; - if (write_acpi_int(handle, NULL, 0x02)) + if (write_acpi_int(asus->handle, meth, 0x02)) return -ENODEV; return 0; } @@ -1224,27 +1263,33 @@ static void asus_laptop_add_fs(struct asus_laptop *asus) { ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); - if (wl_switch_handle) + if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan); - if (bt_switch_handle) + if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) ASUS_SET_DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth); - if (display_set_handle && display_get_handle) - ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp); - else if (display_set_handle) - ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp); + if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { + if (display_get_handle) + ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, + store_disp); + else + ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp); + } - if (ledd_set_handle) + if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd); - if (ls_switch_handle && ls_level_handle) { + if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && + !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); } - if (gps_status_handle && gps_on_handle && gps_off_handle) + if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); } @@ -1337,55 +1382,23 @@ static int asus_laptop_get_info(struct asus_laptop *asus) if (*string) pr_notice(" %s model detected\n", string); - ASUS_HANDLE_INIT(mled_set); - ASUS_HANDLE_INIT(tled_set); - ASUS_HANDLE_INIT(rled_set); - ASUS_HANDLE_INIT(pled_set); - ASUS_HANDLE_INIT(gled_set); - - ASUS_HANDLE_INIT(ledd_set); - - ASUS_HANDLE_INIT(kled_set); - ASUS_HANDLE_INIT(kled_get); - /* * The HWRS method return informations about the hardware. * 0x80 bit is for WLAN, 0x100 for Bluetooth. * The significance of others is yet to be found. - * If we don't find the method, we assume the device are present. */ status = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); - if (ACPI_FAILURE(status)) - hwrs_result = WL_HWRS | BT_HWRS; + if (!ACPI_FAILURE(status)) + pr_notice(" HRWS returned %x", (int)hwrs_result); - if (hwrs_result & WL_HWRS) - ASUS_HANDLE_INIT(wl_switch); - if (hwrs_result & BT_HWRS) - ASUS_HANDLE_INIT(bt_switch); - - if (!ASUS_HANDLE_INIT(wireless_status)) + if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; - ASUS_HANDLE_INIT(brightness_set); - ASUS_HANDLE_INIT(brightness_get); - + /* Scheduled for removal */ ASUS_HANDLE_INIT(lcd_switch); - - ASUS_HANDLE_INIT(display_set); ASUS_HANDLE_INIT(display_get); - /* - * There is a lot of models with "ALSL", but a few get - * a real light sens, so we need to check it. - */ - if (!ASUS_HANDLE_INIT(ls_switch)) - ASUS_HANDLE_INIT(ls_level); - - ASUS_HANDLE_INIT(gps_on); - ASUS_HANDLE_INIT(gps_off); - ASUS_HANDLE_INIT(gps_status); - kfree(model); return AE_OK; @@ -1413,12 +1426,14 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) /* WLED and BLED are on by default */ if (bluetooth_status >= 0) - write_acpi_int(bt_switch_handle, NULL, !!bluetooth_status); + write_acpi_int(asus->handle, METHOD_BLUETOOTH, + !!bluetooth_status); if (wireless_status >= 0) - write_acpi_int(wl_switch_handle, NULL, !!wireless_status); + write_acpi_int(asus->handle, METHOD_WLAN, + !!wireless_status); /* Keyboard Backlight is on by default */ - if (kled_set_handle) + if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) asus_kled_set(asus, 1); /* LED display is off by default */ @@ -1428,14 +1443,17 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) asus->light_switch = 0; /* Default to light sensor disabled */ asus->light_level = 5; /* level 5 for sensor sensitivity */ - if (ls_switch_handle) + if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && + !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { asus_als_switch(asus, asus->light_switch); - - if (ls_level_handle) asus_als_level(asus, asus->light_level); + } /* GPS is on by default */ - asus_gps_switch(asus, 1); + if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) + asus_gps_switch(asus, 1); return result; } -- cgit v1.2.3-70-g09d2 From e5593bf18be79b4897c7ec8b392dc7f07cbc1b11 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 17 Jan 2010 17:20:11 +0100 Subject: asus-laptop: add error check for write_acpi_int calls Also add to helpers for bluetooth and wlan. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 671fad96c275..aad6b9300f5d 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -350,7 +350,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method, } /* Generic LED function */ -static void asus_led_set(struct asus_laptop *asus, char *method, +static int asus_led_set(struct asus_laptop *asus, char *method, int value) { if (!strcmp(method, METHOD_MLED)) @@ -360,7 +360,7 @@ static void asus_led_set(struct asus_laptop *asus, char *method, else value = !!value; - write_acpi_int(asus->handle, method, value); + return write_acpi_int(asus->handle, method, value); } /* @@ -817,6 +817,15 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask) /* * WLAN */ +static int asus_wlan_set(struct asus_laptop *asus, int status) +{ + if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) { + pr_warning("Error setting wlan status to %d", status); + return -EIO; + } + return 0; +} + static ssize_t show_wlan(struct device *dev, struct device_attribute *attr, char *buf) { @@ -836,6 +845,15 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, /* * Bluetooth */ +static int asus_bluetooth_set(struct asus_laptop *asus, int status) +{ + if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) { + pr_warning("Error setting bluetooth status to %d", status); + return -EIO; + } + return 0; +} + static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1353,8 +1371,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus) (uint) bsts_result); /* This too ... */ - write_acpi_int(asus->handle, "CWAP", wapf); - + if (write_acpi_int(asus->handle, "CWAP", wapf)) + pr_err("Error calling CWAP(%d)\n", wapf); /* * Try to match the object returned by INIT to the specific model. * Handle every possible object (or the lack of thereof) the DSDT @@ -1426,11 +1444,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) /* WLED and BLED are on by default */ if (bluetooth_status >= 0) - write_acpi_int(asus->handle, METHOD_BLUETOOTH, - !!bluetooth_status); + asus_bluetooth_set(asus, !!bluetooth_status); + if (wireless_status >= 0) - write_acpi_int(asus->handle, METHOD_WLAN, - !!wireless_status); + asus_wlan_set(asus, !!wireless_status); /* Keyboard Backlight is on by default */ if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) -- cgit v1.2.3-70-g09d2 From d0930a2d42c5a28039d8cc2376a7dff4e59c5f7a Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 17 Jan 2010 17:21:13 +0100 Subject: asus-laptop: rename wireless_status to wlan_status to avoid confusion Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index aad6b9300f5d..bb8fb45c45e9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -76,11 +76,11 @@ static uint wapf = 1; module_param(wapf, uint, 0644); MODULE_PARM_DESC(wapf, "WAPF value"); -static uint wireless_status = 1; +static uint wlan_status = 1; static uint bluetooth_status = 1; -module_param(wireless_status, uint, 0644); -MODULE_PARM_DESC(wireless_status, "Set the wireless status on boot " +module_param(wlan_status, uint, 0644); +MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " "(0 = disabled, 1 = enabled, -1 = don't do anything). " "default is 1"); @@ -1446,8 +1446,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) if (bluetooth_status >= 0) asus_bluetooth_set(asus, !!bluetooth_status); - if (wireless_status >= 0) - asus_wlan_set(asus, !!wireless_status); + if (wlan_status >= 0) + asus_wlan_set(asus, !!wlan_status); /* Keyboard Backlight is on by default */ if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) -- cgit v1.2.3-70-g09d2 From 66a71dd1f7c4eee636867d381995b7e6ae489dc3 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 25 Jan 2010 22:50:11 +0100 Subject: asus-laptop: switch to sparse keymap library This patch is based on Dmitry Torokhov's patch with some modifications and cleanups. Signed-off-by: Corentin Chary --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/asus-laptop.c | 208 ++++++++++++------------------------- 2 files changed, 68 insertions(+), 141 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f526e735c5ab..7f5a222c2325 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -59,6 +59,7 @@ config ASUS_LAPTOP select NEW_LEDS select BACKLIGHT_CLASS_DEVICE depends on INPUT + select INPUT_SPARSEKMAP ---help--- This is the new Linux driver for Asus laptops. It may also support some MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index bb8fb45c45e9..8042568528e5 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -49,6 +49,7 @@ #include #include #include +#include #define ASUS_LAPTOP_VERSION "0.42" @@ -243,52 +244,45 @@ struct asus_laptop { u16 *keycode_map; }; -struct key_entry { - char type; - u8 code; - u16 keycode; -}; - -enum { KE_KEY, KE_END }; - static const struct key_entry asus_keymap[] = { - {KE_KEY, 0x02, KEY_SCREENLOCK}, - {KE_KEY, 0x05, KEY_WLAN}, - {KE_KEY, 0x08, KEY_F13}, - {KE_KEY, 0x17, KEY_ZOOM}, - {KE_KEY, 0x1f, KEY_BATTERY}, - {KE_KEY, 0x30, KEY_VOLUMEUP}, - {KE_KEY, 0x31, KEY_VOLUMEDOWN}, - {KE_KEY, 0x32, KEY_MUTE}, - {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x40, KEY_PREVIOUSSONG}, - {KE_KEY, 0x41, KEY_NEXTSONG}, - {KE_KEY, 0x43, KEY_STOPCD}, - {KE_KEY, 0x45, KEY_PLAYPAUSE}, - {KE_KEY, 0x4c, KEY_MEDIA}, - {KE_KEY, 0x50, KEY_EMAIL}, - {KE_KEY, 0x51, KEY_WWW}, - {KE_KEY, 0x55, KEY_CALC}, - {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ - {KE_KEY, 0x5D, KEY_WLAN}, - {KE_KEY, 0x5E, KEY_WLAN}, - {KE_KEY, 0x5F, KEY_WLAN}, - {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE}, - {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */ - {KE_KEY, 0x82, KEY_CAMERA}, - {KE_KEY, 0x88, KEY_WLAN }, - {KE_KEY, 0x8A, KEY_PROG1}, - {KE_KEY, 0x95, KEY_MEDIA}, - {KE_KEY, 0x99, KEY_PHONE}, - {KE_KEY, 0xc4, KEY_KBDILLUMUP}, - {KE_KEY, 0xc5, KEY_KBDILLUMDOWN}, + {KE_KEY, 0x02, { KEY_SCREENLOCK } }, + {KE_KEY, 0x05, { KEY_WLAN } }, + {KE_KEY, 0x08, { KEY_F13 } }, + {KE_KEY, 0x17, { KEY_ZOOM } }, + {KE_KEY, 0x1f, { KEY_BATTERY } }, + {KE_KEY, 0x30, { KEY_VOLUMEUP } }, + {KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, + {KE_KEY, 0x32, { KEY_MUTE } }, + {KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, + {KE_KEY, 0x41, { KEY_NEXTSONG } }, + {KE_KEY, 0x43, { KEY_STOPCD } }, + {KE_KEY, 0x45, { KEY_PLAYPAUSE } }, + {KE_KEY, 0x4c, { KEY_MEDIA } }, + {KE_KEY, 0x50, { KEY_EMAIL } }, + {KE_KEY, 0x51, { KEY_WWW } }, + {KE_KEY, 0x55, { KEY_CALC } }, + {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */ + {KE_KEY, 0x5D, { KEY_WLAN } }, + {KE_KEY, 0x5E, { KEY_WLAN } }, + {KE_KEY, 0x5F, { KEY_WLAN } }, + {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, + {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */ + {KE_KEY, 0x82, { KEY_CAMERA } }, + {KE_KEY, 0x88, { KEY_WLAN } }, + {KE_KEY, 0x8A, { KEY_PROG1 } }, + {KE_KEY, 0x95, { KEY_MEDIA } }, + {KE_KEY, 0x99, { KEY_PHONE } }, + {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, + {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, {KE_END, 0}, }; + /* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output @@ -1050,123 +1044,55 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, /* * Input device (i.e. hotkeys) */ -static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus, - int code) -{ - struct key_entry *key; - - for (key = asus->keymap; key->type != KE_END; key++) - if (code == key->code) - return key; - - return NULL; -} - -static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus, - int code) -{ - struct key_entry *key; - - for (key = asus->keymap; key->type != KE_END; key++) - if (code == key->keycode && key->type == KE_KEY) - return key; - - return NULL; -} - -static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ - struct asus_laptop *asus = input_get_drvdata(dev); - struct key_entry *key = asus_get_entry_by_scancode(asus, scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; - } - - return -EINVAL; -} - -static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct asus_laptop *asus = input_get_drvdata(dev); - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = asus_get_entry_by_scancode(asus, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!asus_get_entry_by_keycode(asus, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; - } - - return -EINVAL; -} - static void asus_input_notify(struct asus_laptop *asus, int event) { - struct key_entry *key; - - key = asus_get_entry_by_scancode(asus, event); - if (!key) - return ; - - switch (key->type) { - case KE_KEY: - input_report_key(asus->inputdev, key->keycode, 1); - input_sync(asus->inputdev); - input_report_key(asus->inputdev, key->keycode, 0); - input_sync(asus->inputdev); - break; - } + if (asus->inputdev) + sparse_keymap_report_event(asus->inputdev, event, 1, true); } static int asus_input_init(struct asus_laptop *asus) { - const struct key_entry *key; - int result; + struct input_dev *input; + int error; - asus->inputdev = input_allocate_device(); - if (!asus->inputdev) { + input = input_allocate_device(); + if (!input) { pr_info("Unable to allocate input device\n"); return 0; } - asus->inputdev->name = "Asus Laptop extra buttons"; - asus->inputdev->dev.parent = &asus->platform_device->dev; - asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; - asus->inputdev->id.bustype = BUS_HOST; - asus->inputdev->getkeycode = asus_getkeycode; - asus->inputdev->setkeycode = asus_setkeycode; - input_set_drvdata(asus->inputdev, asus); - - asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap), - GFP_KERNEL); - for (key = asus->keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, asus->inputdev->evbit); - set_bit(key->keycode, asus->inputdev->keybit); - break; - } + input->name = "Asus Laptop extra buttons"; + input->phys = ASUS_LAPTOP_FILE "/input0"; + input->id.bustype = BUS_HOST; + input->dev.parent = &asus->platform_device->dev; + input_set_drvdata(input, asus); + + error = sparse_keymap_setup(input, asus_keymap, NULL); + if (error) { + pr_err("Unable to setup input device keymap\n"); + goto err_keymap; } - result = input_register_device(asus->inputdev); - if (result) { + error = input_register_device(input); + if (error) { pr_info("Unable to register input device\n"); - input_free_device(asus->inputdev); + goto err_device; } - return result; + + asus->inputdev = input; + return 0; + +err_keymap: + sparse_keymap_free(input); +err_device: + input_free_device(input); + return error; } static void asus_input_exit(struct asus_laptop *asus) { - if (asus->inputdev) + if (asus->inputdev) { + sparse_keymap_free(asus->inputdev); input_unregister_device(asus->inputdev); + } } /* -- cgit v1.2.3-70-g09d2 From 7f607d71065b6b089f59b78b54144c3fb93ad629 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 17 Jan 2010 17:37:19 +0100 Subject: asus-laptop: add bluetooth keys found on M9V Reported by Andrey F. Ilchuk Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8042568528e5..4f3c4674498b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -272,6 +272,8 @@ static const struct key_entry asus_keymap[] = { {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */ + {KE_KEY, 0x7E, { KEY_BLUETOOTH } }, + {KE_KEY, 0x7D, { KEY_BLUETOOTH } }, {KE_KEY, 0x82, { KEY_CAMERA } }, {KE_KEY, 0x88, { KEY_WLAN } }, {KE_KEY, 0x8A, { KEY_PROG1 } }, -- cgit v1.2.3-70-g09d2 From a539df5e1548751e352990c518e88af50e6111b8 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 25 Jan 2010 22:53:21 +0100 Subject: asus-laptop: add backlight changes notifications We don't want to send KEY_BRIGHTNESSDOWN or KEY_BRIGHTNESSUP because it would be a lie to tell userspace that we want to change the brightness while it's actually done by the firmware. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 4f3c4674498b..516add3c340e 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -93,8 +93,10 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " /* * Some events we use, same for all Asus */ -#define ATKD_BR_UP 0x10 -#define ATKD_BR_DOWN 0x20 +#define ATKD_BR_UP 0x10 // (event & ~ATKD_BR_UP) = brightness level +#define ATKD_BR_DOWN 0x20 // (event & ~ATKD_BR_DOWN) = britghness level +#define ATKD_BR_MIN ATKD_BR_UP +#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) // 0x2f #define ATKD_LCD_ON 0x33 #define ATKD_LCD_OFF 0x34 @@ -245,11 +247,13 @@ struct asus_laptop { }; static const struct key_entry asus_keymap[] = { + /* Lenovo SL Specific keycodes */ {KE_KEY, 0x02, { KEY_SCREENLOCK } }, {KE_KEY, 0x05, { KEY_WLAN } }, {KE_KEY, 0x08, { KEY_F13 } }, {KE_KEY, 0x17, { KEY_ZOOM } }, {KE_KEY, 0x1f, { KEY_BATTERY } }, + /* End of Lenovo SL Specific keycodes */ {KE_KEY, 0x30, { KEY_VOLUMEUP } }, {KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, {KE_KEY, 0x32, { KEY_MUTE } }, @@ -626,6 +630,16 @@ static struct backlight_ops asusbl_ops = { .update_status = update_bl_status, }; +static int asus_backlight_notify(struct asus_laptop *asus) +{ + struct backlight_device *bd = asus->backlight_device; + int old = bd->props.brightness; + + backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY); + + return old; +} + static int asus_backlight_init(struct asus_laptop *asus) { struct backlight_device *bd; @@ -656,6 +670,7 @@ static void asus_backlight_exit(struct asus_laptop *asus) { if (asus->backlight_device) backlight_device_unregister(asus->backlight_device); + asus->backlight_device = NULL; } /* @@ -1121,6 +1136,16 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) dev_name(&asus->device->dev), event, count); + /* Brightness events are special */ + if (event >= ATKD_BR_MIN && event <= ATKD_BR_MAX) { + + /* Ignore them completely if the acpi video driver is used */ + if (asus->backlight_device != NULL) { + /* Update the backlight device. */ + asus_backlight_notify(asus); + } + return ; + } asus_input_notify(asus, event); } -- cgit v1.2.3-70-g09d2 From 75747129a994463e36c2516e8071771427d8494b Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 24 Jan 2010 11:15:42 +0100 Subject: asus-laptop: leds, remove dead code and fix asus_led_exit()/asus_led_init() These bug where introduced in "asus-laptop: code movement". Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 516add3c340e..ca144d251b00 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -371,13 +371,7 @@ static int asus_led_set(struct asus_laptop *asus, char *method, enum led_brightness value); \ static enum led_brightness object##_led_get( \ struct led_classdev *led_cdev); \ - static void object##_led_update(struct work_struct *ignored); \ - static struct led_classdev object##_led = { \ - .name = "asus::" ledname, \ - .brightness_set = object##_led_set, \ - .brightness_get = object##_led_get, \ - .max_brightness = max \ - } + static void object##_led_update(struct work_struct *ignored); ASUS_LED(mled, "mail", 1); ASUS_LED(tled, "touchpad", 1); @@ -478,18 +472,20 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev) return asus_kled_lvl(asus); } -#define ASUS_LED_UNREGISTER(object) \ - if (object##_led.dev) \ - led_classdev_unregister(&object##_led) - static void asus_led_exit(struct asus_laptop *asus) { - ASUS_LED_UNREGISTER(mled); - ASUS_LED_UNREGISTER(tled); - ASUS_LED_UNREGISTER(pled); - ASUS_LED_UNREGISTER(rled); - ASUS_LED_UNREGISTER(gled); - ASUS_LED_UNREGISTER(kled); + if (asus->leds.mled.dev) + led_classdev_unregister(&asus->leds.mled); + if (asus->leds.tled.dev) + led_classdev_unregister(&asus->leds.tled); + if (asus->leds.pled.dev) + led_classdev_unregister(&asus->leds.pled); + if (asus->leds.rled.dev) + led_classdev_unregister(&asus->leds.rled); + if (asus->leds.gled.dev) + led_classdev_unregister(&asus->leds.gled); + if (asus->leds.kled.dev) + led_classdev_unregister(&asus->leds.kled); if (asus->leds.workqueue) { destroy_workqueue(asus->leds.workqueue); asus->leds.workqueue = NULL; @@ -507,6 +503,7 @@ static void asus_led_exit(struct asus_laptop *asus) INIT_WORK(&asus->leds.object##_work, object##_led_update); \ ldev->name = "asus::" _name; \ ldev->brightness_set = object##_led_set; \ + ldev->brightness_get = object##_led_get; \ ldev->max_brightness = max; \ rv = led_classdev_register(&asus->platform_device->dev, ldev); \ if (rv) \ -- cgit v1.2.3-70-g09d2 From 47ee0e99524a7ee0185e3c38423cc17cc1318ddc Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 24 Jan 2010 11:17:15 +0100 Subject: asus-laptop: set initial lcd state There is no way to find the initial lcd state. A quick workaround is to set it "on" by default. Anyway this feature is scheduled for removal. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ca144d251b00..1d61094d3b5f 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1421,6 +1421,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) asus_gps_switch(asus, 1); + + asus->lcd_state = 1; /* LCD should be on when the module load */ return result; } -- cgit v1.2.3-70-g09d2 From 18e1311ee71a67497a33521be61ddf6562fa22c0 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 25 Jan 2010 23:29:24 +0100 Subject: asus-laptop: add gps rfkill The rfkill subsystem will enable gps by default. Signed-off-by: Corentin Chary --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/asus-laptop.c | 65 ++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 7 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7f5a222c2325..527abf1b5bd1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -59,6 +59,7 @@ config ASUS_LAPTOP select NEW_LEDS select BACKLIGHT_CLASS_DEVICE depends on INPUT + depends on RFKILL || RFKILL = n select INPUT_SPARSEKMAP ---help--- This is the new Linux driver for Asus laptops. It may also support some diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 1d61094d3b5f..e1df92a22de9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -50,6 +50,7 @@ #include #include #include +#include #define ASUS_LAPTOP_VERSION "0.42" @@ -238,6 +239,8 @@ struct asus_laptop { bool have_rsts; int lcd_state; + struct rfkill *gps_rfkill; + acpi_handle handle; /* the handle of the hotk device */ u32 ledd_status; /* status of the LED display */ u8 light_level; /* light sensor level */ @@ -1006,7 +1009,6 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, /* * GPS - * TODO: use rfkill */ static int asus_gps_status(struct asus_laptop *asus) { @@ -1052,9 +1054,57 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, ret = asus_gps_switch(asus, !!value); if (ret) return ret; + rfkill_set_sw_state(asus->gps_rfkill, !value); return rv; } +/* + * rfkill + */ +static int asus_gps_rfkill_set(void *data, bool blocked) +{ + acpi_handle handle = data; + + return asus_gps_switch(handle, !blocked); +} + +static const struct rfkill_ops asus_gps_rfkill_ops = { + .set_block = asus_gps_rfkill_set, +}; + +static void asus_rfkill_exit(struct asus_laptop *asus) +{ + if (asus->gps_rfkill) { + rfkill_unregister(asus->gps_rfkill); + rfkill_destroy(asus->gps_rfkill); + asus->gps_rfkill = NULL; + } +} + +static int asus_rfkill_init(struct asus_laptop *asus) +{ + int result; + + if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) || + acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) || + acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) + return 0; + + asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, + RFKILL_TYPE_GPS, + &asus_gps_rfkill_ops, NULL); + if (!asus->gps_rfkill) + return -EINVAL; + + result = rfkill_register(asus->gps_rfkill); + if (result) { + rfkill_destroy(asus->gps_rfkill); + asus->gps_rfkill = NULL; + } + + return result; +} + /* * Input device (i.e. hotkeys) */ @@ -1416,12 +1466,6 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) asus_als_level(asus, asus->light_level); } - /* GPS is on by default */ - if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && - !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && - !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) - asus_gps_switch(asus, 1); - asus->lcd_state = 1; /* LCD should be on when the module load */ return result; } @@ -1469,9 +1513,15 @@ static int __devinit asus_acpi_add(struct acpi_device *device) if (result) goto fail_led; + result = asus_rfkill_init(asus); + if (result) + goto fail_rfkill; + asus_device_present = true; return 0; +fail_rfkill: + asus_led_exit(asus); fail_led: asus_input_exit(asus); fail_input: @@ -1490,6 +1540,7 @@ static int asus_acpi_remove(struct acpi_device *device, int type) struct asus_laptop *asus = acpi_driver_data(device); asus_backlight_exit(asus); + asus_rfkill_exit(asus); asus_led_exit(asus); asus_input_exit(asus); asus_platform_exit(asus); -- cgit v1.2.3-70-g09d2 From aee0afb8cb52178164accfec9cfc58bc27b597b3 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 26 Jan 2010 21:01:34 +0100 Subject: asus-laptop: clean led code Remove all "templates" and add a generic struct asus_led instead. Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 235 ++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 120 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e1df92a22de9..ae5302646c4e 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -193,29 +193,12 @@ ASUS_HANDLE(display_get, /* * Define a specific led structure to keep the main structure clean */ -#define ASUS_DEFINE_LED(object) \ - int object##_wk; \ - struct work_struct object##_work; \ - struct led_classdev object; - - -#define led_to_asus(led_cdev, led) \ - container_of(container_of(led_cdev, struct asus_laptop_leds, \ - led), \ - struct asus_laptop, leds) -#define work_to_asus(work, led) \ - container_of(container_of(work, struct asus_laptop_leds, \ - led##_work), \ - struct asus_laptop, leds) - -struct asus_laptop_leds { - ASUS_DEFINE_LED(mled) - ASUS_DEFINE_LED(tled) - ASUS_DEFINE_LED(rled) - ASUS_DEFINE_LED(pled) - ASUS_DEFINE_LED(gled) - ASUS_DEFINE_LED(kled) - struct workqueue_struct *workqueue; +struct asus_led { + int wk; + struct work_struct work; + struct led_classdev led; + struct asus_laptop *asus; + const char *method; }; /* @@ -233,7 +216,13 @@ struct asus_laptop { struct input_dev *inputdev; struct key_entry *keymap; - struct asus_laptop_leds leds; + struct asus_led mled; + struct asus_led tled; + struct asus_led rled; + struct asus_led pled; + struct asus_led gled; + struct asus_led kled; + struct workqueue_struct *led_workqueue; int wireless_status; bool have_rsts; @@ -353,7 +342,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method, } /* Generic LED function */ -static int asus_led_set(struct asus_laptop *asus, char *method, +static int asus_led_set(struct asus_laptop *asus, const char *method, int value) { if (!strcmp(method, METHOD_MLED)) @@ -369,50 +358,29 @@ static int asus_led_set(struct asus_laptop *asus, char *method, /* * LEDs */ -#define ASUS_LED(object, ledname, max) \ - static void object##_led_set(struct led_classdev *led_cdev, \ - enum led_brightness value); \ - static enum led_brightness object##_led_get( \ - struct led_classdev *led_cdev); \ - static void object##_led_update(struct work_struct *ignored); - -ASUS_LED(mled, "mail", 1); -ASUS_LED(tled, "touchpad", 1); -ASUS_LED(rled, "record", 1); -ASUS_LED(pled, "phone", 1); -ASUS_LED(gled, "gaming", 1); -ASUS_LED(kled, "kbd_backlight", 3); - /* /sys/class/led handlers */ -#define ASUS_LED_HANDLER(object, method) \ - static void object##_led_set(struct led_classdev *led_cdev, \ - enum led_brightness value) \ - { \ - struct asus_laptop *asus = \ - led_to_asus(led_cdev, object); \ - \ - asus->leds.object##_wk = (value > 0) ? 1 : 0; \ - queue_work(asus->leds.workqueue, \ - &asus->leds.object##_work); \ - } \ - static void object##_led_update(struct work_struct *work) \ - { \ - struct asus_laptop *asus = work_to_asus(work, object); \ - \ - int value = asus->leds.object##_wk; \ - asus_led_set(asus, method, value); \ - } \ - static enum led_brightness object##_led_get( \ - struct led_classdev *led_cdev) \ - { \ - return led_cdev->brightness; \ - } +static void asus_led_cdev_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct asus_led *led = container_of(led_cdev, struct asus_led, led); + struct asus_laptop *asus = led->asus; + + led->wk = !!value; + queue_work(asus->led_workqueue, &led->work); +} + +static void asus_led_cdev_update(struct work_struct *work) +{ + struct asus_led *led = container_of(work, struct asus_led, work); + struct asus_laptop *asus = led->asus; -ASUS_LED_HANDLER(mled, METHOD_MLED); -ASUS_LED_HANDLER(pled, METHOD_PLED); -ASUS_LED_HANDLER(rled, METHOD_RLED); -ASUS_LED_HANDLER(tled, METHOD_TLED); -ASUS_LED_HANDLER(gled, METHOD_GLED); + asus_led_set(asus, led->method, led->wk); +} + +static enum led_brightness asus_led_cdev_get(struct led_classdev *led_cdev) +{ + return led_cdev->brightness; +} /* * Keyboard backlight (also a LED) @@ -452,70 +420,76 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv) return 0; } -static void kled_led_set(struct led_classdev *led_cdev, - enum led_brightness value) +static void asus_kled_cdev_set(struct led_classdev *led_cdev, + enum led_brightness value) { - struct asus_laptop *asus = led_to_asus(led_cdev, kled); + struct asus_led *led = container_of(led_cdev, struct asus_led, led); + struct asus_laptop *asus = led->asus; - asus->leds.kled_wk = value; - queue_work(asus->leds.workqueue, &asus->leds.kled_work); + led->wk = value; + queue_work(asus->led_workqueue, &led->work); } -static void kled_led_update(struct work_struct *work) +static void asus_kled_cdev_update(struct work_struct *work) { - struct asus_laptop *asus = work_to_asus(work, kled); + struct asus_led *led = container_of(work, struct asus_led, work); + struct asus_laptop *asus = led->asus; - asus_kled_set(asus, asus->leds.kled_wk); + asus_kled_set(asus, led->wk); } -static enum led_brightness kled_led_get(struct led_classdev *led_cdev) +static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev) { - struct asus_laptop *asus = led_to_asus(led_cdev, kled); + struct asus_led *led = container_of(led_cdev, struct asus_led, led); + struct asus_laptop *asus = led->asus; return asus_kled_lvl(asus); } static void asus_led_exit(struct asus_laptop *asus) { - if (asus->leds.mled.dev) - led_classdev_unregister(&asus->leds.mled); - if (asus->leds.tled.dev) - led_classdev_unregister(&asus->leds.tled); - if (asus->leds.pled.dev) - led_classdev_unregister(&asus->leds.pled); - if (asus->leds.rled.dev) - led_classdev_unregister(&asus->leds.rled); - if (asus->leds.gled.dev) - led_classdev_unregister(&asus->leds.gled); - if (asus->leds.kled.dev) - led_classdev_unregister(&asus->leds.kled); - if (asus->leds.workqueue) { - destroy_workqueue(asus->leds.workqueue); - asus->leds.workqueue = NULL; + if (asus->mled.led.dev) + led_classdev_unregister(&asus->mled.led); + if (asus->tled.led.dev) + led_classdev_unregister(&asus->tled.led); + if (asus->pled.led.dev) + led_classdev_unregister(&asus->pled.led); + if (asus->rled.led.dev) + led_classdev_unregister(&asus->rled.led); + if (asus->gled.led.dev) + led_classdev_unregister(&asus->gled.led); + if (asus->kled.led.dev) + led_classdev_unregister(&asus->kled.led); + if (asus->led_workqueue) { + destroy_workqueue(asus->led_workqueue); + asus->led_workqueue = NULL; } } /* Ugly macro, need to fix that later */ -#define ASUS_LED_REGISTER(asus, object, _name, max, method) \ - do { \ - struct led_classdev *ldev = &asus->leds.object; \ - \ - if (method && acpi_check_handle(asus->handle, method, NULL)) \ - break ; \ - \ - INIT_WORK(&asus->leds.object##_work, object##_led_update); \ - ldev->name = "asus::" _name; \ - ldev->brightness_set = object##_led_set; \ - ldev->brightness_get = object##_led_get; \ - ldev->max_brightness = max; \ - rv = led_classdev_register(&asus->platform_device->dev, ldev); \ - if (rv) \ - goto error; \ - } while (0) +static int asus_led_register(struct asus_laptop *asus, + struct asus_led *led, + const char *name, const char *method) +{ + struct led_classdev *led_cdev = &led->led; + + if (!method || acpi_check_handle(asus->handle, method, NULL)) + return 0; /* Led not present */ + + led->asus = asus; + led->method = method; + + INIT_WORK(&led->work, asus_led_cdev_update); + led_cdev->name = name; + led_cdev->brightness_set = asus_led_cdev_set; + led_cdev->brightness_get = asus_led_cdev_get; + led_cdev->max_brightness = 1; + return led_classdev_register(&asus->platform_device->dev, led_cdev); +} static int asus_led_init(struct asus_laptop *asus) { - int rv; + int r; /* * Functions that actually update the LED's are called from a @@ -523,22 +497,43 @@ static int asus_led_init(struct asus_laptop *asus) * subsystem asks, we avoid messing with the Asus ACPI stuff during a * potentially bad time, such as a timer interrupt. */ - asus->leds.workqueue = create_singlethread_workqueue("led_workqueue"); - if (!asus->leds.workqueue) + asus->led_workqueue = create_singlethread_workqueue("led_workqueue"); + if (!asus->led_workqueue) return -ENOMEM; - ASUS_LED_REGISTER(asus, mled, "mail", 1, METHOD_MLED); - ASUS_LED_REGISTER(asus, tled, "touchpad", 1, METHOD_TLED); - ASUS_LED_REGISTER(asus, rled, "record", 1, METHOD_RLED); - ASUS_LED_REGISTER(asus, pled, "phone", 1, METHOD_PLED); - ASUS_LED_REGISTER(asus, gled, "gaming", 1, METHOD_GLED); + r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED); + if (r) + goto error; + r = asus_led_register(asus, &asus->tled, "asus::touchpad", METHOD_TLED); + if (r) + goto error; + r = asus_led_register(asus, &asus->rled, "asus::record", METHOD_RLED); + if (r) + goto error; + r = asus_led_register(asus, &asus->pled, "asus::phone", METHOD_PLED); + if (r) + goto error; + r = asus_led_register(asus, &asus->gled, "asus::gaming", METHOD_GLED); + if (r) + goto error; if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) && - !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) - ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3, NULL); + !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) { + struct asus_led *led = &asus->kled; + struct led_classdev *cdev = &led->led; + + led->asus = asus; + + INIT_WORK(&led->work, asus_kled_cdev_update); + cdev->name = "asus::kbd_backlight"; + cdev->brightness_set = asus_kled_cdev_set; + cdev->brightness_get = asus_kled_cdev_get; + cdev->max_brightness = 3; + r = led_classdev_register(&asus->platform_device->dev, cdev); + } error: - if (rv) + if (r) asus_led_exit(asus); - return rv; + return r; } /* -- cgit v1.2.3-70-g09d2 From 2a1fd64cb70a42563d2313eb70c6495d2c88b36d Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 26 Jan 2010 21:02:23 +0100 Subject: asus-laptop: use device_create_file() instead of platform_group There is two reason to do that: - we don't want a "gps" file if the model doesn't have a gps - we don't want to use global variables anymore Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 166 +++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 82 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ae5302646c4e..d0d117b0cf79 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -918,6 +918,8 @@ static ssize_t show_disp(struct device *dev, { struct asus_laptop *asus = dev_get_drvdata(dev); + if (!display_get_handle) + return -ENODEV; return sprintf(buf, "%d\n", read_display(asus)); } @@ -1191,77 +1193,113 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) asus_input_notify(asus, event); } -#define ASUS_CREATE_DEVICE_ATTR(_name) \ - struct device_attribute dev_attr_##_name = { \ - .attr = { \ - .name = __stringify(_name), \ - .mode = 0 }, \ - .show = NULL, \ - .store = NULL, \ +static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL); +static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); +static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth, + store_bluetooth); +static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); +static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); +static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); +static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); +static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); + +static void asus_sysfs_exit(struct asus_laptop *asus) +{ + struct platform_device *device = asus->platform_device; + + device_remove_file(&device->dev, &dev_attr_infos); + device_remove_file(&device->dev, &dev_attr_wlan); + device_remove_file(&device->dev, &dev_attr_bluetooth); + device_remove_file(&device->dev, &dev_attr_display); + device_remove_file(&device->dev, &dev_attr_ledd); + device_remove_file(&device->dev, &dev_attr_ls_switch); + device_remove_file(&device->dev, &dev_attr_ls_level); + device_remove_file(&device->dev, &dev_attr_gps); +} + +static int asus_sysfs_init(struct asus_laptop *asus) +{ + struct platform_device *device = asus->platform_device; + int err; + + err = device_create_file(&device->dev, &dev_attr_infos); + if (err) + return err; + + if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) { + err = device_create_file(&device->dev, &dev_attr_wlan); + if (err) + return err; } -#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \ - do { \ - dev_attr_##_name.attr.mode = _mode; \ - dev_attr_##_name.show = _show; \ - dev_attr_##_name.store = _store; \ - } while(0) - -static ASUS_CREATE_DEVICE_ATTR(infos); -static ASUS_CREATE_DEVICE_ATTR(wlan); -static ASUS_CREATE_DEVICE_ATTR(bluetooth); -static ASUS_CREATE_DEVICE_ATTR(display); -static ASUS_CREATE_DEVICE_ATTR(ledd); -static ASUS_CREATE_DEVICE_ATTR(ls_switch); -static ASUS_CREATE_DEVICE_ATTR(ls_level); -static ASUS_CREATE_DEVICE_ATTR(gps); - -static struct attribute *asuspf_attributes[] = { - &dev_attr_infos.attr, - &dev_attr_wlan.attr, - &dev_attr_bluetooth.attr, - &dev_attr_display.attr, - &dev_attr_ledd.attr, - &dev_attr_ls_switch.attr, - &dev_attr_ls_level.attr, - &dev_attr_gps.attr, - NULL -}; + if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) { + err = device_create_file(&device->dev, &dev_attr_bluetooth); + if (err) + return err; + } -static struct attribute_group platform_attribute_group = { - .attrs = asuspf_attributes -}; + if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { + err = device_create_file(&device->dev, &dev_attr_display); + if (err) + return err; + } + + if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) { + err = device_create_file(&device->dev, &dev_attr_ledd); + if (err) + return err; + } + + if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && + !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { + err = device_create_file(&device->dev, &dev_attr_ls_switch); + if (err) + return err; + err = device_create_file(&device->dev, &dev_attr_ls_level); + if (err) + return err; + } + + if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && + !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) { + err = device_create_file(&device->dev, &dev_attr_gps); + if (err) + return err; + } + + return err; +} static int asus_platform_init(struct asus_laptop *asus) { - int result; + int err; asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); if (!asus->platform_device) return -ENOMEM; platform_set_drvdata(asus->platform_device, asus); - result = platform_device_add(asus->platform_device); - if (result) + err = platform_device_add(asus->platform_device); + if (err) goto fail_platform_device; - result = sysfs_create_group(&asus->platform_device->dev.kobj, - &platform_attribute_group); - if (result) + err = asus_sysfs_init(asus); + if (err) goto fail_sysfs; return 0; fail_sysfs: + asus_sysfs_exit(asus); platform_device_del(asus->platform_device); fail_platform_device: platform_device_put(asus->platform_device); - return result; + return err; } static void asus_platform_exit(struct asus_laptop *asus) { - sysfs_remove_group(&asus->platform_device->dev.kobj, - &platform_attribute_group); + asus_sysfs_exit(asus); platform_device_unregister(asus->platform_device); } @@ -1272,40 +1310,6 @@ static struct platform_driver platform_driver = { } }; -static void asus_laptop_add_fs(struct asus_laptop *asus) -{ - ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); - - if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) - ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan); - - if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) - ASUS_SET_DEVICE_ATTR(bluetooth, 0644, - show_bluetooth, store_bluetooth); - - if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { - if (display_get_handle) - ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, - store_disp); - else - ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp); - } - - if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) - ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd); - - if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && - !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { - ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); - ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); - } - - if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && - !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && - !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) - ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); -} - static int asus_handle_init(char *name, acpi_handle * handle, char **paths, int num_paths) { @@ -1435,8 +1439,6 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) if (result) return result; - asus_laptop_add_fs(asus); - /* WLED and BLED are on by default */ if (bluetooth_status >= 0) asus_bluetooth_set(asus, !!bluetooth_status); -- cgit v1.2.3-70-g09d2 From 060cbce6c4431465e83907102e1903ecea366db5 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Thu, 28 Jan 2010 10:52:40 +0100 Subject: asus-laptop: fix style problems reported by checkpath.pl Signed-off-by: Corentin Chary --- drivers/platform/x86/asus-laptop.c | 94 +++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index d0d117b0cf79..791fcf321506 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -45,12 +45,12 @@ #include #include #include -#include -#include -#include +#include #include #include #include +#include +#include #define ASUS_LAPTOP_VERSION "0.42" @@ -94,10 +94,10 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " /* * Some events we use, same for all Asus */ -#define ATKD_BR_UP 0x10 // (event & ~ATKD_BR_UP) = brightness level -#define ATKD_BR_DOWN 0x20 // (event & ~ATKD_BR_DOWN) = britghness level +#define ATKD_BR_UP 0x10 /* (event & ~ATKD_BR_UP) = brightness level */ +#define ATKD_BR_DOWN 0x20 /* (event & ~ATKD_BR_DOWN) = britghness level */ #define ATKD_BR_MIN ATKD_BR_UP -#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) // 0x2f +#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) /* 0x2f */ #define ATKD_LCD_ON 0x33 #define ATKD_LCD_OFF 0x34 @@ -114,10 +114,6 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " #define WL_RSTS 0x01 /* internal Wifi */ #define BT_RSTS 0x02 /* internal Bluetooth */ -#define ASUS_HANDLE(object, paths...) \ - static acpi_handle object##_handle = NULL; \ - static char *object##_paths[] = { paths } - /* LED */ #define METHOD_MLED "MLED" #define METHOD_TLED "TLED" @@ -142,40 +138,44 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " #define METHOD_BRIGHTNESS_GET "GPLV" /* Backlight */ -ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ - "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */ - "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ - "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ - "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ - "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ - "\\_SB.PCI0.PX40.Q10", /* S1x */ - "\\Q10"); /* A2x, L2D, L3D, M2E */ +static acpi_handle lcd_switch_handle; +static const char *lcd_switch_paths[] = { + "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ + "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */ + "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ + "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ + "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ + "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ + "\\_SB.PCI0.PX40.Q10", /* S1x */ + "\\Q10"}; /* A2x, L2D, L3D, M2E */ /* Display */ #define METHOD_SWITCH_DISPLAY "SDSP" -ASUS_HANDLE(display_get, - /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ - "\\_SB.PCI0.P0P1.VGA.GETD", - /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ - "\\_SB.PCI0.P0P2.VGA.GETD", - /* A6V A6Q */ - "\\_SB.PCI0.P0P3.VGA.GETD", - /* A6T, A6M */ - "\\_SB.PCI0.P0PA.VGA.GETD", - /* L3C */ - "\\_SB.PCI0.PCI1.VGAC.NMAP", - /* Z96F */ - "\\_SB.PCI0.VGA.GETD", - /* A2D */ - "\\ACTD", - /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ - "\\ADVG", - /* P30 */ - "\\DNXT", - /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ - "\\INFB", - /* A3F A6F A3N A3L M6N W3N W6A */ - "\\SSTE"); + +static acpi_handle display_get_handle; +static const char *display_get_paths[] = { + /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ + "\\_SB.PCI0.P0P1.VGA.GETD", + /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ + "\\_SB.PCI0.P0P2.VGA.GETD", + /* A6V A6Q */ + "\\_SB.PCI0.P0P3.VGA.GETD", + /* A6T, A6M */ + "\\_SB.PCI0.P0PA.VGA.GETD", + /* L3C */ + "\\_SB.PCI0.PCI1.VGAC.NMAP", + /* Z96F */ + "\\_SB.PCI0.VGA.GETD", + /* A2D */ + "\\ACTD", + /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ + "\\ADVG", + /* P30 */ + "\\DNXT", + /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ + "\\INFB", + /* A3F A6F A3N A3L M6N W3N W6A */ + "\\SSTE"}; #define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */ #define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */ @@ -426,7 +426,7 @@ static void asus_kled_cdev_set(struct led_classdev *led_cdev, struct asus_led *led = container_of(led_cdev, struct asus_led, led); struct asus_laptop *asus = led->asus; - led->wk = value; + led->wk = value; queue_work(asus->led_workqueue, &led->work); } @@ -474,7 +474,7 @@ static int asus_led_register(struct asus_laptop *asus, struct led_classdev *led_cdev = &led->led; if (!method || acpi_check_handle(asus->handle, method, NULL)) - return 0; /* Led not present */ + return 0; /* Led not present */ led->asus = asus; led->method = method; @@ -687,8 +687,8 @@ static ssize_t show_infos(struct device *dev, acpi_status rv = AE_OK; /* - * We use the easy way, we don't care of off and count, so we don't set eof - * to 1 + * We use the easy way, we don't care of off and count, + * so we don't set eof to 1 */ len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n"); @@ -904,7 +904,7 @@ static int read_display(struct asus_laptop *asus) pr_warning("Error reading display status\n"); } - value &= 0x0F; /* needed for some models, shouldn't hurt others */ + value &= 0x0F; /* needed for some models, shouldn't hurt others */ return value; } @@ -1041,7 +1041,7 @@ static ssize_t show_gps(struct device *dev, static ssize_t store_gps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct asus_laptop *asus = dev_get_drvdata(dev); + struct asus_laptop *asus = dev_get_drvdata(dev); int rv, value; int ret; -- cgit v1.2.3-70-g09d2 From 94d8f785dd1f021c1971df73e6437f000c0d9449 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 1 Mar 2010 09:43:52 -0500 Subject: dell-laptop: Fix build error by making buffer_mutex static The following build bug (x86, allyesconfig): arch/x86/oprofile/built-in.o:(.data+0x250): multiple definition of `buffer_mutex' Was triggered in -tip testing, caused by this upstream commit: 116ee77: dell-laptop: Use buffer with 32-bit physical address There's multiple buffer_mutex's in the kernel. Make this new one static. Signed-off-by: Ingo Molnar --- drivers/platform/x86/dell-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index b7f4d2705916..29d96a4f5769 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -132,8 +132,8 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = { }; static struct calling_interface_buffer *buffer; -struct page *bufferpage; -DEFINE_MUTEX(buffer_mutex); +static struct page *bufferpage; +static DEFINE_MUTEX(buffer_mutex); static int hwswitch_state; -- cgit v1.2.3-70-g09d2 From 92e00e47b61f558009ff81be42b412a76fd89d84 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 1 Mar 2010 09:46:43 -0500 Subject: dell-laptop: Fix errors on failure and exit paths Make sure that work is cancelled after removing the i8042 filter, and unregister the platform device rather than deleting it. Signed-off-by: Matthew Garrett Cc: Dmitry Torokhov --- drivers/platform/x86/dell-laptop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 29d96a4f5769..ef614979afe9 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -580,6 +580,7 @@ static int __init dell_init(void) fail_backlight: i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); fail_filter: dell_cleanup_rfkill(); fail_rfkill: @@ -597,12 +598,12 @@ fail_platform_driver: static void __exit dell_exit(void) { - cancel_delayed_work_sync(&dell_rfkill_work); i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); backlight_device_unregister(dell_backlight_device); dell_cleanup_rfkill(); if (platform_device) { - platform_device_del(platform_device); + platform_device_unregister(platform_device); platform_driver_unregister(&platform_driver); } kfree(da_tokens); -- cgit v1.2.3-70-g09d2 From b466301b842f3a54e219b5cc587f22233ecb1345 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Mon, 1 Mar 2010 09:50:46 -0500 Subject: toshiba-acpi: fix multimedia keys on some machines Some Toshibas only send ACPI events on key down, not key release. Ignore any release events and send key down and key up events on every ACPI key down event. Signed-off-by: Frans Pop --- drivers/platform/x86/toshiba_acpi.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 26c211724acf..405b969734d6 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -814,21 +814,23 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) if (hci_result == HCI_SUCCESS) { if (value == 0x100) continue; - else if (value & 0x80) { - key = toshiba_acpi_get_entry_by_scancode - (value & ~0x80); - if (!key) { - printk(MY_INFO "Unknown key %x\n", - value & ~0x80); - continue; - } - input_report_key(toshiba_acpi.hotkey_dev, - key->keycode, 1); - input_sync(toshiba_acpi.hotkey_dev); - input_report_key(toshiba_acpi.hotkey_dev, - key->keycode, 0); - input_sync(toshiba_acpi.hotkey_dev); + /* act on key press; ignore key release */ + if (value & 0x80) + continue; + + key = toshiba_acpi_get_entry_by_scancode + (value); + if (!key) { + printk(MY_INFO "Unknown key %x\n", + value); + continue; } + input_report_key(toshiba_acpi.hotkey_dev, + key->keycode, 1); + input_sync(toshiba_acpi.hotkey_dev); + input_report_key(toshiba_acpi.hotkey_dev, + key->keycode, 0); + input_sync(toshiba_acpi.hotkey_dev); } else if (hci_result == HCI_NOT_SUPPORTED) { /* This is a workaround for an unresolved issue on * some machines where system events sporadically -- cgit v1.2.3-70-g09d2 From 6268f50df8c36e15e43ae2a10951b2cffd0ecfc4 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 1 Mar 2010 13:26:22 -0500 Subject: asus-acpi: remove duplicate comparison of asus_model strings These tests already occur elsewhere Signed-off-by: Roel Kluin Cc: Corentin Chary Cc: Karol Kozimor Cc: Len Brown Signed-off-by: Andrew Morton --- drivers/platform/x86/asus_acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index c1d2aeeea948..1381430e1105 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -1225,9 +1225,8 @@ static int asus_model_match(char *model) else if (strncmp(model, "M2N", 3) == 0 || strncmp(model, "M3N", 3) == 0 || strncmp(model, "M5N", 3) == 0 || - strncmp(model, "M6N", 3) == 0 || strncmp(model, "S1N", 3) == 0 || - strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0) + strncmp(model, "S5N", 3) == 0) return xxN; else if (strncmp(model, "M1", 2) == 0) return M1A; -- cgit v1.2.3-70-g09d2 From 881a6c25a8453388e3190de94a5e105439a9f806 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 1 Mar 2010 16:15:58 -0500 Subject: classmate-laptop: Added some keys present in other devices Some new devices have extra keys, which we add to our list. Currently, they all generate events that allow us to use a simple table/array, without need for the sparse keymap. Signed-off-by: Thadeu Lima de Souza Cascardo --- drivers/platform/x86/classmate-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 8cb20e45bad6..035a7dd65a3f 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -507,6 +507,10 @@ static int cmpc_keys_codes[] = { KEY_BRIGHTNESSDOWN, KEY_BRIGHTNESSUP, KEY_VENDOR, + KEY_UNKNOWN, + KEY_CAMERA, + KEY_BACK, + KEY_FORWARD, KEY_MAX }; -- cgit v1.2.3-70-g09d2 From 51c1410bd651609aafbcc3a2294df26a47bf6137 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 2 Mar 2010 09:53:45 -0500 Subject: compal-laptop: Make it depend on CONFIG_RFKILL -tip testing found this build failure (x86 randconfig): drivers/built-in.o: In function `setup_rfkill': compal-laptop.c:(.text+0x36abe8): undefined reference to `rfkill_alloc' compal-laptop.c:(.text+0x36abfc): undefined reference to `rfkill_register' compal-laptop.c:(.text+0x36ac30): undefined reference to `rfkill_alloc' compal-laptop.c:(.text+0x36ac44): undefined reference to `rfkill_register' Which can happen with CONFIG_COMPAL_LAPTOP=y but COMPAL_LAPTOP=m. Signed-off-by: Ingo Molnar --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 92161c7ff4b7..cd2ee6fce1b4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -179,6 +179,7 @@ config COMPAL_LAPTOP tristate "Compal Laptop Extras" depends on ACPI depends on BACKLIGHT_CLASS_DEVICE + depends on RFKILL ---help--- This is a driver for laptops built by Compal: -- cgit v1.2.3-70-g09d2 From ea79632d90754409b11388410bbe23b62394401d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 4 Feb 2010 20:56:52 +0100 Subject: x86: move hp-wmi's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to hp_wmi_bios_setup is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Frans Pop Cc: Larry Finger Cc: Len Brown Cc: Helge Deller Cc: Andrew Morton Acked-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/hp-wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 3aa57da8b43b..7ccf33c08967 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -57,7 +57,7 @@ enum hp_wmi_radio { HPWMI_WWAN = 2, }; -static int __init hp_wmi_bios_setup(struct platform_device *device); +static int __devinit hp_wmi_bios_setup(struct platform_device *device); static int __exit hp_wmi_bios_remove(struct platform_device *device); static int hp_wmi_resume_handler(struct device *device); @@ -447,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_tablet); } -static int __init hp_wmi_bios_setup(struct platform_device *device) +static int __devinit hp_wmi_bios_setup(struct platform_device *device) { int err; int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); -- cgit v1.2.3-70-g09d2 From 46d0e9e091ba5dd29cac7543e97084540da9c4b7 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Sat, 9 Jan 2010 21:16:52 +0800 Subject: msi-laptop: Support standard ec 66/62 command on MSI notebook and nebook Suppport standard ec 66/62 command on MSI notebook and nebook. MSI netbook and notebook already support 66/62 command, so, add new get_state function, and put the old model to non-standard model, but driver still support those old model. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 43 +++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 759763d18e4c..323e99460c9f 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -66,6 +66,11 @@ #define MSI_EC_COMMAND_WIRELESS 0x10 #define MSI_EC_COMMAND_LCD_LEVEL 0x11 +#define MSI_STANDARD_EC_COMMAND_ADDRESS 0x2e +#define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0) +#define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1) +#define MSI_STANDARD_EC_WLAN_MASK (1 << 3) + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -74,6 +79,9 @@ static int auto_brightness; module_param(auto_brightness, int, 0); MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); +static bool old_ec_model; +static int wlan_s, bluetooth_s; + /* Hardware access */ static int set_lcd_level(int level) @@ -148,6 +156,22 @@ static int get_wireless_state(int *wlan, int *bluetooth) return 0; } +static int get_wireless_state_ec_standard(void) +{ + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); + if (result < 0) + return -1; + + wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK); + + bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK); + + return 0; +} + /* Backlight device stuff */ static int bl_get_brightness(struct backlight_device *b) @@ -176,7 +200,12 @@ static ssize_t show_wlan(struct device *dev, int ret, enabled; - ret = get_wireless_state(&enabled, NULL); + if (old_ec_model) { + ret = get_wireless_state(&enabled, NULL); + } else { + ret = get_wireless_state_ec_standard(); + enabled = wlan_s; + } if (ret < 0) return ret; @@ -189,7 +218,12 @@ static ssize_t show_bluetooth(struct device *dev, int ret, enabled; - ret = get_wireless_state(NULL, &enabled); + if (old_ec_model) { + ret = get_wireless_state(NULL, &enabled); + } else { + ret = get_wireless_state_ec_standard(); + enabled = bluetooth_s; + } if (ret < 0) return ret; @@ -339,8 +373,8 @@ static int __init msi_init(void) if (acpi_disabled) return -ENODEV; - if (!force && !dmi_check_system(msi_dmi_table)) - return -ENODEV; + if (force || dmi_check_system(msi_dmi_table)) + old_ec_model = 1; if (auto_brightness < 0 || auto_brightness > 2) return -EINVAL; @@ -435,3 +469,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARIN MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); +MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*"); -- cgit v1.2.3-70-g09d2 From fc0dc4c926e6b7afe680aecf809f48eef3faa182 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Sat, 9 Jan 2010 23:17:07 +0800 Subject: msi-laptop: Add threeg sysfs file for support query 3G state by standard 66/62 ec command Add threeg sysfs file for support query 3G state by standard 66/62 ec command, the MSI standard ec interface supported this feature. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 323e99460c9f..1784d5588d41 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -70,6 +70,7 @@ #define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0) #define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1) #define MSI_STANDARD_EC_WLAN_MASK (1 << 3) +#define MSI_STANDARD_EC_3G_MASK (1 << 4) static int force; module_param(force, bool, 0); @@ -80,7 +81,7 @@ module_param(auto_brightness, int, 0); MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); static bool old_ec_model; -static int wlan_s, bluetooth_s; +static int wlan_s, bluetooth_s, threeg_s; /* Hardware access */ @@ -169,6 +170,8 @@ static int get_wireless_state_ec_standard(void) bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK); + threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK); + return 0; } @@ -230,6 +233,23 @@ static ssize_t show_bluetooth(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t show_threeg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + int ret; + + /* old msi ec not support 3G */ + if (old_ec_model) + return -1; + + ret = get_wireless_state_ec_standard(); + if (ret < 0) + return ret; + + return sprintf(buf, "%i\n", threeg_s); +} + static ssize_t show_lcd_level(struct device *dev, struct device_attribute *attr, char *buf) { @@ -292,6 +312,7 @@ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); +static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); static struct attribute *msipf_attributes[] = { &dev_attr_lcd_level.attr, @@ -412,6 +433,12 @@ static int __init msi_init(void) if (ret) goto fail_platform_device2; + if (!old_ec_model) { + ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); + if (ret) + goto fail_platform_device2; + } + /* Disable automatic brightness control by default because * this module was probably loaded to do brightness control in * software. */ @@ -446,6 +473,8 @@ static void __exit msi_cleanup(void) { sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); + if (!old_ec_model) + device_remove_file(&msipf_device->dev, &dev_attr_threeg); platform_device_unregister(msipf_device); platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); -- cgit v1.2.3-70-g09d2 From 472ea12d1a265c868e1605abb59bf21f595eedfc Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Fri, 22 Jan 2010 00:15:59 +0800 Subject: msi-laptop: Support some MSI 3G netbook that is need load SCM Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, those netbook will load the SCM (windows app) to disable the original Wlan/Bluetooth control by BIOS when user press fn key, then control Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user cann't on/off 3G module on those 3G netbook. On Linux, msi-laptop driver will do the same thing to disable the original BIOS control, then might need use HAL or other userland application to do the software control that simulate with SCM. e.g. MSI N034 netbook Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 238 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 1784d5588d41..ff21d1acf3be 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -58,6 +58,7 @@ #include #include #include +#include #define MSI_DRIVER_VERSION "0.5" @@ -72,6 +73,10 @@ #define MSI_STANDARD_EC_WLAN_MASK (1 << 3) #define MSI_STANDARD_EC_3G_MASK (1 << 4) +/* For set SCM load flag to disable BIOS fn key */ +#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d +#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -83,6 +88,19 @@ MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disab static bool old_ec_model; static int wlan_s, bluetooth_s, threeg_s; +/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, + * those netbook will load the SCM (windows app) to disable the original + * Wlan/Bluetooth control by BIOS when user press fn key, then control + * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user + * cann't on/off 3G module on those 3G netbook. + * On Linux, msi-laptop driver will do the same thing to disable the + * original BIOS control, then might need use HAL or other userland + * application to do the software control that simulate with SCM. + * e.g. MSI N034 netbook + */ +static bool load_scm_model; +static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg; + /* Hardware access */ static int set_lcd_level(int level) @@ -139,6 +157,35 @@ static int set_auto_brightness(int enable) return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); } +static ssize_t set_device_state(const char *buf, size_t count, u8 mask) +{ + int status; + u8 wdata = 0, rdata; + int result; + + if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1)) + return -EINVAL; + + /* read current device state */ + result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); + if (result < 0) + return -EINVAL; + + if (!!(rdata & mask) != status) { + /* reverse device bit */ + if (rdata & mask) + wdata = rdata & ~mask; + else + wdata = rdata | mask; + + result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata); + if (result < 0) + return -EINVAL; + } + + return count; +} + static int get_wireless_state(int *wlan, int *bluetooth) { u8 wdata = 0, rdata; @@ -215,6 +262,12 @@ static ssize_t show_wlan(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t store_wlan(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK); +} + static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf) { @@ -233,6 +286,12 @@ static ssize_t show_bluetooth(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t store_bluetooth(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK); +} + static ssize_t show_threeg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -250,6 +309,12 @@ static ssize_t show_threeg(struct device *dev, return sprintf(buf, "%i\n", threeg_s); } +static ssize_t store_threeg(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK); +} + static ssize_t show_lcd_level(struct device *dev, struct device_attribute *attr, char *buf) { @@ -387,6 +452,169 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { { } }; +static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { + { + .ident = "MSI N034", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "MICRO-STAR INTERNATIONAL CO., LTD"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"), + DMI_MATCH(DMI_CHASSIS_VENDOR, + "MICRO-STAR INTERNATIONAL CO., LTD") + }, + .callback = dmi_check_cb + }, + { } +}; + +static int rfkill_bluetooth_set(void *data, bool blocked) +{ + /* Do something with blocked...*/ + /* + * blocked == false is on + * blocked == true is off + */ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); + + return 0; +} + +static int rfkill_wlan_set(void *data, bool blocked) +{ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK); + + return 0; +} + +static int rfkill_threeg_set(void *data, bool blocked) +{ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK); + + return 0; +} + +static struct rfkill_ops rfkill_bluetooth_ops = { + .set_block = rfkill_bluetooth_set +}; + +static struct rfkill_ops rfkill_wlan_ops = { + .set_block = rfkill_wlan_set +}; + +static struct rfkill_ops rfkill_threeg_ops = { + .set_block = rfkill_threeg_set +}; + +static void rfkill_cleanup(void) +{ + if (rfk_bluetooth) { + rfkill_unregister(rfk_bluetooth); + rfkill_destroy(rfk_bluetooth); + } + + if (rfk_threeg) { + rfkill_unregister(rfk_threeg); + rfkill_destroy(rfk_threeg); + } + + if (rfk_wlan) { + rfkill_unregister(rfk_wlan); + rfkill_destroy(rfk_wlan); + } +} + +static int rfkill_init(struct platform_device *sdev) +{ + /* add rfkill */ + int retval; + + rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev, + RFKILL_TYPE_BLUETOOTH, + &rfkill_bluetooth_ops, NULL); + if (!rfk_bluetooth) { + retval = -ENOMEM; + goto err_bluetooth; + } + retval = rfkill_register(rfk_bluetooth); + if (retval) + goto err_bluetooth; + + rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN, + &rfkill_wlan_ops, NULL); + if (!rfk_wlan) { + retval = -ENOMEM; + goto err_wlan; + } + retval = rfkill_register(rfk_wlan); + if (retval) + goto err_wlan; + + rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN, + &rfkill_threeg_ops, NULL); + if (!rfk_threeg) { + retval = -ENOMEM; + goto err_threeg; + } + retval = rfkill_register(rfk_threeg); + if (retval) + goto err_threeg; + + return 0; + +err_threeg: + rfkill_destroy(rfk_threeg); + if (rfk_wlan) + rfkill_unregister(rfk_wlan); +err_wlan: + rfkill_destroy(rfk_wlan); + if (rfk_bluetooth) + rfkill_unregister(rfk_bluetooth); +err_bluetooth: + rfkill_destroy(rfk_bluetooth); + + return retval; +} + +static int load_scm_model_init(struct platform_device *sdev) +{ + u8 data; + int result; + + /* allow userland write sysfs file */ + dev_attr_bluetooth.store = store_bluetooth; + dev_attr_wlan.store = store_wlan; + dev_attr_threeg.store = store_threeg; + dev_attr_bluetooth.attr.mode |= S_IWUSR; + dev_attr_wlan.attr.mode |= S_IWUSR; + dev_attr_threeg.attr.mode |= S_IWUSR; + + /* disable hardware control by fn key */ + result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); + if (result < 0) + return result; + + result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, + data | MSI_STANDARD_EC_SCM_LOAD_MASK); + if (result < 0) + return result; + + /* initial rfkill */ + result = rfkill_init(sdev); + if (result < 0) + return result; + + return 0; +} + static int __init msi_init(void) { int ret; @@ -397,6 +625,9 @@ static int __init msi_init(void) if (force || dmi_check_system(msi_dmi_table)) old_ec_model = 1; + if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) + load_scm_model = 1; + if (auto_brightness < 0 || auto_brightness > 2) return -EINVAL; @@ -429,6 +660,11 @@ static int __init msi_init(void) if (ret) goto fail_platform_device1; + if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) { + ret = -EINVAL; + goto fail_platform_device1; + } + ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); if (ret) goto fail_platform_device2; @@ -479,6 +715,8 @@ static void __exit msi_cleanup(void) platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); + rfkill_cleanup(); + /* Enable automatic brightness control again */ if (auto_brightness != 2) set_auto_brightness(1); -- cgit v1.2.3-70-g09d2 From ec766278ba927f3d3c75211ea7697aae37f327f0 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Wed, 27 Jan 2010 00:13:45 +0800 Subject: msi-laptop: Add resume method for set the SCM load again Implement the resume method for set the load SCM flag after system reusme. Without this patch, the wifi function key on SCM model will back to BIOS control mode then confuse with the userland software control. e.g. MSI N034 Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index ff21d1acf3be..af1b62f76117 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -77,6 +77,8 @@ #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) +static int msi_laptop_resume(struct platform_device *device); + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -395,7 +397,8 @@ static struct platform_driver msipf_driver = { .driver = { .name = "msi-laptop-pf", .owner = THIS_MODULE, - } + }, + .resume = msi_laptop_resume, }; static struct platform_device *msipf_device; @@ -584,6 +587,27 @@ err_bluetooth: return retval; } +static int msi_laptop_resume(struct platform_device *device) +{ + u8 data; + int result; + + if (!load_scm_model) + return 0; + + /* set load SCM to disable hardware control by fn key */ + result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); + if (result < 0) + return result; + + result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, + data | MSI_STANDARD_EC_SCM_LOAD_MASK); + if (result < 0) + return result; + + return 0; +} + static int load_scm_model_init(struct platform_device *sdev) { u8 data; -- cgit v1.2.3-70-g09d2 From e22388e71b8787b26dc33d023e5c1eec58865541 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Wed, 27 Jan 2010 12:23:00 +0800 Subject: msi-laptop: Detect 3G device exists by standard ec command Detect 3G device exists by standard ec command. Driver will not create the threeg sysfs file and threeg rfkill interface if there have no internal 3G device in MSI notebook/netbook. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 44 ++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index af1b62f76117..c2b05da4289a 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -79,6 +79,8 @@ static int msi_laptop_resume(struct platform_device *device); +#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -89,6 +91,7 @@ MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disab static bool old_ec_model; static int wlan_s, bluetooth_s, threeg_s; +static int threeg_exists; /* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, * those netbook will load the SCM (windows app) to disable the original @@ -224,6 +227,20 @@ static int get_wireless_state_ec_standard(void) return 0; } +static int get_threeg_exists(void) +{ + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata); + if (result < 0) + return -1; + + threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK); + + return 0; +} + /* Backlight device stuff */ static int bl_get_brightness(struct backlight_device *b) @@ -561,15 +578,17 @@ static int rfkill_init(struct platform_device *sdev) if (retval) goto err_wlan; - rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN, - &rfkill_threeg_ops, NULL); - if (!rfk_threeg) { - retval = -ENOMEM; - goto err_threeg; + if (threeg_exists) { + rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, + RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL); + if (!rfk_threeg) { + retval = -ENOMEM; + goto err_threeg; + } + retval = rfkill_register(rfk_threeg); + if (retval) + goto err_threeg; } - retval = rfkill_register(rfk_threeg); - if (retval) - goto err_threeg; return 0; @@ -649,6 +668,9 @@ static int __init msi_init(void) if (force || dmi_check_system(msi_dmi_table)) old_ec_model = 1; + if (!old_ec_model) + get_threeg_exists(); + if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) load_scm_model = 1; @@ -694,7 +716,9 @@ static int __init msi_init(void) goto fail_platform_device2; if (!old_ec_model) { - ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); + if (threeg_exists) + ret = device_create_file(&msipf_device->dev, + &dev_attr_threeg); if (ret) goto fail_platform_device2; } @@ -733,7 +757,7 @@ static void __exit msi_cleanup(void) { sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); - if (!old_ec_model) + if (!old_ec_model && threeg_exists) device_remove_file(&msipf_device->dev, &dev_attr_threeg); platform_device_unregister(msipf_device); platform_driver_unregister(&msipf_driver); -- cgit v1.2.3-70-g09d2 From 410c17651998944630a95fbb286a50362de2dbb0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 3 Feb 2010 14:24:28 -0800 Subject: msi-laptop: depends on RFKILL msi-laptop uses rfkill*() interfaces so it should depend on RFKILL. msi-laptop.c:(.text+0x1fcd1b): undefined reference to `rfkill_alloc' msi-laptop.c:(.text+0x1fcd76): undefined reference to `rfkill_register' msi-laptop.c:(.text+0x1fcdc8): undefined reference to `rfkill_destroy' msi-laptop.c:(.text+0x1fcdd9): undefined reference to `rfkill_unregister' This repairs "msi-laptop: Detect 3G device exists by standard ec command", which is in some gregkh tree. Signed-off-by: Randy Dunlap Cc: Lennart Poettering Cc: Lee, Chun-Yi Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index cd2ee6fce1b4..e631dbeafd79 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -150,6 +150,7 @@ config MSI_LAPTOP tristate "MSI Laptop Extras" depends on ACPI depends on BACKLIGHT_CLASS_DEVICE + depends on RFKILL ---help--- This is a driver for laptops built by MSI (MICRO-STAR INTERNATIONAL): -- cgit v1.2.3-70-g09d2 From 58b939959d228681208ba997595411fddc860849 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 8 Mar 2010 22:37:10 -0800 Subject: Input: scancode in get/set_keycodes should be unsigned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HID layer has some scan codes of the form 0xffbc0000 for logitech devices which do not work if scancode is typed as signed int, so we need to switch to unsigned it instead. While at it keycode being signed does not make much sense either. Acked-by: Márton Németh Acked-by: Matthew Garrett Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-input.c | 24 ++++++++++++------------ drivers/input/evdev.c | 2 +- drivers/input/input.c | 20 +++++++++----------- drivers/input/misc/ati_remote2.c | 14 +++++++------- drivers/input/misc/winbond-cir.c | 12 +++++------- drivers/input/sparse-keymap.c | 6 ++++-- drivers/media/IR/ir-keytable.c | 4 ++-- drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 4 ++-- drivers/platform/x86/dell-wmi.c | 16 +++++++--------- drivers/platform/x86/hp-wmi.c | 15 +++++++-------- drivers/platform/x86/panasonic-laptop.c | 15 +++++++-------- drivers/platform/x86/topstar-laptop.c | 13 ++++++------- drivers/platform/x86/toshiba_acpi.c | 17 +++++++---------- include/linux/input.h | 20 ++++++++++++-------- 14 files changed, 88 insertions(+), 94 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 79d9edd0bdfa..7a0d2e4661a1 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -68,22 +68,25 @@ static const struct { #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ &max, EV_KEY, (c)) -static inline int match_scancode(int code, int scancode) +static inline int match_scancode(unsigned int code, unsigned int scancode) { if (scancode == 0) return 1; - return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); + + return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode; } -static inline int match_keycode(int code, int keycode) +static inline int match_keycode(unsigned int code, unsigned int keycode) { if (keycode == 0) return 1; - return (code == keycode); + + return code == keycode; } static struct hid_usage *hidinput_find_key(struct hid_device *hid, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int i, j, k; struct hid_report *report; @@ -105,8 +108,8 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, return NULL; } -static int hidinput_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int hidinput_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; @@ -119,16 +122,13 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int hidinput_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int hidinput_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - usage = hidinput_find_key(hid, scancode, 0); if (usage) { old_keycode = usage->code; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9f9816baeb97..2ee6c7a68bdc 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -515,7 +515,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct input_absinfo abs; struct ff_effect effect; int __user *ip = (int __user *)p; - int i, t, u, v; + unsigned int i, t, u, v; int error; switch (cmd) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 41168d5f8c17..e2dd8858e19d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -582,7 +582,8 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) } static int input_default_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { if (!dev->keycodesize) return -EINVAL; @@ -596,7 +597,8 @@ static int input_default_getkeycode(struct input_dev *dev, } static int input_default_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int old_keycode; int i; @@ -654,11 +656,9 @@ static int input_default_setkeycode(struct input_dev *dev, * This function should be called by anyone interested in retrieving current * keymap. Presently keyboard and evdev handlers use it. */ -int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) +int input_get_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { - if (scancode < 0) - return -EINVAL; - return dev->getkeycode(dev, scancode, keycode); } EXPORT_SYMBOL(input_get_keycode); @@ -672,16 +672,14 @@ EXPORT_SYMBOL(input_get_keycode); * This function should be called by anyone needing to update current * keymap. Presently keyboard and evdev handlers use it. */ -int input_set_keycode(struct input_dev *dev, int scancode, int keycode) +int input_set_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { unsigned long flags; int old_keycode; int retval; - if (scancode < 0) - return -EINVAL; - - if (keycode < 0 || keycode > KEY_MAX) + if (keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0501f0e65157..15be5430bc6d 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -474,10 +474,11 @@ static void ati_remote2_complete_key(struct urb *urb) } static int ati_remote2_getkeycode(struct input_dev *idev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode; + unsigned int mode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -491,10 +492,12 @@ static int ati_remote2_getkeycode(struct input_dev *idev, return 0; } -static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) +static int ati_remote2_setkeycode(struct input_dev *idev, + unsigned int scancode, unsigned int keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode, old_keycode; + unsigned int mode, old_keycode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -504,9 +507,6 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc if (index < 0) return -EINVAL; - if (keycode < KEY_RESERVED || keycode > KEY_MAX) - return -EINVAL; - old_keycode = ar2->keycode[mode][index]; ar2->keycode[mode][index] = keycode; __set_bit(keycode, idev->keybit); diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index cbec3dfdd42b..9c155a43abc2 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -385,26 +385,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) } static int -wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) +wbcir_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct wbcir_data *data = input_get_drvdata(dev); - *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); + *keycode = wbcir_do_getkeycode(data, scancode); return 0; } static int -wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) +wbcir_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct wbcir_data *data = input_get_drvdata(dev); struct wbcir_keyentry *keyentry; struct wbcir_keyentry *new_keyentry; unsigned long flags; unsigned int old_keycode = KEY_RESERVED; - u32 scancode = (u32)sscancode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); if (!new_keyentry) diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index fbd3987af57f..e6bde55e5203 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -64,7 +64,8 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); static int sparse_keymap_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { const struct key_entry *key = sparse_keymap_entry_from_scancode(dev, scancode); @@ -78,7 +79,8 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, } static int sparse_keymap_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { struct key_entry *key; int old_keycode; diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 0903f539bf68..0a3b4ed38e48 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -123,7 +123,7 @@ static int ir_copy_table(struct ir_scancode_table *destin, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { int elem; struct ir_input_dev *ir_dev = input_get_drvdata(dev); @@ -291,7 +291,7 @@ static int ir_insert_key(struct ir_scancode_table *rc_tab, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { int rc = 0; struct ir_input_dev *ir_dev = input_get_drvdata(dev); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index a03ef7efec9a..852fe89539cf 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -9,7 +9,7 @@ #include static int dvb_usb_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); @@ -39,7 +39,7 @@ static int dvb_usb_getkeycode(struct input_dev *dev, } static int dvb_usb_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 1b1dddbd5744..bed764e3ea2a 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -142,7 +142,7 @@ static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap; static struct input_dev *dell_wmi_input_dev; -static struct key_entry *dell_wmi_get_entry_by_scancode(int code) +static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -153,7 +153,7 @@ static struct key_entry *dell_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -164,8 +164,8 @@ static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int dell_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode); @@ -177,13 +177,11 @@ static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int dell_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = dell_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 7ccf33c08967..56086363becc 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -278,7 +278,7 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); -static struct key_entry *hp_wmi_get_entry_by_scancode(int code) +static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -289,7 +289,7 @@ static struct key_entry *hp_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -300,7 +300,8 @@ static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int hp_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); @@ -312,13 +313,11 @@ static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) return -EINVAL; } -static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int hp_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = hp_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index fe7cf0188acc..c9fc479fc290 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -200,7 +200,7 @@ static struct acpi_driver acpi_pcc_driver = { }; #define KEYMAP_SIZE 11 -static const int initial_keymap[KEYMAP_SIZE] = { +static const unsigned int initial_keymap[KEYMAP_SIZE] = { /* 0 */ KEY_RESERVED, /* 1 */ KEY_BRIGHTNESSDOWN, /* 2 */ KEY_BRIGHTNESSUP, @@ -222,7 +222,7 @@ struct pcc_acpi { struct acpi_device *device; struct input_dev *input_dev; struct backlight_device *backlight; - int keymap[KEYMAP_SIZE]; + unsigned int keymap[KEYMAP_SIZE]; }; struct pcc_keyinput { @@ -445,7 +445,8 @@ static struct attribute_group pcc_attr_group = { /* hotkey input device driver */ -static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int pcc_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); @@ -457,7 +458,7 @@ static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) +static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode) { int i; @@ -469,7 +470,8 @@ static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) return 0; } -static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int pcc_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); int oldkeycode; @@ -477,9 +479,6 @@ static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) if (scancode >= ARRAY_SIZE(pcc->keymap)) return -EINVAL; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - oldkeycode = pcc->keymap[scancode]; pcc->keymap[scancode] = keycode; diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 02f3d4e9e666..4d6516fded7e 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -46,7 +46,7 @@ static struct tps_key_entry topstar_keymap[] = { { } }; -static struct tps_key_entry *tps_get_key_by_scancode(int code) +static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code) { struct tps_key_entry *key; @@ -57,7 +57,7 @@ static struct tps_key_entry *tps_get_key_by_scancode(int code) return NULL; } -static struct tps_key_entry *tps_get_key_by_keycode(int code) +static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code) { struct tps_key_entry *key; @@ -126,7 +126,8 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) return 0; } -static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int topstar_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct tps_key_entry *key = tps_get_key_by_scancode(scancode); @@ -137,14 +138,12 @@ static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int topstar_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct tps_key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - key = tps_get_key_by_scancode(scancode); if (!key) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 405b969734d6..789240d1b577 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -745,7 +745,7 @@ static struct backlight_ops toshiba_backlight_data = { .update_status = set_lcd_status, }; -static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -756,7 +756,7 @@ static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code) { struct key_entry *key; @@ -767,8 +767,8 @@ static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) return NULL; } -static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int toshiba_acpi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); @@ -780,14 +780,11 @@ static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int toshiba_acpi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = toshiba_acpi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/include/linux/input.h b/include/linux/input.h index dc24effb6d0e..7ed2251b33f1 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -58,10 +58,10 @@ struct input_absinfo { #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ -#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */ -#define EVIOCSREP _IOW('E', 0x03, int[2]) /* set repeat settings */ -#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */ -#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */ +#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ +#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */ +#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */ +#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */ #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ @@ -1142,8 +1142,10 @@ struct input_dev { unsigned int keycodemax; unsigned int keycodesize; void *keycode; - int (*setkeycode)(struct input_dev *dev, int scancode, int keycode); - int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode); + int (*setkeycode)(struct input_dev *dev, + unsigned int scancode, unsigned int keycode); + int (*getkeycode)(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode); struct ff_device *ff; @@ -1415,8 +1417,10 @@ static inline void input_set_abs_params(struct input_dev *dev, int axis, int min dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); } -int input_get_keycode(struct input_dev *dev, int scancode, int *keycode); -int input_set_keycode(struct input_dev *dev, int scancode, int keycode); +int input_get_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode); +int input_set_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode); extern struct class input_class; -- cgit v1.2.3-70-g09d2