From c1bc97f8f498a2bfab63ceef761fb0e88ef7c065 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 28 Apr 2014 20:50:56 +0100 Subject: goldfish bus: don't call request_mem_region This is a bug fix that has been lurking in the Google tree but not pushed upstream. From: Octavian Purdila The memory region is already reserved in goldfish_init() during platform init. Signed-off-by: Octavian Purdila Signed-off-by: Jun Tian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/pdev_bus.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c index 92cc4cfafde5..4eb2bb34790d 100644 --- a/drivers/platform/goldfish/pdev_bus.c +++ b/drivers/platform/goldfish/pdev_bus.c @@ -184,11 +184,6 @@ static int goldfish_pdev_bus_probe(struct platform_device *pdev) pdev_bus_addr = r->start; pdev_bus_len = resource_size(r); - if (request_mem_region(pdev_bus_addr, pdev_bus_len, "goldfish")) { - dev_err(&pdev->dev, "unable to reserve Goldfish MMIO.\n"); - return -EBUSY; - } - pdev_bus_base = ioremap(pdev_bus_addr, pdev_bus_len); if (pdev_bus_base == NULL) { ret = -ENOMEM; -- cgit From 49a75c444fcf07fdde2ec74428b6b1b9ff1c6b15 Mon Sep 17 00:00:00 2001 From: Jun Tian Date: Mon, 12 May 2014 16:54:46 +0100 Subject: goldfish: 64-bit pipe driver for goldfish platform Support 64-bit channel and address for the goldfish pipe driver. Signed-off-by: Jun Tian Signed-off-by: Octavian Purdila Signed-off-by: Brian Wood Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 35 +++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 4f5aa831f549..f33c6e0e7fb0 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -66,8 +66,14 @@ #define PIPE_REG_COMMAND 0x00 /* write: value = command */ #define PIPE_REG_STATUS 0x04 /* read */ #define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */ +#ifdef CONFIG_64BIT +#define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */ +#endif #define PIPE_REG_SIZE 0x0c /* read/write: buffer size */ #define PIPE_REG_ADDRESS 0x10 /* write: physical address */ +#ifdef CONFIG_64BIT +#define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */ +#endif #define PIPE_REG_WAKES 0x14 /* read: wake flags */ #define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ #define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ @@ -109,9 +115,9 @@ #define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ struct access_params { - u32 channel; + unsigned long channel; u32 size; - u32 address; + unsigned long address; u32 cmd; u32 result; /* reserved for future extension */ @@ -155,7 +161,10 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - writel((u32)pipe, dev->base + PIPE_REG_CHANNEL); + writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); +#ifdef CONFIG_64BIT + writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); +#endif writel(cmd, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); spin_unlock_irqrestore(&dev->lock, flags); @@ -168,7 +177,10 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - writel((u32)pipe, dev->base + PIPE_REG_CHANNEL); + writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); +#ifdef CONFIG_64BIT + writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); +#endif writel(cmd, dev->base + PIPE_REG_COMMAND); spin_unlock_irqrestore(&dev->lock, flags); } @@ -322,9 +334,15 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, spin_lock_irqsave(&dev->lock, irq_flags); if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, address, avail, pipe, &status)) { - writel((u32)pipe, dev->base + PIPE_REG_CHANNEL); + writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); +#ifdef CONFIG_64BIT + writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); +#endif writel(avail, dev->base + PIPE_REG_SIZE); writel(address, dev->base + PIPE_REG_ADDRESS); +#ifdef CONFIG_64BIT + writel((u32)((u64)address >> 32), dev->base + PIPE_REG_ADDRESS_HIGH); +#endif writel(CMD_WRITE_BUFFER + cmd_offset, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); @@ -447,7 +465,12 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) /* First read the channel, 0 means the end of the list */ struct goldfish_pipe *pipe; unsigned long wakes; - unsigned long channel = readl(dev->base + PIPE_REG_CHANNEL); + unsigned long channel = 0; + +#ifdef CONFIG_64BIT + channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32; +#endif + channel |= readl(dev->base + PIPE_REG_CHANNEL); if (channel == 0) break; -- cgit From 25c72c786cb571cfdf39a31f9f64d143d8623a7a Mon Sep 17 00:00:00 2001 From: Jun Tian Date: Mon, 12 May 2014 16:54:57 +0100 Subject: goldfish: fix kernel panic when using multiple adb connection When using multiple adb on 64 bit kernel to transfer data, the goldfish pipe interrupt will crash the kernel. Signed-off-by: Jun Tian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index f33c6e0e7fb0..670b9b94f74b 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -469,6 +469,9 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) #ifdef CONFIG_64BIT channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32; + + if (channel == 0) + break; #endif channel |= readl(dev->base + PIPE_REG_CHANNEL); -- cgit From f10d8434201859d5ad7f51032dcd2d0c09e85ee2 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 12 May 2014 16:55:05 +0100 Subject: goldfish: add support for 64bit to the virtual bus This patchs adds a new register to pass the upper 32bits for the device name address when running in 64bit mode. Signed-off-by: Octavian Purdila Signed-off-by: Jun Tian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/pdev_bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c index 4eb2bb34790d..eb254400c44a 100644 --- a/drivers/platform/goldfish/pdev_bus.c +++ b/drivers/platform/goldfish/pdev_bus.c @@ -36,6 +36,7 @@ #define PDEV_BUS_IO_SIZE (0x14) #define PDEV_BUS_IRQ (0x18) #define PDEV_BUS_IRQ_COUNT (0x1c) +#define PDEV_BUS_GET_NAME_HIGH (0x20) struct pdev_bus_dev { struct list_head list; @@ -129,7 +130,10 @@ static int goldfish_new_pdev(void) dev->pdev.dev.dma_mask = (void *)(dev->pdev.name + name_len + 1); *dev->pdev.dev.dma_mask = ~0; - writel((unsigned long)name, pdev_bus_base + PDEV_BUS_GET_NAME); +#ifdef CONFIG_64BIT + writel((u32)((u64)name>>32), pdev_bus_base + PDEV_BUS_GET_NAME_HIGH); +#endif + writel((u32)(u64)name, pdev_bus_base + PDEV_BUS_GET_NAME); name[name_len] = '\0'; dev->pdev.id = readl(pdev_bus_base + PDEV_BUS_ID); dev->pdev.resource[0].start = base; -- cgit From a99698facdb92adebf4a4ed7691493b7e08ff5b6 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 12 May 2014 16:57:22 +0100 Subject: goldfish: clean up the pipe driver 64bit ifdefs Use the 64bit helper method to scrub most of the ifdefs from the driver. The pipe reading has a funny case we can't scrub completely. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 33 +++++++++++-------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 670b9b94f74b..c86180bba72e 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -56,6 +56,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -66,14 +67,10 @@ #define PIPE_REG_COMMAND 0x00 /* write: value = command */ #define PIPE_REG_STATUS 0x04 /* read */ #define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */ -#ifdef CONFIG_64BIT #define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */ -#endif #define PIPE_REG_SIZE 0x0c /* read/write: buffer size */ #define PIPE_REG_ADDRESS 0x10 /* write: physical address */ -#ifdef CONFIG_64BIT #define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */ -#endif #define PIPE_REG_WAKES 0x14 /* read: wake flags */ #define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ #define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ @@ -155,16 +152,14 @@ enum { static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) -{ +{ unsigned long flags; u32 status; struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); -#ifdef CONFIG_64BIT - writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); -#endif + gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, + dev->base + PIPE_REG_CHANNEL_HIGH); writel(cmd, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); spin_unlock_irqrestore(&dev->lock, flags); @@ -172,15 +167,13 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) } static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) -{ +{ unsigned long flags; struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); -#ifdef CONFIG_64BIT - writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); -#endif + gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, + dev->base + PIPE_REG_CHANNEL_HIGH); writel(cmd, dev->base + PIPE_REG_COMMAND); spin_unlock_irqrestore(&dev->lock, flags); } @@ -334,15 +327,11 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, spin_lock_irqsave(&dev->lock, irq_flags); if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, address, avail, pipe, &status)) { - writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); -#ifdef CONFIG_64BIT - writel((u32)((u64)pipe >> 32), dev->base + PIPE_REG_CHANNEL_HIGH); -#endif + gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, + dev->base + PIPE_REG_CHANNEL_HIGH); writel(avail, dev->base + PIPE_REG_SIZE); - writel(address, dev->base + PIPE_REG_ADDRESS); -#ifdef CONFIG_64BIT - writel((u32)((u64)address >> 32), dev->base + PIPE_REG_ADDRESS_HIGH); -#endif + gf_write64(address, dev->base + PIPE_REG_ADDRESS, + dev->base + PIPE_REG_ADDRESS_HIGH); writel(CMD_WRITE_BUFFER + cmd_offset, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); -- cgit From f2dbdf625ddc98fece71a79d78d0981204e933ee Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 16 May 2014 08:24:58 +0300 Subject: goldfish: bus: fix warnings for 32bit builds drivers/platform/goldfish/pdev_bus.c: In function 'goldfish_new_pdev': drivers/platform/goldfish/pdev_bus.c:136:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] writel((u32)(u64)name, pdev_bus_base + PDEV_BUS_GET_NAME); Reported-by: Fengguang Wu Cc: Jun Tian Acked-by: Alan Cox Signed-off-by: Octavian Purdila Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/pdev_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c index eb254400c44a..8c43589c3edb 100644 --- a/drivers/platform/goldfish/pdev_bus.c +++ b/drivers/platform/goldfish/pdev_bus.c @@ -133,7 +133,7 @@ static int goldfish_new_pdev(void) #ifdef CONFIG_64BIT writel((u32)((u64)name>>32), pdev_bus_base + PDEV_BUS_GET_NAME_HIGH); #endif - writel((u32)(u64)name, pdev_bus_base + PDEV_BUS_GET_NAME); + writel((u32)(unsigned long)name, pdev_bus_base + PDEV_BUS_GET_NAME); name[name_len] = '\0'; dev->pdev.id = readl(pdev_bus_base + PDEV_BUS_ID); dev->pdev.resource[0].start = base; -- cgit From f4e131dc38d34469b9fee1840ad237324831bce3 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 16 May 2014 08:24:59 +0300 Subject: goldfish: pipe: fix warnings for 32bit builds drivers/platform/goldfish/goldfish_pipe.c: In function 'goldfish_cmd_status': drivers/platform/goldfish/goldfish_pipe.c:164:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); ^ drivers/platform/goldfish/goldfish_pipe.c: In function 'goldfish_cmd': drivers/platform/goldfish/goldfish_pipe.c:180:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); ^ drivers/platform/goldfish/goldfish_pipe.c: In function 'goldfish_pipe_read_write': drivers/platform/goldfish/goldfish_pipe.c:337:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] writel((u32)(u64)pipe, dev->base + PIPE_REG_CHANNEL); Reported-by: Fengguang Wu Cc: Jun Tian Acked-by: Alan Cox Signed-off-by: Octavian Purdila Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index c86180bba72e..d9a09d9637d9 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -158,7 +158,7 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, + gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); writel(cmd, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); @@ -172,7 +172,7 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) struct goldfish_pipe_dev *dev = pipe->dev; spin_lock_irqsave(&dev->lock, flags); - gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, + gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); writel(cmd, dev->base + PIPE_REG_COMMAND); spin_unlock_irqrestore(&dev->lock, flags); @@ -327,8 +327,9 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, spin_lock_irqsave(&dev->lock, irq_flags); if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, address, avail, pipe, &status)) { - gf_write64((u64)pipe, dev->base + PIPE_REG_CHANNEL, - dev->base + PIPE_REG_CHANNEL_HIGH); + gf_write64((u64)(unsigned long)pipe, + dev->base + PIPE_REG_CHANNEL, + dev->base + PIPE_REG_CHANNEL_HIGH); writel(avail, dev->base + PIPE_REG_SIZE); gf_write64(address, dev->base + PIPE_REG_ADDRESS, dev->base + PIPE_REG_ADDRESS_HIGH); -- cgit From d13374154e571293bb13df743b8d53b1e6797807 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 May 2014 10:48:02 +0200 Subject: acer-wmi: Switch to acpi_video_unregister_backlight Switch from acpi_video_unregister(), to acpi_video_unregister_backlight(), so that the hotkeys handler registered by acpi-video stays in place. Since there are no mappings for the atkbd raw codes for the brightness keys used by newer Acer models in /lib/udev/hwdb.d/60-keyboard.hwdb, and since we map the wmi events with a code of KE_IGNORE, we rely on acpi-video to do the hotkey handling for us. For laptops such as the Acer Aspire 5750 which uses intel gfx this works despite us calling acpi_video_unregister() because the following happens: 1) acpi-video module gets loaded (as it is a dependency of acer-wmi and i915) 2) acpi-video does NOT call acpi_video_register() 3) acer-wmi loads (assume it loads before i915), calls acpi_video_dmi_promote_vendor(); which sets ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 4) calls acpi_video_unregister -> not registered, nop 5) i915 loads, calls acpi_video_register 6) acpi_video_register registers the acpi_notifier for the hotkeys, does NOT register a backlight device because of ACPI_VIDEO_BACKLIGHT_DMI_VENDOR But on the Acer Aspire 5750G, which uses nvidia graphics the following happens: 1) acpi-video module gets loaded (as it is a dependency of acer-wmi) 2) acpi-video calls acpi_video_register() 3) acpi_video_register registers the acpi_notifier for the hotkeys, and a backlight device 4) acer-wmi loads, calls acpi_video_dmi_promote_vendor() 5) calls acpi_video_unregister, this unregisters BOTH the acpi_notifier for the hotkeys AND the backlight device And we end up without any handler for the brightness hotkeys. This patch fixes this by switching over to acpi_video_unregister_backlight() which keeps the hotkey handler in place. References: https://bugzilla.kernel.org/show_bug.cgi?id=35622 Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- 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 c91f69b39db4..3a746998f92a 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2228,7 +2228,7 @@ static int __init acer_wmi_init(void) pr_info("Brightness must be controlled by acpi video driver\n"); } else { pr_info("Disabling ACPI video driver\n"); - acpi_video_unregister(); + acpi_video_unregister_backlight(); } if (wmi_has_guid(WMID_GUID3)) { -- cgit From 9404cd95507de0a61f2a000fbd76748a9cae33b4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 17 May 2014 10:48:03 +0200 Subject: acer-wmi: Add Aspire 5741 to video_vendor_dmi_table The Aspire 5741 has broken acpi-video backlight control, so add it to the quirk table. References: https://bugzilla.redhat.com/show_bug.cgi?id=1012674 Signed-off-by: Hans de Goede Reviewed-by: Lee, Chun-Yi Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/acer-wmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3a746998f92a..bbf78b2d6d93 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -570,6 +570,14 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), }, }, + { + .callback = video_set_backlight_video_vendor, + .ident = "Acer Aspire 5741", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), + }, + }, {} }; -- cgit From c893d133eaccdda2516a3e71cd05a7dac2e14b00 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 30 May 2014 11:01:03 +0800 Subject: PCI: Make pci_bus_add_device() void pci_bus_add_device() always returns 0, so there's no point in returning anything at all. Make it a void function and remove the tests of the return value from the callers. [bhelgaas: changelog, remove unused "err" from i82875p_setup_overfl_dev()] Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/platform/x86/asus-wmi.c | 3 +-- drivers/platform/x86/eeepc-laptop.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c5e082fb82fa..91ef69a52263 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -642,8 +642,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus) dev = pci_scan_single_device(bus, 0); if (dev) { pci_bus_assign_resources(bus); - if (pci_bus_add_device(dev)) - pr_err("Unable to hotplug wifi\n"); + pci_bus_add_device(dev); } } else { dev = pci_get_slot(bus, 0); diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 399e8c562192..9b0c57cd1d4a 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -633,8 +633,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) dev = pci_scan_single_device(bus, 0); if (dev) { pci_bus_assign_resources(bus); - if (pci_bus_add_device(dev)) - pr_err("Unable to hotplug wifi\n"); + pci_bus_add_device(dev); } } else { dev = pci_get_slot(bus, 0); -- cgit From 21a3542753a63091bc4700525e6096d76fe32f62 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 Apr 2014 10:54:11 +0800 Subject: platform-drivers-x86: intel_pmic_gpio: Fix off-by-one valid offset range check Only pin 0-7 support input, so the valid offset range should be 0 ~ 7. Signed-off-by: Axel Lin Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_pmic_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 2805988485f6..40929e4f7ad7 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -91,7 +91,7 @@ static void pmic_program_irqtype(int gpio, int type) static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - if (offset > 8) { + if (offset >= 8) { pr_err("only pin 0-7 support input\n"); return -1;/* we only have 8 GPIO can use as input */ } @@ -130,7 +130,7 @@ static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset) int ret; /* we only have 8 GPIO pins we can use as input */ - if (offset > 8) + if (offset >= 8) return -EOPNOTSUPP; ret = intel_scu_ipc_ioread8(GPIO0 + offset, &r); if (ret < 0) -- cgit From fe808bfb59d693e07ee23c99542cd64e1f41b8c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Apr 2014 15:15:38 +0200 Subject: toshiba_acpi: Add alternative keymap support for Satellite M840 Toshiba Satellite M840 laptop has a complete different keymap although it's bound with the same ACPI ID "TOS1900". This patch provides an alternative keymap specific to this machine by identifying via DMI matching. The keymap table doesn't fill all entries that were used before since some keys aren't found on this machine at all. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=69761 Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=812209 Reported-and-tested-by: Federico Vecchiarelli Signed-off-by: Takashi Iwai Signed-off-by: Matthew Garrett --- drivers/platform/x86/toshiba_acpi.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 46473ca7566b..76441dcbe5ff 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -56,6 +56,7 @@ #include #include #include +#include #include MODULE_AUTHOR("John Belmonte"); @@ -213,6 +214,30 @@ static const struct key_entry toshiba_acpi_keymap[] = { { KE_END, 0 }, }; +/* alternative keymap */ +static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), + }, + }, + {} +}; + +static const struct key_entry toshiba_acpi_alt_keymap[] = { + { KE_KEY, 0x157, { KEY_MUTE } }, + { KE_KEY, 0x102, { KEY_ZOOMOUT } }, + { KE_KEY, 0x103, { KEY_ZOOMIN } }, + { KE_KEY, 0x139, { KEY_ZOOMRESET } }, + { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, 0x13d, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x158, { KEY_WLAN } }, + { KE_KEY, 0x13f, { KEY_TOUCHPAD_TOGGLE } }, + { KE_END, 0 }, +}; + /* utility */ @@ -1440,6 +1465,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) acpi_handle ec_handle; int error; u32 hci_result; + const struct key_entry *keymap = toshiba_acpi_keymap; dev->hotkey_dev = input_allocate_device(); if (!dev->hotkey_dev) @@ -1449,7 +1475,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) dev->hotkey_dev->phys = "toshiba_acpi/input0"; dev->hotkey_dev->id.bustype = BUS_HOST; - error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL); + if (dmi_check_system(toshiba_alt_keymap_dmi)) + keymap = toshiba_acpi_alt_keymap; + error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL); if (error) goto err_free_dev; -- cgit From 0ca849ea4fb86d9ee61435559f7159ed627895c3 Mon Sep 17 00:00:00 2001 From: Scott Thrasher Date: Tue, 6 May 2014 08:06:42 -0700 Subject: platform/x86: samsung-laptop: Add support for Samsung's NP7[34]0U3E models. These models have only 4 levels of keyboard backlight brightness and forget how to work the backlight after resuming from S3 sleep. I've added a quirk to set the appropriate number of backlight levels, and one to re-enable the keyboard backlight on resume. (Whitespace cleaned up by Matthew Garrett) Signed-off-by: Scott Thrasher Signed-off-by: Matthew Garrett --- drivers/platform/x86/samsung-laptop.c | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index d1f030053176..5a5966512277 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -27,6 +27,7 @@ #include #include #include +#include #include /* @@ -340,6 +341,8 @@ struct samsung_laptop { struct samsung_laptop_debug debug; struct samsung_quirks *quirks; + struct notifier_block pm_nb; + bool handle_backlight; bool has_stepping_quirk; @@ -348,6 +351,8 @@ struct samsung_laptop { struct samsung_quirks { bool broken_acpi_video; + bool four_kbd_backlight_levels; + bool enable_kbd_backlight; }; static struct samsung_quirks samsung_unknown = {}; @@ -356,6 +361,11 @@ static struct samsung_quirks samsung_broken_acpi_video = { .broken_acpi_video = true, }; +static struct samsung_quirks samsung_np740u3e = { + .four_kbd_backlight_levels = true, + .enable_kbd_backlight = true, +}; + static bool force; module_param(force, bool, 0); MODULE_PARM_DESC(force, @@ -1051,6 +1061,8 @@ static int __init samsung_leds_init(struct samsung_laptop *samsung) samsung->kbd_led.brightness_set = kbd_led_set; samsung->kbd_led.brightness_get = kbd_led_get; samsung->kbd_led.max_brightness = 8; + if (samsung->quirks->four_kbd_backlight_levels) + samsung->kbd_led.max_brightness = 4; ret = led_classdev_register(&samsung->platform_device->dev, &samsung->kbd_led); @@ -1414,6 +1426,19 @@ static void samsung_platform_exit(struct samsung_laptop *samsung) } } +static int samsung_pm_notification(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + struct samsung_laptop *samsung; + + samsung = container_of(nb, struct samsung_laptop, pm_nb); + if (val == PM_POST_HIBERNATION && + samsung->quirks->enable_kbd_backlight) + kbd_backlight_enable(samsung); + + return 0; +} + static int __init samsung_platform_init(struct samsung_laptop *samsung) { struct platform_device *pdev; @@ -1534,6 +1559,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, .driver_data = &samsung_broken_acpi_video, }, + { + .callback = samsung_dmi_matched, + .ident = "730U3E/740U3E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"), + }, + .driver_data = &samsung_np740u3e, + }, { }, }; MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); @@ -1608,6 +1642,9 @@ static int __init samsung_init(void) if (ret) goto error_debugfs; + samsung->pm_nb.notifier_call = samsung_pm_notification; + register_pm_notifier(&samsung->pm_nb); + samsung_platform_device = samsung->platform_device; return ret; @@ -1633,6 +1670,7 @@ static void __exit samsung_exit(void) struct samsung_laptop *samsung; samsung = platform_get_drvdata(samsung_platform_device); + unregister_pm_notifier(&samsung->pm_nb); samsung_debugfs_exit(samsung); samsung_leds_exit(samsung); -- cgit From 7939831eacd81fccbd7a956b30c7bb3abb9079db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 May 2014 17:52:26 +0200 Subject: pvpanic: Set high notifier priority We've observed the missing pvpanic call at panic, and it turned out that this was blocked by the broken notifier of drm_fb_helper, where scheduling may be called during switching to the fb console. It's fairly difficult to fix the drm_fb problem and a quick fix isn't foreseen, a simpler solution for the missing pvpanic call would be just to call this earlier. In order to assure that, this patch sets a higher priority to pvpanic notifier_block. Once when the issue of drm_fb is resolved, we can remove this priority again. Signed-off-by: Takashi Iwai Signed-off-by: Matthew Garrett --- drivers/platform/x86/pvpanic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/pvpanic.c b/drivers/platform/x86/pvpanic.c index c9f6e511daa6..073a90a63dbc 100644 --- a/drivers/platform/x86/pvpanic.c +++ b/drivers/platform/x86/pvpanic.c @@ -70,6 +70,7 @@ pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, static struct notifier_block pvpanic_panic_nb = { .notifier_call = pvpanic_panic_notify, + .priority = 1, /* let this called before broken drm_fb_helper */ }; -- cgit From b998680e9adea22159b66bd59ecdf07624e201ed Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 7 May 2014 15:08:09 -0500 Subject: alienware-wmi: Update WMAX brightness method limit to 15 This more closely reflects what the hardware can actually support. Signed-off-by: Mario Limonciello Signed-off-by: Matthew Garrett --- drivers/platform/x86/alienware-wmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 541f9514f76f..e5329eac86b7 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -350,12 +350,11 @@ static int alienware_zone_init(struct platform_device *dev) char *name; if (interface == WMAX) { - global_led.max_brightness = 100; lighting_control_state = WMAX_RUNNING; } else if (interface == LEGACY) { - global_led.max_brightness = 0x0F; lighting_control_state = LEGACY_RUNNING; } + global_led.max_brightness = 0x0F; global_brightness = global_led.max_brightness; /* -- cgit From bc2ef884320bdca8d2544d517ac5489bb1722896 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 7 May 2014 15:08:10 -0500 Subject: alienware-wmi: For WMAX HDMI method, introduce a way to query HDMI cable status Since there are now multiple HDMI attributes associated with the WMAX method, create a sysfs group for them instead. Signed-off-by: Mario Limonciello Signed-off-by: Matthew Garrett --- drivers/platform/x86/alienware-wmi.c | 118 ++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 30 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index e5329eac86b7..297b6640213f 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -32,6 +32,7 @@ #define WMAX_METHOD_HDMI_STATUS 0x2 #define WMAX_METHOD_BRIGHTNESS 0x3 #define WMAX_METHOD_ZONE_CONTROL 0x4 +#define WMAX_METHOD_HDMI_CABLE 0x5 MODULE_AUTHOR("Mario Limonciello "); MODULE_DESCRIPTION("Alienware special feature control"); @@ -422,41 +423,85 @@ static void alienware_zone_exit(struct platform_device *dev) The HDMI mux sysfs node indicates the status of the HDMI input mux. It can toggle between standard system GPU output and HDMI input. */ -static ssize_t show_hdmi(struct device *dev, struct device_attribute *attr, - char *buf) +static acpi_status alienware_hdmi_command(struct hdmi_args *in_args, + u32 command, int *out_data) { acpi_status status; - struct acpi_buffer input; union acpi_object *obj; - u32 tmp = 0; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer input; + struct acpi_buffer output; + + input.length = (acpi_size) sizeof(*in_args); + input.pointer = in_args; + if (out_data != NULL) { + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; + status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, + command, &input, &output); + } else + status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, + command, &input, NULL); + + if (ACPI_SUCCESS(status) && out_data != NULL) { + obj = (union acpi_object *)output.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + *out_data = (u32) obj->integer.value; + } + return status; + +} + +static ssize_t show_hdmi_cable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + acpi_status status; + u32 out_data; struct hdmi_args in_args = { .arg = 0, }; - input.length = (acpi_size) sizeof(in_args); - input.pointer = &in_args; - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, - WMAX_METHOD_HDMI_STATUS, &input, &output); + status = + alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE, + (u32 *) &out_data); + if (ACPI_SUCCESS(status)) { + if (out_data == 0) + return scnprintf(buf, PAGE_SIZE, + "[unconnected] connected unknown\n"); + else if (out_data == 1) + return scnprintf(buf, PAGE_SIZE, + "unconnected [connected] unknown\n"); + } + pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status); + return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n"); +} + +static ssize_t show_hdmi_source(struct device *dev, + struct device_attribute *attr, char *buf) +{ + acpi_status status; + u32 out_data; + struct hdmi_args in_args = { + .arg = 0, + }; + status = + alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS, + (u32 *) &out_data); if (ACPI_SUCCESS(status)) { - obj = (union acpi_object *)output.pointer; - if (obj && obj->type == ACPI_TYPE_INTEGER) - tmp = (u32) obj->integer.value; - if (tmp == 1) + if (out_data == 1) return scnprintf(buf, PAGE_SIZE, "[input] gpu unknown\n"); - else if (tmp == 2) + else if (out_data == 2) return scnprintf(buf, PAGE_SIZE, "input [gpu] unknown\n"); } - pr_err("alienware-wmi: unknown HDMI status: %d\n", status); + pr_err("alienware-wmi: unknown HDMI source status: %d\n", out_data); return scnprintf(buf, PAGE_SIZE, "input gpu [unknown]\n"); } -static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t toggle_hdmi_source(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct acpi_buffer input; acpi_status status; struct hdmi_args args; if (strcmp(buf, "gpu\n") == 0) @@ -466,33 +511,46 @@ static ssize_t toggle_hdmi(struct device *dev, struct device_attribute *attr, else args.arg = 3; pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); - input.length = (acpi_size) sizeof(args); - input.pointer = &args; - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 1, - WMAX_METHOD_HDMI_SOURCE, &input, NULL); + + status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); + if (ACPI_FAILURE(status)) pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", status); return count; } -static DEVICE_ATTR(hdmi, S_IRUGO | S_IWUSR, show_hdmi, toggle_hdmi); +static DEVICE_ATTR(cable, S_IRUGO, show_hdmi_cable, NULL); +static DEVICE_ATTR(source, S_IRUGO | S_IWUSR, show_hdmi_source, + toggle_hdmi_source); + +static struct attribute *hdmi_attrs[] = { + &dev_attr_cable.attr, + &dev_attr_source.attr, + NULL, +}; -static void remove_hdmi(struct platform_device *device) +static struct attribute_group hdmi_attribute_group = { + .name = "hdmi", + .attrs = hdmi_attrs, +}; + +static void remove_hdmi(struct platform_device *dev) { - device_remove_file(&device->dev, &dev_attr_hdmi); + sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); } -static int create_hdmi(void) +static int create_hdmi(struct platform_device *dev) { - int ret = -ENOMEM; - ret = device_create_file(&platform_device->dev, &dev_attr_hdmi); + int ret; + + ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group); if (ret) goto error_create_hdmi; return 0; error_create_hdmi: - remove_hdmi(platform_device); + remove_hdmi(dev); return ret; } @@ -526,7 +584,7 @@ static int __init alienware_wmi_init(void) goto fail_platform_device2; if (interface == WMAX) { - ret = create_hdmi(); + ret = create_hdmi(platform_device); if (ret) goto fail_prep_hdmi; } -- cgit From c08db55fe1455202e4bcda416e88bbbc20700dc4 Mon Sep 17 00:00:00 2001 From: Andreas Utterberg Date: Tue, 6 May 2014 22:27:45 +0200 Subject: asus-wmi: Set WAPF to 4 for Asus X550CA The 'asus-nb-wmi' WAPF parameter must be set to 4, so the internal Wireless LAN device is operational. Signed-off-by: Andreas Utterberg Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 563f59efa669..ddf0eefd862c 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -135,6 +135,15 @@ static struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_x401u, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550CA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), + }, + .driver_data = &quirk_asus_x401u, + }, { .callback = dmi_matched, .ident = "ASUSTeK COMPUTER INC. X55A", -- cgit From 85093f79f586176f8bbf90e56e22a3dfa526e334 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 13 May 2014 16:00:28 +0200 Subject: ideapad-laptop: Blacklist rfkill control on the Lenovo Yoga 2 11 The Lenovo Yoga 2 11 always reports everything as blocked, causing userspace to not even try to use the wlan / bluetooth even though they work fine. Note this patch also removes the "else priv->rfk[i] = NULL;" bit of the rfkill initialization, it is not necessary as the priv struct is allocated with kzalloc. Reported-and-tested-by: Vincent Gerris Signed-off-by: Hans de Goede Signed-off-by: Matthew Garrett --- drivers/platform/x86/ideapad-laptop.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 6dd060a0bb65..219eb289a909 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -36,6 +36,7 @@ #include #include #include +#include #define IDEAPAD_RFKILL_DEV_NUM (3) @@ -819,6 +820,19 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) } } +/* Blacklist for devices where the ideapad rfkill interface does not work */ +static struct dmi_system_id rfkill_blacklist[] = { + /* The Lenovo Yoga 2 11 always reports everything as blocked */ + { + .ident = "Lenovo Yoga 2 11", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), + }, + }, + {} +}; + static int ideapad_acpi_add(struct platform_device *pdev) { int ret, i; @@ -854,11 +868,10 @@ static int ideapad_acpi_add(struct platform_device *pdev) if (ret) goto input_failed; - for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) { - if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) - ideapad_register_rfkill(priv, i); - else - priv->rfk[i] = NULL; + if (!dmi_check_system(rfkill_blacklist)) { + for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) + if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) + ideapad_register_rfkill(priv, i); } ideapad_sync_rfk_state(priv); ideapad_sync_touchpad_state(priv); -- cgit From eec3b959f57508b250831ed10efa07f8209e9d1b Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Wed, 21 May 2014 17:24:28 -0300 Subject: platform x86 Kconfig: Refer to the laptop list in the Compal driver help Signed-off-by: Ismael Luceno Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 27df2c533b09..3ba9c42408c5 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -102,7 +102,7 @@ config DELL_LAPTOP default n ---help--- This driver adds support for rfkill and backlight control to Dell - laptops. + laptops (except for some models covered by the Compal driver). config DELL_WMI tristate "Dell WMI extras" @@ -265,23 +265,21 @@ config PANASONIC_LAPTOP R2, R3, R5, T2, W2 and Y2 series), say Y. config COMPAL_LAPTOP - tristate "Compal Laptop Extras" + tristate "Compal (and others) Laptop Extras" depends on ACPI depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL depends on HWMON depends on POWER_SUPPLY ---help--- - This is a driver for laptops built by Compal: + This is a driver for laptops built by Compal, and some models by + other brands (e.g. Dell, Toshiba). - Compal FL90/IFL90 - Compal FL91/IFL91 - Compal FL92/JFL92 - Compal FT00/IFT00 + It adds support for rfkill, Bluetooth, WLAN and LCD brightness + control. - It adds support for Bluetooth, WLAN and LCD brightness control. - - If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here. + For a (possibly incomplete) list of supported laptops, please refer + to: Documentation/platform/x86-laptop-drivers.txt config SONY_LAPTOP tristate "Sony Laptop Extras" -- cgit From 14627e36121c90b9a794ab0ea3195efa4c23373e Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 25 May 2014 13:05:45 +0530 Subject: ix86/mid/thermal: Introduce the use of the managed version of kzalloc This patch moves data allocated using kzalloc to managed data allocated using devm_kzalloc and cleans now unnecessary kfrees in probe and remove functions. The following Coccinelle semantic patch was used for making the change: @platform@ identifier p, probefn, removefn; @@ struct platform_driver p = { .probe = probefn, .remove = removefn, }; @prb@ identifier platform.probefn, pdev; expression e, e1, e2; @@ probefn(struct platform_device *pdev, ...) { <+... - e = kzalloc(e1, e2) + e = devm_kzalloc(&pdev->dev, e1, e2) ... ?-kfree(e); ...+> } @rem depends on prb@ identifier platform.removefn; expression e; @@ removefn(...) { <... - kfree(e); ...> } Signed-off-by: Himangi Saraogi Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_mid_thermal.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index 93fab8b70ce1..ab7860a21a22 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c @@ -481,7 +481,8 @@ static int mid_thermal_probe(struct platform_device *pdev) int i; struct platform_info *pinfo; - pinfo = kzalloc(sizeof(struct platform_info), GFP_KERNEL); + pinfo = devm_kzalloc(&pdev->dev, sizeof(struct platform_info), + GFP_KERNEL); if (!pinfo) return -ENOMEM; @@ -489,7 +490,6 @@ static int mid_thermal_probe(struct platform_device *pdev) ret = mid_initialize_adc(&pdev->dev); if (ret) { dev_err(&pdev->dev, "ADC init failed"); - kfree(pinfo); return ret; } @@ -520,7 +520,6 @@ err: thermal_zone_device_unregister(pinfo->tzd[i]); } configure_adc(0); - kfree(pinfo); return ret; } @@ -541,8 +540,6 @@ static int mid_thermal_remove(struct platform_device *pdev) thermal_zone_device_unregister(pinfo->tzd[i]); } - kfree(pinfo); - /* Stop the ADC */ return configure_adc(0); } -- cgit From 8ad3be1eacbe252b93f5a0478413774308f3dbfb Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 1 Jun 2014 14:58:52 +0200 Subject: platform: x86: asus-wmi.c: Cleaning up uninitialized variables There is a risk that the variable will be used without being initialized. This was largely found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 91ef69a52263..3c6ccedc82b6 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -266,7 +266,7 @@ static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_status status; union acpi_object *obj; - u32 tmp; + u32 tmp = 0; status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id, &input, &output); @@ -277,8 +277,6 @@ static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, obj = (union acpi_object *)output.pointer; if (obj && obj->type == ACPI_TYPE_INTEGER) tmp = (u32) obj->integer.value; - else - tmp = 0; if (retval) *retval = tmp; -- cgit From b02fdfcc40d74e64d3ea2a2120c96979e1b33128 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 1 Jun 2014 22:02:48 +0200 Subject: platform/x86: Fix run-time dependencies of OLPC drivers Let the xo15-ebook driver depend on OLPC as all other OLPC drivers already do. Add COMPILE_TEST as an alternative for both xo1-rfkill and xo15-ebook, to increase the build testing coverage. Signed-off-by: Jean Delvare Cc: Matthew Garrett Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3ba9c42408c5..60d33834f28f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -722,7 +722,7 @@ config IBM_RTL config XO1_RFKILL tristate "OLPC XO-1 software RF kill switch" - depends on OLPC + depends on OLPC || COMPILE_TEST depends on RFKILL ---help--- Support for enabling/disabling the WLAN interface on the OLPC XO-1 @@ -730,6 +730,7 @@ config XO1_RFKILL config XO15_EBOOK tristate "OLPC XO-1.5 ebook switch" + depends on OLPC || COMPILE_TEST depends on ACPI && INPUT ---help--- Support for the ebook switch on the OLPC XO-1.5 laptop. -- cgit From b3facd7ba822ede3e98108e17a75f2c9c3e463af Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Mon, 9 Jun 2014 17:46:50 -0400 Subject: ideapad_laptop: Introduce the use of the managed version of kzalloc This patch moves data allocated using kzalloc to managed data allocated using devm_kzalloc and cleans now unnecessary kfrees in probe and remove functions. The label sysfs_failed is removed as it is no longer required. Also, linux/device.h is added to make sure the devm_*() routine declarations are unambiguously available. The following Coccinelle semantic patch was used for making the change: @platform@ identifier p, probefn, removefn; @@ struct platform_driver p = { .probe = probefn, .remove = removefn, }; @prb@ identifier platform.probefn, pdev; expression e, e1, e2; @@ probefn(struct platform_device *pdev, ...) { <+... - e = kzalloc(e1, e2) + e = devm_kzalloc(&pdev->dev, e1, e2) ... ?-kfree(e); ...+> } @rem depends on prb@ identifier platform.removefn; expression e; @@ removefn(...) { <... - kfree(e); ...> } Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Signed-off-by: Matthew Garrett --- drivers/platform/x86/ideapad-laptop.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 219eb289a909..b4c495a62eec 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -37,6 +37,7 @@ #include #include #include +#include #define IDEAPAD_RFKILL_DEV_NUM (3) @@ -847,7 +848,7 @@ static int ideapad_acpi_add(struct platform_device *pdev) if (read_method_int(adev->handle, "_CFG", &cfg)) return -ENODEV; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -858,7 +859,7 @@ static int ideapad_acpi_add(struct platform_device *pdev) ret = ideapad_sysfs_init(priv); if (ret) - goto sysfs_failed; + return ret; ret = ideapad_debugfs_init(priv); if (ret) @@ -897,8 +898,6 @@ input_failed: ideapad_debugfs_exit(priv); debugfs_failed: ideapad_sysfs_exit(priv); -sysfs_failed: - kfree(priv); return ret; } @@ -916,7 +915,6 @@ static int ideapad_acpi_remove(struct platform_device *pdev) ideapad_debugfs_exit(priv); ideapad_sysfs_exit(priv); dev_set_drvdata(&pdev->dev, NULL); - kfree(priv); return 0; } -- cgit From 4738d8aabe89d237f30a28c65f61391a1435e3a7 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Thu, 22 May 2014 13:15:48 +0200 Subject: platform: x86: dell-smo8800: Dell Latitude freefall driver (ACPI SMO8800/SMO8810) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This acpi driver provide supports for freefall sensors SMO8800/SMO8810 which can be found on Dell Latitude laptops. Driver register /dev/freefall misc device which has same interface as driver hp_accel freefall driver. So any existing applications for HP freefall sensor /dev/freefall will work for with this new driver for Dell Latitude laptops too. Signed-off-by: Pali Rohár Cc: Sonal Santan Tested-By: Valdis Kletnieks Acked-By: Valdis Kletnieks Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 10 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/dell-smo8800.c | 233 ++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 drivers/platform/x86/dell-smo8800.c (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 60d33834f28f..172f26ce59ac 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -127,6 +127,16 @@ config DELL_WMI_AIO To compile this driver as a module, choose M here: the module will be called dell-wmi-aio. +config DELL_SMO8800 + tristate "Dell Latitude freefall driver (ACPI SMO8800/SMO8810)" + depends on ACPI + ---help--- + Say Y here if you want to support SMO8800/SMO8810 freefall device + on Dell Latitude laptops. + + To compile this driver as a module, choose M here: the module will + be called dell-smo8800. + config FUJITSU_LAPTOP tristate "Fujitsu Laptop Extras" diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 1a2eafc9d48e..c4ca428fd3db 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o +obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ACERHDF) += acerhdf.o obj-$(CONFIG_HP_ACCEL) += hp_accel.o diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c new file mode 100644 index 000000000000..a653716055d1 --- /dev/null +++ b/drivers/platform/x86/dell-smo8800.c @@ -0,0 +1,233 @@ +/* + * dell-smo8800.c - Dell Latitude ACPI SMO8800/SMO8810 freefall sensor driver + * + * Copyright (C) 2012 Sonal Santan + * Copyright (C) 2014 Pali Rohár + * + * This is loosely based on lis3lv02d driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define DRIVER_NAME "smo8800" + +#include +#include +#include +#include +#include + +struct smo8800_device { + u32 irq; /* acpi device irq */ + atomic_t counter; /* count after last read */ + struct miscdevice miscdev; /* for /dev/freefall */ + unsigned long misc_opened; /* whether the device is open */ + wait_queue_head_t misc_wait; /* Wait queue for the misc dev */ + struct device *dev; /* acpi device */ +}; + +static irqreturn_t smo8800_interrupt_quick(int irq, void *data) +{ + struct smo8800_device *smo8800 = data; + + atomic_inc(&smo8800->counter); + wake_up_interruptible(&smo8800->misc_wait); + return IRQ_WAKE_THREAD; +} + +static irqreturn_t smo8800_interrupt_thread(int irq, void *data) +{ + struct smo8800_device *smo8800 = data; + + dev_info(smo8800->dev, "detected free fall\n"); + return IRQ_HANDLED; +} + +static acpi_status smo8800_get_resource(struct acpi_resource *resource, + void *context) +{ + struct acpi_resource_extended_irq *irq; + + if (resource->type != ACPI_RESOURCE_TYPE_EXTENDED_IRQ) + return AE_OK; + + irq = &resource->data.extended_irq; + if (!irq || !irq->interrupt_count) + return AE_OK; + + *((u32 *)context) = irq->interrupts[0]; + return AE_CTRL_TERMINATE; +} + +static u32 smo8800_get_irq(struct acpi_device *device) +{ + u32 irq = 0; + acpi_status status; + + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + smo8800_get_resource, &irq); + if (ACPI_FAILURE(status)) { + dev_err(&device->dev, "acpi_walk_resources failed\n"); + return 0; + } + + return irq; +} + +static ssize_t smo8800_misc_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + struct smo8800_device *smo8800 = container_of(file->private_data, + struct smo8800_device, miscdev); + + u32 data = 0; + unsigned char byte_data = 0; + ssize_t retval = 1; + + if (count < 1) + return -EINVAL; + + atomic_set(&smo8800->counter, 0); + retval = wait_event_interruptible(smo8800->misc_wait, + (data = atomic_xchg(&smo8800->counter, 0))); + + if (retval) + return retval; + + byte_data = 1; + retval = 1; + + if (data < 255) + byte_data = data; + else + byte_data = 255; + + if (put_user(byte_data, buf)) + retval = -EFAULT; + + return retval; +} + +static int smo8800_misc_open(struct inode *inode, struct file *file) +{ + struct smo8800_device *smo8800 = container_of(file->private_data, + struct smo8800_device, miscdev); + + if (test_and_set_bit(0, &smo8800->misc_opened)) + return -EBUSY; /* already open */ + + atomic_set(&smo8800->counter, 0); + return 0; +} + +static int smo8800_misc_release(struct inode *inode, struct file *file) +{ + struct smo8800_device *smo8800 = container_of(file->private_data, + struct smo8800_device, miscdev); + + clear_bit(0, &smo8800->misc_opened); /* release the device */ + return 0; +} + +static const struct file_operations smo8800_misc_fops = { + .owner = THIS_MODULE, + .read = smo8800_misc_read, + .open = smo8800_misc_open, + .release = smo8800_misc_release, +}; + +static int smo8800_add(struct acpi_device *device) +{ + int err; + struct smo8800_device *smo8800; + + smo8800 = devm_kzalloc(&device->dev, sizeof(*smo8800), GFP_KERNEL); + if (!smo8800) { + dev_err(&device->dev, "failed to allocate device data\n"); + return -ENOMEM; + } + + smo8800->dev = &device->dev; + smo8800->miscdev.minor = MISC_DYNAMIC_MINOR; + smo8800->miscdev.name = "freefall"; + smo8800->miscdev.fops = &smo8800_misc_fops; + + init_waitqueue_head(&smo8800->misc_wait); + + err = misc_register(&smo8800->miscdev); + if (err) { + dev_err(&device->dev, "failed to register misc dev: %d\n", err); + return err; + } + + device->driver_data = smo8800; + + smo8800->irq = smo8800_get_irq(device); + if (!smo8800->irq) { + dev_err(&device->dev, "failed to obtain IRQ\n"); + err = -EINVAL; + goto error; + } + + err = request_threaded_irq(smo8800->irq, smo8800_interrupt_quick, + smo8800_interrupt_thread, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + DRIVER_NAME, smo8800); + if (err) { + dev_err(&device->dev, + "failed to request thread for IRQ %d: %d\n", + smo8800->irq, err); + goto error; + } + + dev_dbg(&device->dev, "device /dev/freefall registered with IRQ %d\n", + smo8800->irq); + return 0; + +error: + misc_deregister(&smo8800->miscdev); + return err; +} + +static int smo8800_remove(struct acpi_device *device) +{ + struct smo8800_device *smo8800 = device->driver_data; + + free_irq(smo8800->irq, smo8800); + misc_deregister(&smo8800->miscdev); + dev_dbg(&device->dev, "device /dev/freefall unregistered\n"); + return 0; +} + +static const struct acpi_device_id smo8800_ids[] = { + { "SMO8800", 0 }, + { "SMO8810", 0 }, + { "", 0 }, +}; + +MODULE_DEVICE_TABLE(acpi, smo8800_ids); + +static struct acpi_driver smo8800_driver = { + .name = DRIVER_NAME, + .class = "Latitude", + .ids = smo8800_ids, + .ops = { + .add = smo8800_add, + .remove = smo8800_remove, + }, + .owner = THIS_MODULE, +}; + +module_acpi_driver(smo8800_driver); + +MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO8800/SMO8810)"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sonal Santan, Pali Rohár"); -- cgit From 8b9dd4fab26a0f328420cbda0845a325f45bcd92 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 9 Apr 2014 11:46:46 +0200 Subject: thinkpad_acpi: Add mappings for F9 - F12 hotkeys on X240 / T440 / T540 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The T440s user guide says that when Fn-lock is not active, the *40s' F9 - F12 keys should be mapped to: control-panel, search, show-all-windows and Computer. These keys generate the sofar unused 28 - 31 hotkey scancodes. For the first 2 this nicely matches the icons on the keys, for the latter 2 the icons are somewhat creative, which is why I ended up looking them up in the user manual. Signed-off-by: Hans de Goede Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 15e61c16736e..d82f196e3cfe 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3171,8 +3171,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_MICMUTE, /* 0x1a: Mic mute (since ?400 or so) */ /* (assignments unknown, please report if found) */ - KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, + + /* Extra keys in use since the X240 / T440 / T540 */ + KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, }, }; -- cgit From f82bdd0d77b6bf0dea08a1d957ab45d503f328b1 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 9 Jun 2014 12:26:06 -0500 Subject: hp-wmi: Enable hotkeys on some systems This is a third attempt to enable these buttons. The new variable being commit 997daa1bd9aca412ab97955a35b26c460c0ec7a4 (i.e. hp-wmi: detect "2009 BIOS or later"). Older systems that do not have the 2009 BIOS query method respond with a dummy value, in this case 4. Using that, we can target a fairly narrow group of systems. i.e. old enough to not have HPWMI_FEATURE_QUERY 0xd, but new enough to have HPWMI_BIOS_QUERY 0x9. This group may be further limited if some systems respond with something other than 4 to non-existant feature queries. Signed-off-by: Kyle Evans Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8ba8956b5a48..484a8673b835 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_ALS_QUERY 0x3 #define HPWMI_HARDWARE_QUERY 0x4 #define HPWMI_WIRELESS_QUERY 0x5 +#define HPWMI_BIOS_QUERY 0x9 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_FEATURE_QUERY 0xd #define HPWMI_WIRELESS2_QUERY 0x1b @@ -144,6 +145,7 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x2142, { KEY_MEDIA } }, { KE_KEY, 0x213b, { KEY_INFO } }, { KE_KEY, 0x2169, { KEY_DIRECTION } }, + { KE_KEY, 0x216a, { KEY_SETUP } }, { KE_KEY, 0x231b, { KEY_HELP } }, { KE_END, 0 } }; @@ -304,6 +306,19 @@ static int hp_wmi_bios_2009_later(void) return (state & 0x10) ? 1 : 0; } +static int hp_wmi_enable_hotkeys(void) +{ + int ret; + int query = 0x6e; + + ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query), + 0); + + if (ret) + return -EINVAL; + return 0; +} + static int hp_wmi_set_block(void *data, bool blocked) { enum hp_wmi_radio r = (enum hp_wmi_radio) data; @@ -648,6 +663,9 @@ static int __init hp_wmi_input_setup(void) hp_wmi_tablet_state()); input_sync(hp_wmi_input_dev); + if (hp_wmi_bios_2009_later() == 4) + hp_wmi_enable_hotkeys(); + status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); if (ACPI_FAILURE(status)) { err = -EIO; -- cgit