Commit a77c0058 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86

Pull x86 platform drivers from Matthew Garrett:
 "Small set of updates, mainly trivial bugfixes and some small updates
  to deal with newer hardware.

  There's also a new driver that allows qemu guests to notify the
  hypervisor that they've just paniced, which seems useful."

* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86:
  Add support for fan button on Ideapad Z580
  pvpanic: pvpanic device driver
  asus-nb-wmi: set wapf=4 for ASUSTeK COMPUTER INC. X75A
  drivers: platform: x86: Use PTR_RET function
  sony-laptop: SVS151290S kbd backlight and gfx switch support
  hp-wmi: add more definitions for new event_id's
  dell-laptop: Fix krealloc() misuse in parse_da_table()
  hp_accel: Ignore the error from lis3lv02d_poweron() at resume
  dell: add new dell WMI format for the AIO machines
parents 3644bc2e a1ec56ed
...@@ -781,4 +781,12 @@ config APPLE_GMUX ...@@ -781,4 +781,12 @@ config APPLE_GMUX
graphics as well as the backlight. Currently only backlight graphics as well as the backlight. Currently only backlight
control is supported by the driver. control is supported by the driver.
config PVPANIC
tristate "pvpanic device support"
depends on ACPI
---help---
This driver provides support for the pvpanic device. pvpanic is
a paravirtualized device provided by QEMU; it lets a virtual machine
(guest) communicate panic events to the host.
endif # X86_PLATFORM_DEVICES endif # X86_PLATFORM_DEVICES
...@@ -51,3 +51,5 @@ obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o ...@@ -51,3 +51,5 @@ obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
...@@ -171,6 +171,15 @@ static struct dmi_system_id asus_quirks[] = { ...@@ -171,6 +171,15 @@ static struct dmi_system_id asus_quirks[] = {
}, },
.driver_data = &quirk_asus_x401u, .driver_data = &quirk_asus_x401u,
}, },
{
.callback = dmi_matched,
.ident = "ASUSTeK COMPUTER INC. X75A",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),
},
.driver_data = &quirk_asus_x401u,
},
{}, {},
}; };
......
...@@ -34,6 +34,14 @@ MODULE_LICENSE("GPL"); ...@@ -34,6 +34,14 @@ MODULE_LICENSE("GPL");
#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4" #define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
#define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8" #define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"
struct dell_wmi_event {
u16 length;
/* 0x000: A hot key pressed or an event occurred
* 0x00F: A sequence of hot keys are pressed */
u16 type;
u16 event[];
};
static const char *dell_wmi_aio_guids[] = { static const char *dell_wmi_aio_guids[] = {
EVENT_GUID1, EVENT_GUID1,
EVENT_GUID2, EVENT_GUID2,
...@@ -46,15 +54,41 @@ MODULE_ALIAS("wmi:"EVENT_GUID2); ...@@ -46,15 +54,41 @@ MODULE_ALIAS("wmi:"EVENT_GUID2);
static const struct key_entry dell_wmi_aio_keymap[] = { static const struct key_entry dell_wmi_aio_keymap[] = {
{ KE_KEY, 0xc0, { KEY_VOLUMEUP } }, { KE_KEY, 0xc0, { KEY_VOLUMEUP } },
{ KE_KEY, 0xc1, { KEY_VOLUMEDOWN } }, { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0xe030, { KEY_VOLUMEUP } },
{ KE_KEY, 0xe02e, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0xe020, { KEY_MUTE } },
{ KE_KEY, 0xe027, { KEY_DISPLAYTOGGLE } },
{ KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
{ KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
{ KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
{ KE_END, 0 } { KE_END, 0 }
}; };
static struct input_dev *dell_wmi_aio_input_dev; static struct input_dev *dell_wmi_aio_input_dev;
/*
* The new WMI event data format will follow the dell_wmi_event structure
* So, we will check if the buffer matches the format
*/
static bool dell_wmi_aio_event_check(u8 *buffer, int length)
{
struct dell_wmi_event *event = (struct dell_wmi_event *)buffer;
if (event == NULL || length < 6)
return false;
if ((event->type == 0 || event->type == 0xf) &&
event->length >= 2)
return true;
return false;
}
static void dell_wmi_aio_notify(u32 value, void *context) static void dell_wmi_aio_notify(u32 value, void *context)
{ {
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj; union acpi_object *obj;
struct dell_wmi_event *event;
acpi_status status; acpi_status status;
status = wmi_get_event_data(value, &response); status = wmi_get_event_data(value, &response);
...@@ -65,7 +99,7 @@ static void dell_wmi_aio_notify(u32 value, void *context) ...@@ -65,7 +99,7 @@ static void dell_wmi_aio_notify(u32 value, void *context)
obj = (union acpi_object *)response.pointer; obj = (union acpi_object *)response.pointer;
if (obj) { if (obj) {
unsigned int scancode; unsigned int scancode = 0;
switch (obj->type) { switch (obj->type) {
case ACPI_TYPE_INTEGER: case ACPI_TYPE_INTEGER:
...@@ -75,13 +109,22 @@ static void dell_wmi_aio_notify(u32 value, void *context) ...@@ -75,13 +109,22 @@ static void dell_wmi_aio_notify(u32 value, void *context)
scancode, 1, true); scancode, 1, true);
break; break;
case ACPI_TYPE_BUFFER: case ACPI_TYPE_BUFFER:
/* Broken machines return the scancode in a buffer */ if (dell_wmi_aio_event_check(obj->buffer.pointer,
if (obj->buffer.pointer && obj->buffer.length > 0) { obj->buffer.length)) {
scancode = obj->buffer.pointer[0]; event = (struct dell_wmi_event *)
obj->buffer.pointer;
scancode = event->event[0];
} else {
/* Broken machines return the scancode in a
buffer */
if (obj->buffer.pointer &&
obj->buffer.length > 0)
scancode = obj->buffer.pointer[0];
}
if (scancode)
sparse_keymap_report_event( sparse_keymap_report_event(
dell_wmi_aio_input_dev, dell_wmi_aio_input_dev,
scancode, 1, true); scancode, 1, true);
}
break; break;
} }
} }
......
...@@ -71,6 +71,14 @@ enum hp_wmi_event_ids { ...@@ -71,6 +71,14 @@ enum hp_wmi_event_ids {
HPWMI_WIRELESS = 5, HPWMI_WIRELESS = 5,
HPWMI_CPU_BATTERY_THROTTLE = 6, HPWMI_CPU_BATTERY_THROTTLE = 6,
HPWMI_LOCK_SWITCH = 7, HPWMI_LOCK_SWITCH = 7,
HPWMI_LID_SWITCH = 8,
HPWMI_SCREEN_ROTATION = 9,
HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A,
HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B,
HPWMI_PROXIMITY_SENSOR = 0x0C,
HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
HPWMI_PEAKSHIFT_PERIOD = 0x0F,
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
}; };
struct bios_args { struct bios_args {
...@@ -536,6 +544,22 @@ static void hp_wmi_notify(u32 value, void *context) ...@@ -536,6 +544,22 @@ static void hp_wmi_notify(u32 value, void *context)
break; break;
case HPWMI_LOCK_SWITCH: case HPWMI_LOCK_SWITCH:
break; break;
case HPWMI_LID_SWITCH:
break;
case HPWMI_SCREEN_ROTATION:
break;
case HPWMI_COOLSENSE_SYSTEM_MOBILE:
break;
case HPWMI_COOLSENSE_SYSTEM_HOT:
break;
case HPWMI_PROXIMITY_SENSOR:
break;
case HPWMI_BACKLIT_KB_BRIGHTNESS:
break;
case HPWMI_PEAKSHIFT_PERIOD:
break;
case HPWMI_BATTERY_CHARGE_PERIOD:
break;
default: default:
pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data); pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
break; break;
......
...@@ -362,7 +362,8 @@ static int lis3lv02d_suspend(struct device *dev) ...@@ -362,7 +362,8 @@ static int lis3lv02d_suspend(struct device *dev)
static int lis3lv02d_resume(struct device *dev) static int lis3lv02d_resume(struct device *dev)
{ {
return lis3lv02d_poweron(&lis3_dev); lis3lv02d_poweron(&lis3_dev);
return 0;
} }
static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume); static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
......
...@@ -640,7 +640,8 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) ...@@ -640,7 +640,8 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
for (bit = 0; bit < 16; bit++) { for (bit = 0; bit < 16; bit++) {
if (test_bit(bit, &value)) { if (test_bit(bit, &value)) {
switch (bit) { switch (bit) {
case 6: case 0: /* Z580 */
case 6: /* Z570 */
/* Thermal Management button */ /* Thermal Management button */
ideapad_input_report(priv, 65); ideapad_input_report(priv, 65);
break; break;
...@@ -648,6 +649,9 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) ...@@ -648,6 +649,9 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
/* OneKey Theater button */ /* OneKey Theater button */
ideapad_input_report(priv, 64); ideapad_input_report(priv, 64);
break; break;
default:
pr_info("Unknown special button: %lu\n", bit);
break;
} }
} }
} }
......
/*
* pvpanic.c - pvpanic Device Support
*
* Copyright (C) 2013 Fujitsu.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
MODULE_DESCRIPTION("pvpanic device driver");
MODULE_LICENSE("GPL");
static int pvpanic_add(struct acpi_device *device);
static int pvpanic_remove(struct acpi_device *device);
static const struct acpi_device_id pvpanic_device_ids[] = {
{ "QEMU0001", 0 },
{ "", 0 },
};
MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids);
#define PVPANIC_PANICKED (1 << 0)
static u16 port;
static struct acpi_driver pvpanic_driver = {
.name = "pvpanic",
.class = "QEMU",
.ids = pvpanic_device_ids,
.ops = {
.add = pvpanic_add,
.remove = pvpanic_remove,
},
.owner = THIS_MODULE,
};
static void
pvpanic_send_event(unsigned int event)
{
outb(event, port);
}
static int
pvpanic_panic_notify(struct notifier_block *nb, unsigned long code,
void *unused)
{
pvpanic_send_event(PVPANIC_PANICKED);
return NOTIFY_DONE;
}
static struct notifier_block pvpanic_panic_nb = {
.notifier_call = pvpanic_panic_notify,
};
static acpi_status
pvpanic_walk_resources(struct acpi_resource *res, void *context)
{
switch (res->type) {
case ACPI_RESOURCE_TYPE_END_TAG:
return AE_OK;
case ACPI_RESOURCE_TYPE_IO:
port = res->data.io.minimum;
return AE_OK;
default:
return AE_ERROR;
}
}
static int pvpanic_add(struct acpi_device *device)
{
acpi_status status;
u64 ret;
status = acpi_evaluate_integer(device->handle, "_STA", NULL,
&ret);
if (ACPI_FAILURE(status) || (ret & 0x0B) != 0x0B)
return -ENODEV;
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
pvpanic_walk_resources, NULL);
if (!port)
return -ENODEV;
atomic_notifier_chain_register(&panic_notifier_list,
&pvpanic_panic_nb);
return 0;
}
static int pvpanic_remove(struct acpi_device *device)
{
atomic_notifier_chain_unregister(&panic_notifier_list,
&pvpanic_panic_nb);
return 0;
}
module_acpi_driver(pvpanic_driver);
...@@ -176,10 +176,7 @@ static int __init samsungq10_init(void) ...@@ -176,10 +176,7 @@ static int __init samsungq10_init(void)
samsungq10_probe, samsungq10_probe,
NULL, 0, NULL, 0); NULL, 0, NULL, 0);
if (IS_ERR(samsungq10_device)) return PTR_RET(samsungq10_device);
return PTR_ERR(samsungq10_device);
return 0;
} }
static void __exit samsungq10_exit(void) static void __exit samsungq10_exit(void)
......
...@@ -1255,6 +1255,11 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) ...@@ -1255,6 +1255,11 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
real_ev = __sony_nc_gfx_switch_status_get(); real_ev = __sony_nc_gfx_switch_status_get();
break; break;
case 0x015B:
/* Hybrid GFX switching SVS151290S */
ev_type = GFX_SWITCH;
real_ev = __sony_nc_gfx_switch_status_get();
break;
default: default:
dprintk("Unknown event 0x%x for handle 0x%x\n", dprintk("Unknown event 0x%x for handle 0x%x\n",
event, handle); event, handle);
...@@ -1353,6 +1358,7 @@ static void sony_nc_function_setup(struct acpi_device *device, ...@@ -1353,6 +1358,7 @@ static void sony_nc_function_setup(struct acpi_device *device,
break; break;
case 0x0128: case 0x0128:
case 0x0146: case 0x0146:
case 0x015B:
result = sony_nc_gfx_switch_setup(pf_device, handle); result = sony_nc_gfx_switch_setup(pf_device, handle);
if (result) if (result)
pr_err("couldn't set up GFX Switch status (%d)\n", pr_err("couldn't set up GFX Switch status (%d)\n",
...@@ -1375,6 +1381,7 @@ static void sony_nc_function_setup(struct acpi_device *device, ...@@ -1375,6 +1381,7 @@ static void sony_nc_function_setup(struct acpi_device *device,
case 0x0143: case 0x0143:
case 0x014b: case 0x014b:
case 0x014c: case 0x014c:
case 0x0163:
result = sony_nc_kbd_backlight_setup(pf_device, handle); result = sony_nc_kbd_backlight_setup(pf_device, handle);
if (result) if (result)
pr_err("couldn't set up keyboard backlight function (%d)\n", pr_err("couldn't set up keyboard backlight function (%d)\n",
...@@ -1426,6 +1433,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) ...@@ -1426,6 +1433,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
break; break;
case 0x0128: case 0x0128:
case 0x0146: case 0x0146:
case 0x015B:
sony_nc_gfx_switch_cleanup(pd); sony_nc_gfx_switch_cleanup(pd);
break; break;
case 0x0131: case 0x0131:
...@@ -1439,6 +1447,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) ...@@ -1439,6 +1447,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
case 0x0143: case 0x0143:
case 0x014b: case 0x014b:
case 0x014c: case 0x014c:
case 0x0163:
sony_nc_kbd_backlight_cleanup(pd); sony_nc_kbd_backlight_cleanup(pd);
break; break;
default: default:
...@@ -1485,6 +1494,7 @@ static void sony_nc_function_resume(void) ...@@ -1485,6 +1494,7 @@ static void sony_nc_function_resume(void)
case 0x0143: case 0x0143:
case 0x014b: case 0x014b:
case 0x014c: case 0x014c:
case 0x0163:
sony_nc_kbd_backlight_resume(); sony_nc_kbd_backlight_resume();
break; break;
default: default:
...@@ -2390,7 +2400,9 @@ static int __sony_nc_gfx_switch_status_get(void) ...@@ -2390,7 +2400,9 @@ static int __sony_nc_gfx_switch_status_get(void)
{ {
unsigned int result; unsigned int result;
if (sony_call_snc_handle(gfxs_ctl->handle, 0x0100, &result)) if (sony_call_snc_handle(gfxs_ctl->handle,
gfxs_ctl->handle == 0x015B ? 0x0000 : 0x0100,
&result))
return -EIO; return -EIO;
switch (gfxs_ctl->handle) { switch (gfxs_ctl->handle) {
...@@ -2400,6 +2412,12 @@ static int __sony_nc_gfx_switch_status_get(void) ...@@ -2400,6 +2412,12 @@ static int __sony_nc_gfx_switch_status_get(void)
*/ */
return result & 0x1 ? SPEED : STAMINA; return result & 0x1 ? SPEED : STAMINA;
break; break;
case 0x015B:
/* 0: discrete GFX (speed)
* 1: integrated GFX (stamina)
*/
return result & 0x1 ? STAMINA : SPEED;
break;
case 0x0128: case 0x0128:
/* it's a more elaborated bitmask, for now: /* it's a more elaborated bitmask, for now:
* 2: integrated GFX (stamina) * 2: integrated GFX (stamina)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment