You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86: (32 commits) Move N014, N051 and CR620 dmi information to load scm dmi table drivers/platform/x86/eeepc-wmi.c: fix build warning X86 platfrom wmi: Add debug facility to dump WMI data in a readable way X86 platform wmi: Also log GUID string when an event happens and debug is set X86 platform wmi: Introduce debug param to log all WMI events Clean up all objects used by scm model when driver initial fail or exit msi-laptop: fix up some coding style issues found by checkpatch msi-laptop: Add i8042 filter to sync sw state with BIOS when function key pressed msi-laptop: Set rfkill init state when msi-laptop intiial msi-laptop: Add MSI CR620 notebook dmi information to scm models table msi-laptop: Add N014 N051 dmi information to scm models table drivers/platform/x86: Use kmemdup drivers/platform/x86: Use kzalloc drivers/platform/x86: Clarify the MRST IPC driver description slightly eeepc-wmi: depends on BACKLIGHT_CLASS_DEVICE IPC driver for Intel Mobile Internet Device (MID) platforms classmate-laptop: Add RFKILL support. thinkpad-acpi: document backlight level writeback at driver init thinkpad-acpi: clean up ACPI handles handling thinkpad-acpi: don't depend on led_path for led firmware type (v2) ...
This commit is contained in:
@@ -292,13 +292,13 @@ sysfs notes:
|
||||
|
||||
Warning: when in NVRAM mode, the volume up/down/mute
|
||||
keys are synthesized according to changes in the mixer,
|
||||
so you have to use volume up or volume down to unmute,
|
||||
as per the ThinkPad volume mixer user interface. When
|
||||
in ACPI event mode, volume up/down/mute are reported as
|
||||
separate events, but this behaviour may be corrected in
|
||||
future releases of this driver, in which case the
|
||||
ThinkPad volume mixer user interface semantics will be
|
||||
enforced.
|
||||
which uses a single volume up or volume down hotkey
|
||||
press to unmute, as per the ThinkPad volume mixer user
|
||||
interface. When in ACPI event mode, volume up/down/mute
|
||||
events are reported by the firmware and can behave
|
||||
differently (and that behaviour changes with firmware
|
||||
version -- not just with firmware models -- as well as
|
||||
OSI(Linux) state).
|
||||
|
||||
hotkey_poll_freq:
|
||||
frequency in Hz for hot key polling. It must be between
|
||||
@@ -309,7 +309,7 @@ sysfs notes:
|
||||
will cause hot key presses that require NVRAM polling
|
||||
to never be reported.
|
||||
|
||||
Setting hotkey_poll_freq too low will cause repeated
|
||||
Setting hotkey_poll_freq too low may cause repeated
|
||||
pressings of the same hot key to be misreported as a
|
||||
single key press, or to not even be detected at all.
|
||||
The recommended polling frequency is 10Hz.
|
||||
@@ -397,6 +397,7 @@ ACPI Scan
|
||||
event code Key Notes
|
||||
|
||||
0x1001 0x00 FN+F1 -
|
||||
|
||||
0x1002 0x01 FN+F2 IBM: battery (rare)
|
||||
Lenovo: Screen lock
|
||||
|
||||
@@ -404,7 +405,8 @@ event code Key Notes
|
||||
this hot key, even with hot keys
|
||||
disabled or with Fn+F3 masked
|
||||
off
|
||||
IBM: screen lock
|
||||
IBM: screen lock, often turns
|
||||
off the ThinkLight as side-effect
|
||||
Lenovo: battery
|
||||
|
||||
0x1004 0x03 FN+F4 Sleep button (ACPI sleep button
|
||||
@@ -433,7 +435,8 @@ event code Key Notes
|
||||
Do you feel lucky today?
|
||||
|
||||
0x1008 0x07 FN+F8 IBM: toggle screen expand
|
||||
Lenovo: configure UltraNav
|
||||
Lenovo: configure UltraNav,
|
||||
or toggle screen expand
|
||||
|
||||
0x1009 0x08 FN+F9 -
|
||||
.. .. ..
|
||||
@@ -444,7 +447,7 @@ event code Key Notes
|
||||
either through the ACPI event,
|
||||
or through a hotkey event.
|
||||
The firmware may refuse to
|
||||
generate further FN+F4 key
|
||||
generate further FN+F12 key
|
||||
press events until a S3 or S4
|
||||
ACPI sleep cycle is performed,
|
||||
or some time passes.
|
||||
@@ -512,15 +515,19 @@ events for switches:
|
||||
SW_RFKILL_ALL T60 and later hardware rfkill rocker switch
|
||||
SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A
|
||||
|
||||
Non hot-key ACPI HKEY event map:
|
||||
Non hotkey ACPI HKEY event map:
|
||||
-------------------------------
|
||||
|
||||
Events that are not propagated by the driver, except for legacy
|
||||
compatibility purposes when hotkey_report_mode is set to 1:
|
||||
|
||||
0x5001 Lid closed
|
||||
0x5002 Lid opened
|
||||
0x5009 Tablet swivel: switched to tablet mode
|
||||
0x500A Tablet swivel: switched to normal mode
|
||||
0x7000 Radio Switch may have changed state
|
||||
|
||||
The above events are not propagated by the driver, except for legacy
|
||||
compatibility purposes when hotkey_report_mode is set to 1.
|
||||
Events that are never propagated by the driver:
|
||||
|
||||
0x2304 System is waking up from suspend to undock
|
||||
0x2305 System is waking up from suspend to eject bay
|
||||
@@ -528,14 +535,39 @@ compatibility purposes when hotkey_report_mode is set to 1.
|
||||
0x2405 System is waking up from hibernation to eject bay
|
||||
0x5010 Brightness level changed/control event
|
||||
|
||||
The above events are never propagated by the driver.
|
||||
Events that are propagated by the driver to userspace:
|
||||
|
||||
0x2313 ALARM: System is waking up from suspend because
|
||||
the battery is nearly empty
|
||||
0x2413 ALARM: System is waking up from hibernation because
|
||||
the battery is nearly empty
|
||||
0x3003 Bay ejection (see 0x2x05) complete, can sleep again
|
||||
0x3006 Bay hotplug request (hint to power up SATA link when
|
||||
the optical drive tray is ejected)
|
||||
0x4003 Undocked (see 0x2x04), can sleep again
|
||||
0x500B Tablet pen inserted into its storage bay
|
||||
0x500C Tablet pen removed from its storage bay
|
||||
0x6011 ALARM: battery is too hot
|
||||
0x6012 ALARM: battery is extremely hot
|
||||
0x6021 ALARM: a sensor is too hot
|
||||
0x6022 ALARM: a sensor is extremely hot
|
||||
0x6030 System thermal table changed
|
||||
|
||||
The above events are propagated by the driver.
|
||||
Battery nearly empty alarms are a last resort attempt to get the
|
||||
operating system to hibernate or shutdown cleanly (0x2313), or shutdown
|
||||
cleanly (0x2413) before power is lost. They must be acted upon, as the
|
||||
wake up caused by the firmware will have negated most safety nets...
|
||||
|
||||
When any of the "too hot" alarms happen, according to Lenovo the user
|
||||
should suspend or hibernate the laptop (and in the case of battery
|
||||
alarms, unplug the AC adapter) to let it cool down. These alarms do
|
||||
signal that something is wrong, they should never happen on normal
|
||||
operating conditions.
|
||||
|
||||
The "extremely hot" alarms are emergencies. According to Lenovo, the
|
||||
operating system is to force either an immediate suspend or hibernate
|
||||
cycle, or a system shutdown. Obviously, something is very wrong if this
|
||||
happens.
|
||||
|
||||
Compatibility notes:
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef _ASM_X86_INTEL_SCU_IPC_H_
|
||||
#define _ASM_X86_INTEL_SCU_IPC_H_
|
||||
|
||||
/* Read single register */
|
||||
int intel_scu_ipc_ioread8(u16 addr, u8 *data);
|
||||
|
||||
/* Read two sequential registers */
|
||||
int intel_scu_ipc_ioread16(u16 addr, u16 *data);
|
||||
|
||||
/* Read four sequential registers */
|
||||
int intel_scu_ipc_ioread32(u16 addr, u32 *data);
|
||||
|
||||
/* Read a vector */
|
||||
int intel_scu_ipc_readv(u16 *addr, u8 *data, int len);
|
||||
|
||||
/* Write single register */
|
||||
int intel_scu_ipc_iowrite8(u16 addr, u8 data);
|
||||
|
||||
/* Write two sequential registers */
|
||||
int intel_scu_ipc_iowrite16(u16 addr, u16 data);
|
||||
|
||||
/* Write four sequential registers */
|
||||
int intel_scu_ipc_iowrite32(u16 addr, u32 data);
|
||||
|
||||
/* Write a vector */
|
||||
int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);
|
||||
|
||||
/* Update single register based on the mask */
|
||||
int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
|
||||
|
||||
/*
|
||||
* Indirect register read
|
||||
* Can be used when SCCB(System Controller Configuration Block) register
|
||||
* HRIM(Honor Restricted IPC Messages) is set (bit 23)
|
||||
*/
|
||||
int intel_scu_ipc_register_read(u32 addr, u32 *data);
|
||||
|
||||
/*
|
||||
* Indirect register write
|
||||
* Can be used when SCCB(System Controller Configuration Block) register
|
||||
* HRIM(Honor Restricted IPC Messages) is set (bit 23)
|
||||
*/
|
||||
int intel_scu_ipc_register_write(u32 addr, u32 data);
|
||||
|
||||
/* Issue commands to the SCU with or without data */
|
||||
int intel_scu_ipc_simple_command(int cmd, int sub);
|
||||
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
|
||||
u32 *out, int outlen);
|
||||
/* I2C control api */
|
||||
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
|
||||
|
||||
/* Update FW version */
|
||||
int intel_scu_ipc_fw_update(u8 *buffer, u32 length);
|
||||
|
||||
#endif
|
||||
@@ -390,6 +390,7 @@ config EEEPC_WMI
|
||||
depends on ACPI_WMI
|
||||
depends on INPUT
|
||||
depends on EXPERIMENTAL
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select INPUT_SPARSEKMAP
|
||||
---help---
|
||||
Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
|
||||
@@ -527,4 +528,13 @@ config ACPI_CMPC
|
||||
keys as input device, backlight device, tablet and accelerometer
|
||||
devices.
|
||||
|
||||
config INTEL_SCU_IPC
|
||||
bool "Intel SCU IPC Support"
|
||||
depends on X86_MRST
|
||||
default y
|
||||
---help---
|
||||
IPC is used to bridge the communications between kernel and SCU on
|
||||
some embedded Intel x86 platforms. This is not needed for PC-type
|
||||
machines.
|
||||
|
||||
endif # X86_PLATFORM_DEVICES
|
||||
|
||||
@@ -25,3 +25,4 @@ obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
|
||||
obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
|
||||
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
|
||||
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
|
||||
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -37,7 +38,7 @@ struct cmpc_accel {
|
||||
|
||||
#define CMPC_ACCEL_HID "ACCE0000"
|
||||
#define CMPC_TABLET_HID "TBLT0000"
|
||||
#define CMPC_BL_HID "IPML200"
|
||||
#define CMPC_IPML_HID "IPML200"
|
||||
#define CMPC_KEYS_HID "FnBT0000"
|
||||
|
||||
/*
|
||||
@@ -461,43 +462,168 @@ static const struct backlight_ops cmpc_bl_ops = {
|
||||
.update_status = cmpc_bl_update_status
|
||||
};
|
||||
|
||||
static int cmpc_bl_add(struct acpi_device *acpi)
|
||||
/*
|
||||
* RFKILL code.
|
||||
*/
|
||||
|
||||
static acpi_status cmpc_get_rfkill_wlan(acpi_handle handle,
|
||||
unsigned long long *value)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
union acpi_object param;
|
||||
struct acpi_object_list input;
|
||||
unsigned long long output;
|
||||
acpi_status status;
|
||||
|
||||
param.type = ACPI_TYPE_INTEGER;
|
||||
param.integer.value = 0xC1;
|
||||
input.count = 1;
|
||||
input.pointer = ¶m;
|
||||
status = acpi_evaluate_integer(handle, "GRDI", &input, &output);
|
||||
if (ACPI_SUCCESS(status))
|
||||
*value = output;
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status cmpc_set_rfkill_wlan(acpi_handle handle,
|
||||
unsigned long long value)
|
||||
{
|
||||
union acpi_object param[2];
|
||||
struct acpi_object_list input;
|
||||
acpi_status status;
|
||||
unsigned long long output;
|
||||
|
||||
param[0].type = ACPI_TYPE_INTEGER;
|
||||
param[0].integer.value = 0xC1;
|
||||
param[1].type = ACPI_TYPE_INTEGER;
|
||||
param[1].integer.value = value;
|
||||
input.count = 2;
|
||||
input.pointer = param;
|
||||
status = acpi_evaluate_integer(handle, "GWRI", &input, &output);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void cmpc_rfkill_query(struct rfkill *rfkill, void *data)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
unsigned long long state;
|
||||
bool blocked;
|
||||
|
||||
handle = data;
|
||||
status = cmpc_get_rfkill_wlan(handle, &state);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
blocked = state & 1 ? false : true;
|
||||
rfkill_set_sw_state(rfkill, blocked);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmpc_rfkill_block(void *data, bool blocked)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
unsigned long long state;
|
||||
|
||||
handle = data;
|
||||
status = cmpc_get_rfkill_wlan(handle, &state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
if (blocked)
|
||||
state &= ~1;
|
||||
else
|
||||
state |= 1;
|
||||
status = cmpc_set_rfkill_wlan(handle, state);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rfkill_ops cmpc_rfkill_ops = {
|
||||
.query = cmpc_rfkill_query,
|
||||
.set_block = cmpc_rfkill_block,
|
||||
};
|
||||
|
||||
/*
|
||||
* Common backlight and rfkill code.
|
||||
*/
|
||||
|
||||
struct ipml200_dev {
|
||||
struct backlight_device *bd;
|
||||
struct rfkill *rf;
|
||||
};
|
||||
|
||||
static int cmpc_ipml_add(struct acpi_device *acpi)
|
||||
{
|
||||
int retval;
|
||||
struct ipml200_dev *ipml;
|
||||
struct backlight_properties props;
|
||||
|
||||
ipml = kmalloc(sizeof(*ipml), GFP_KERNEL);
|
||||
if (ipml == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 7;
|
||||
bd = backlight_device_register("cmpc_bl", &acpi->dev, acpi->handle,
|
||||
&cmpc_bl_ops, &props);
|
||||
if (IS_ERR(bd))
|
||||
return PTR_ERR(bd);
|
||||
dev_set_drvdata(&acpi->dev, bd);
|
||||
return 0;
|
||||
ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
|
||||
acpi->handle, &cmpc_bl_ops,
|
||||
&props);
|
||||
if (IS_ERR(ipml->bd)) {
|
||||
retval = PTR_ERR(ipml->bd);
|
||||
goto out_bd;
|
||||
}
|
||||
|
||||
static int cmpc_bl_remove(struct acpi_device *acpi, int type)
|
||||
ipml->rf = rfkill_alloc("cmpc_rfkill", &acpi->dev, RFKILL_TYPE_WLAN,
|
||||
&cmpc_rfkill_ops, acpi->handle);
|
||||
/* rfkill_alloc may fail if RFKILL is disabled. We should still work
|
||||
* anyway. */
|
||||
if (!IS_ERR(ipml->rf)) {
|
||||
retval = rfkill_register(ipml->rf);
|
||||
if (retval) {
|
||||
rfkill_destroy(ipml->rf);
|
||||
ipml->rf = NULL;
|
||||
}
|
||||
} else {
|
||||
ipml->rf = NULL;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&acpi->dev, ipml);
|
||||
return 0;
|
||||
|
||||
out_bd:
|
||||
kfree(ipml);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cmpc_ipml_remove(struct acpi_device *acpi, int type)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
struct ipml200_dev *ipml;
|
||||
|
||||
ipml = dev_get_drvdata(&acpi->dev);
|
||||
|
||||
backlight_device_unregister(ipml->bd);
|
||||
|
||||
if (ipml->rf) {
|
||||
rfkill_unregister(ipml->rf);
|
||||
rfkill_destroy(ipml->rf);
|
||||
}
|
||||
|
||||
kfree(ipml);
|
||||
|
||||
bd = dev_get_drvdata(&acpi->dev);
|
||||
backlight_device_unregister(bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cmpc_bl_device_ids[] = {
|
||||
{CMPC_BL_HID, 0},
|
||||
static const struct acpi_device_id cmpc_ipml_device_ids[] = {
|
||||
{CMPC_IPML_HID, 0},
|
||||
{"", 0}
|
||||
};
|
||||
|
||||
static struct acpi_driver cmpc_bl_acpi_driver = {
|
||||
static struct acpi_driver cmpc_ipml_acpi_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cmpc",
|
||||
.class = "cmpc",
|
||||
.ids = cmpc_bl_device_ids,
|
||||
.ids = cmpc_ipml_device_ids,
|
||||
.ops = {
|
||||
.add = cmpc_bl_add,
|
||||
.remove = cmpc_bl_remove
|
||||
.add = cmpc_ipml_add,
|
||||
.remove = cmpc_ipml_remove
|
||||
}
|
||||
};
|
||||
|
||||
@@ -580,7 +706,7 @@ static int cmpc_init(void)
|
||||
if (r)
|
||||
goto failed_keys;
|
||||
|
||||
r = acpi_bus_register_driver(&cmpc_bl_acpi_driver);
|
||||
r = acpi_bus_register_driver(&cmpc_ipml_acpi_driver);
|
||||
if (r)
|
||||
goto failed_bl;
|
||||
|
||||
@@ -598,7 +724,7 @@ failed_accel:
|
||||
acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver);
|
||||
|
||||
failed_tablet:
|
||||
acpi_bus_unregister_driver(&cmpc_bl_acpi_driver);
|
||||
acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver);
|
||||
|
||||
failed_bl:
|
||||
acpi_bus_unregister_driver(&cmpc_keys_acpi_driver);
|
||||
@@ -611,7 +737,7 @@ static void cmpc_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&cmpc_accel_acpi_driver);
|
||||
acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver);
|
||||
acpi_bus_unregister_driver(&cmpc_bl_acpi_driver);
|
||||
acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver);
|
||||
acpi_bus_unregister_driver(&cmpc_keys_acpi_driver);
|
||||
}
|
||||
|
||||
@@ -621,7 +747,7 @@ 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_IPML_HID, 0},
|
||||
{CMPC_KEYS_HID, 0},
|
||||
{"", 0}
|
||||
};
|
||||
|
||||
@@ -206,7 +206,7 @@ static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
|
||||
{
|
||||
struct backlight_device *bd = eeepc->backlight_device;
|
||||
int old = bd->props.brightness;
|
||||
int new;
|
||||
int new = old;
|
||||
|
||||
if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
|
||||
new = code - NOTIFY_BRNUP_MIN + 1;
|
||||
|
||||
@@ -1090,10 +1090,9 @@ static int __init fujitsu_init(void)
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
fujitsu = kmalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
|
||||
fujitsu = kzalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
|
||||
if (!fujitsu)
|
||||
return -ENOMEM;
|
||||
memset(fujitsu, 0, sizeof(struct fujitsu_t));
|
||||
fujitsu->keycode1 = KEY_PROG1;
|
||||
fujitsu->keycode2 = KEY_PROG2;
|
||||
fujitsu->keycode3 = KEY_PROG3;
|
||||
@@ -1150,12 +1149,11 @@ static int __init fujitsu_init(void)
|
||||
|
||||
/* Register hotkey driver */
|
||||
|
||||
fujitsu_hotkey = kmalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL);
|
||||
fujitsu_hotkey = kzalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL);
|
||||
if (!fujitsu_hotkey) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_hotkey;
|
||||
}
|
||||
memset(fujitsu_hotkey, 0, sizeof(struct fujitsu_hotkey_t));
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_fujitsu_hotkey_driver);
|
||||
if (result < 0) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,7 @@
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/i8042.h>
|
||||
|
||||
#define MSI_DRIVER_VERSION "0.5"
|
||||
|
||||
@@ -118,7 +119,8 @@ static int set_lcd_level(int level)
|
||||
buf[0] = 0x80;
|
||||
buf[1] = (u8) (level*31);
|
||||
|
||||
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0, 1);
|
||||
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf),
|
||||
NULL, 0, 1);
|
||||
}
|
||||
|
||||
static int get_lcd_level(void)
|
||||
@@ -126,7 +128,8 @@ static int get_lcd_level(void)
|
||||
u8 wdata = 0, rdata;
|
||||
int result;
|
||||
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1);
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1,
|
||||
&rdata, 1, 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -138,7 +141,8 @@ static int get_auto_brightness(void)
|
||||
u8 wdata = 4, rdata;
|
||||
int result;
|
||||
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1);
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1,
|
||||
&rdata, 1, 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
@@ -152,14 +156,16 @@ static int set_auto_brightness(int enable)
|
||||
|
||||
wdata[0] = 4;
|
||||
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1, 1);
|
||||
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1,
|
||||
&rdata, 1, 1);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
wdata[0] = 0x84;
|
||||
wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0);
|
||||
|
||||
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1);
|
||||
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)
|
||||
@@ -254,7 +260,7 @@ static int bl_update_status(struct backlight_device *b)
|
||||
return set_lcd_level(b->props.brightness);
|
||||
}
|
||||
|
||||
static struct backlight_ops msibl_ops = {
|
||||
static const struct backlight_ops msibl_ops = {
|
||||
.get_brightness = bl_get_brightness,
|
||||
.update_status = bl_update_status,
|
||||
};
|
||||
@@ -353,7 +359,8 @@ static ssize_t store_lcd_level(struct device *dev,
|
||||
|
||||
int level, ret;
|
||||
|
||||
if (sscanf(buf, "%i", &level) != 1 || (level < 0 || level >= MSI_LCD_LEVEL_MAX))
|
||||
if (sscanf(buf, "%i", &level) != 1 ||
|
||||
(level < 0 || level >= MSI_LCD_LEVEL_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
ret = set_lcd_level(level);
|
||||
@@ -393,7 +400,8 @@ static ssize_t store_auto_brightness(struct device *dev,
|
||||
}
|
||||
|
||||
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(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);
|
||||
@@ -424,7 +432,8 @@ static struct platform_device *msipf_device;
|
||||
|
||||
static int dmi_check_cb(const struct dmi_system_id *id)
|
||||
{
|
||||
printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
|
||||
printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n",
|
||||
id->ident);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -435,7 +444,8 @@ static struct dmi_system_id __initdata msi_dmi_table[] = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR,
|
||||
"MICRO-STAR INT'L CO.,LTD")
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
@@ -465,7 +475,8 @@ static struct dmi_system_id __initdata msi_dmi_table[] = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR,
|
||||
"MICRO-STAR INT'L CO.,LTD")
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
@@ -484,6 +495,35 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "MSI N051",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"MICRO-STAR INTERNATIONAL CO., LTD"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MS-N051"),
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR,
|
||||
"MICRO-STAR INTERNATIONAL CO., LTD")
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "MSI N014",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"MICRO-STAR INTERNATIONAL CO., LTD"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MS-N014"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "MSI CR620",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"Micro-Star International"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CR620"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -552,11 +592,71 @@ static void rfkill_cleanup(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void msi_update_rfkill(struct work_struct *ignored)
|
||||
{
|
||||
get_wireless_state_ec_standard();
|
||||
|
||||
if (rfk_wlan)
|
||||
rfkill_set_sw_state(rfk_wlan, !wlan_s);
|
||||
if (rfk_bluetooth)
|
||||
rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
|
||||
if (rfk_threeg)
|
||||
rfkill_set_sw_state(rfk_threeg, !threeg_s);
|
||||
}
|
||||
static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill);
|
||||
|
||||
static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
|
||||
struct serio *port)
|
||||
{
|
||||
static bool extended;
|
||||
|
||||
if (str & 0x20)
|
||||
return false;
|
||||
|
||||
/* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/
|
||||
if (unlikely(data == 0xe0)) {
|
||||
extended = true;
|
||||
return false;
|
||||
} else if (unlikely(extended)) {
|
||||
switch (data) {
|
||||
case 0x54:
|
||||
case 0x62:
|
||||
case 0x76:
|
||||
schedule_delayed_work(&msi_rfkill_work,
|
||||
round_jiffies_relative(0.5 * HZ));
|
||||
break;
|
||||
}
|
||||
extended = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void msi_init_rfkill(struct work_struct *ignored)
|
||||
{
|
||||
if (rfk_wlan) {
|
||||
rfkill_set_sw_state(rfk_wlan, !wlan_s);
|
||||
rfkill_wlan_set(NULL, !wlan_s);
|
||||
}
|
||||
if (rfk_bluetooth) {
|
||||
rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
|
||||
rfkill_bluetooth_set(NULL, !bluetooth_s);
|
||||
}
|
||||
if (rfk_threeg) {
|
||||
rfkill_set_sw_state(rfk_threeg, !threeg_s);
|
||||
rfkill_threeg_set(NULL, !threeg_s);
|
||||
}
|
||||
}
|
||||
static DECLARE_DELAYED_WORK(msi_rfkill_init, msi_init_rfkill);
|
||||
|
||||
static int rfkill_init(struct platform_device *sdev)
|
||||
{
|
||||
/* add rfkill */
|
||||
int retval;
|
||||
|
||||
/* keep the hardware wireless state */
|
||||
get_wireless_state_ec_standard();
|
||||
|
||||
rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev,
|
||||
RFKILL_TYPE_BLUETOOTH,
|
||||
&rfkill_bluetooth_ops, NULL);
|
||||
@@ -590,6 +690,10 @@ static int rfkill_init(struct platform_device *sdev)
|
||||
goto err_threeg;
|
||||
}
|
||||
|
||||
/* schedule to run rfkill state initial */
|
||||
schedule_delayed_work(&msi_rfkill_init,
|
||||
round_jiffies_relative(1 * HZ));
|
||||
|
||||
return 0;
|
||||
|
||||
err_threeg:
|
||||
@@ -653,9 +757,24 @@ static int load_scm_model_init(struct platform_device *sdev)
|
||||
/* initial rfkill */
|
||||
result = rfkill_init(sdev);
|
||||
if (result < 0)
|
||||
return result;
|
||||
goto fail_rfkill;
|
||||
|
||||
result = i8042_install_filter(msi_laptop_i8042_filter);
|
||||
if (result) {
|
||||
printk(KERN_ERR
|
||||
"msi-laptop: Unable to install key filter\n");
|
||||
goto fail_filter;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_filter:
|
||||
rfkill_cleanup();
|
||||
|
||||
fail_rfkill:
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int __init msi_init(void)
|
||||
@@ -714,7 +833,8 @@ static int __init msi_init(void)
|
||||
goto fail_platform_device1;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
|
||||
ret = sysfs_create_group(&msipf_device->dev.kobj,
|
||||
&msipf_attribute_group);
|
||||
if (ret)
|
||||
goto fail_platform_device2;
|
||||
|
||||
@@ -739,6 +859,11 @@ static int __init msi_init(void)
|
||||
|
||||
fail_platform_device2:
|
||||
|
||||
if (load_scm_model) {
|
||||
i8042_remove_filter(msi_laptop_i8042_filter);
|
||||
cancel_delayed_work_sync(&msi_rfkill_work);
|
||||
rfkill_cleanup();
|
||||
}
|
||||
platform_device_del(msipf_device);
|
||||
|
||||
fail_platform_device1:
|
||||
@@ -758,6 +883,11 @@ fail_backlight:
|
||||
|
||||
static void __exit msi_cleanup(void)
|
||||
{
|
||||
if (load_scm_model) {
|
||||
i8042_remove_filter(msi_laptop_i8042_filter);
|
||||
cancel_delayed_work_sync(&msi_rfkill_work);
|
||||
rfkill_cleanup();
|
||||
}
|
||||
|
||||
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
|
||||
if (!old_ec_model && threeg_exists)
|
||||
@@ -766,8 +896,6 @@ 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);
|
||||
@@ -788,3 +916,6 @@ MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-105
|
||||
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:*");
|
||||
MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*");
|
||||
MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*");
|
||||
MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -81,6 +81,16 @@ static struct wmi_block wmi_blocks;
|
||||
#define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */
|
||||
#define ACPI_WMI_EVENT 0x8 /* GUID is an event */
|
||||
|
||||
static int debug_event;
|
||||
module_param(debug_event, bool, 0444);
|
||||
MODULE_PARM_DESC(debug_event,
|
||||
"Log WMI Events [0/1]");
|
||||
|
||||
static int debug_dump_wdg;
|
||||
module_param(debug_dump_wdg, bool, 0444);
|
||||
MODULE_PARM_DESC(debug_dump_wdg,
|
||||
"Dump available WMI interfaces [0/1]");
|
||||
|
||||
static int acpi_wmi_remove(struct acpi_device *device, int type);
|
||||
static int acpi_wmi_add(struct acpi_device *device);
|
||||
static void acpi_wmi_notify(struct acpi_device *device, u32 event);
|
||||
@@ -477,6 +487,64 @@ const struct acpi_buffer *in)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wmi_set_block);
|
||||
|
||||
static void wmi_dump_wdg(struct guid_block *g)
|
||||
{
|
||||
char guid_string[37];
|
||||
|
||||
wmi_gtoa(g->guid, guid_string);
|
||||
printk(KERN_INFO PREFIX "%s:\n", guid_string);
|
||||
printk(KERN_INFO PREFIX "\tobject_id: %c%c\n",
|
||||
g->object_id[0], g->object_id[1]);
|
||||
printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id);
|
||||
printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved);
|
||||
printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count);
|
||||
printk(KERN_INFO PREFIX "\tflags: %#x", g->flags);
|
||||
if (g->flags) {
|
||||
printk(" ");
|
||||
if (g->flags & ACPI_WMI_EXPENSIVE)
|
||||
printk("ACPI_WMI_EXPENSIVE ");
|
||||
if (g->flags & ACPI_WMI_METHOD)
|
||||
printk("ACPI_WMI_METHOD ");
|
||||
if (g->flags & ACPI_WMI_STRING)
|
||||
printk("ACPI_WMI_STRING ");
|
||||
if (g->flags & ACPI_WMI_EVENT)
|
||||
printk("ACPI_WMI_EVENT ");
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
}
|
||||
|
||||
static void wmi_notify_debug(u32 value, void *context)
|
||||
{
|
||||
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *obj;
|
||||
|
||||
wmi_get_event_data(value, &response);
|
||||
|
||||
obj = (union acpi_object *)response.pointer;
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
printk(KERN_INFO PREFIX "DEBUG Event ");
|
||||
switch(obj->type) {
|
||||
case ACPI_TYPE_BUFFER:
|
||||
printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
|
||||
break;
|
||||
case ACPI_TYPE_STRING:
|
||||
printk("STRING_TYPE - %s\n", obj->string.pointer);
|
||||
break;
|
||||
case ACPI_TYPE_INTEGER:
|
||||
printk("INTEGER_TYPE - %llu\n", obj->integer.value);
|
||||
break;
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
|
||||
break;
|
||||
default:
|
||||
printk("object type 0x%X\n", obj->type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wmi_install_notify_handler - Register handler for WMI events
|
||||
* @handler: Function to handle notifications
|
||||
@@ -496,7 +564,7 @@ wmi_notify_handler handler, void *data)
|
||||
if (!find_guid(guid, &block))
|
||||
return AE_NOT_EXIST;
|
||||
|
||||
if (block->handler)
|
||||
if (block->handler && block->handler != wmi_notify_debug)
|
||||
return AE_ALREADY_ACQUIRED;
|
||||
|
||||
block->handler = handler;
|
||||
@@ -516,7 +584,7 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
|
||||
acpi_status wmi_remove_notify_handler(const char *guid)
|
||||
{
|
||||
struct wmi_block *block;
|
||||
acpi_status status;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (!guid)
|
||||
return AE_BAD_PARAMETER;
|
||||
@@ -524,14 +592,16 @@ acpi_status wmi_remove_notify_handler(const char *guid)
|
||||
if (!find_guid(guid, &block))
|
||||
return AE_NOT_EXIST;
|
||||
|
||||
if (!block->handler)
|
||||
if (!block->handler || block->handler == wmi_notify_debug)
|
||||
return AE_NULL_ENTRY;
|
||||
|
||||
if (debug_event) {
|
||||
block->handler = wmi_notify_debug;
|
||||
} else {
|
||||
status = wmi_method_enable(block, 0);
|
||||
|
||||
block->handler = NULL;
|
||||
block->handler_data = NULL;
|
||||
|
||||
}
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
|
||||
@@ -756,12 +826,10 @@ static __init acpi_status parse_wdg(acpi_handle handle)
|
||||
|
||||
total = obj->buffer.length / sizeof(struct guid_block);
|
||||
|
||||
gblock = kzalloc(obj->buffer.length, GFP_KERNEL);
|
||||
gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
|
||||
if (!gblock)
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
/*
|
||||
Some WMI devices, like those for nVidia hooks, have a
|
||||
@@ -776,12 +844,19 @@ static __init acpi_status parse_wdg(acpi_handle handle)
|
||||
guid_string);
|
||||
continue;
|
||||
}
|
||||
if (debug_dump_wdg)
|
||||
wmi_dump_wdg(&gblock[i]);
|
||||
|
||||
wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
|
||||
if (!wblock)
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
wblock->gblock = gblock[i];
|
||||
wblock->handle = handle;
|
||||
if (debug_event) {
|
||||
wblock->handler = wmi_notify_debug;
|
||||
status = wmi_method_enable(wblock, 1);
|
||||
}
|
||||
list_add_tail(&wblock->list, &wmi_blocks.list);
|
||||
}
|
||||
|
||||
@@ -840,6 +915,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
|
||||
struct guid_block *block;
|
||||
struct wmi_block *wblock;
|
||||
struct list_head *p;
|
||||
char guid_string[37];
|
||||
|
||||
list_for_each(p, &wmi_blocks.list) {
|
||||
wblock = list_entry(p, struct wmi_block, list);
|
||||
@@ -849,6 +925,11 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
|
||||
(block->notify_id == event)) {
|
||||
if (wblock->handler)
|
||||
wblock->handler(event, wblock->handler_data);
|
||||
if (debug_event) {
|
||||
wmi_gtoa(wblock->gblock.guid, guid_string);
|
||||
printk(KERN_INFO PREFIX "DEBUG Event GUID:"
|
||||
" %s\n", guid_string);
|
||||
}
|
||||
|
||||
acpi_bus_generate_netlink_event(
|
||||
device->pnp.device_class, dev_name(&device->dev),
|
||||
|
||||
Reference in New Issue
Block a user