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: (38 commits) acer-wmi: support Lenovo ideapad S205 wifi switch acerhdf.c: spaces in aliased changed to * platform-drivers-x86: ideapad-laptop: add missing ideapad_input_exit in ideapad_acpi_add error path x86 driver: fix typo in TDP override enabling Platform: fix samsung-laptop DMI identification for N150/N210/220/N230 dell-wmi: Add keys for Dell XPS L502X platform-drivers-x86: samsung-q10: make dmi_check_callback return 1 Platform: Samsung Q10 backlight driver platform-drivers-x86: intel_scu_ipc: convert to DEFINE_PCI_DEVICE_TABLE platform-drivers-x86: intel_rar_register: convert to DEFINE_PCI_DEVICE_TABLE platform-drivers-x86: intel_menlow: add missing return AE_OK for intel_menlow_register_sensor() platform-drivers-x86: intel_mid_thermal: fix memory leak platform-drivers-x86: msi-wmi: add missing sparse_keymap_free in msi_wmi_init error path Samsung Laptop platform driver: support N510 asus-wmi: add uwb rfkill support asus-wmi: add gps rfkill support asus-wmi: add CWAP support and clarify the meaning of WAPF bits asus-wmi: return proper value in store_cpufv() asus-wmi: check for temp1 presence asus-wmi: add thermal sensor ...
This commit is contained in:
Коммит
2560540b78
|
@ -4,3 +4,20 @@ KernelVersion: 2.6.37
|
|||
Contact: "Ike Panhc <ike.pan@canonical.com>"
|
||||
Description:
|
||||
Control the power of camera module. 1 means on, 0 means off.
|
||||
|
||||
What: /sys/devices/platform/ideapad/cfg
|
||||
Date: Jun 2011
|
||||
KernelVersion: 3.1
|
||||
Contact: "Ike Panhc <ike.pan@canonical.com>"
|
||||
Description:
|
||||
Ideapad capability bits.
|
||||
Bit 8-10: 1 - Intel graphic only
|
||||
2 - ATI graphic only
|
||||
3 - Nvidia graphic only
|
||||
4 - Intel and ATI graphic
|
||||
5 - Intel and Nvidia graphic
|
||||
Bit 16: Bluetooth exist (1 for exist)
|
||||
Bit 17: 3G exist (1 for exist)
|
||||
Bit 18: Wifi exist (1 for exist)
|
||||
Bit 19: Camera exist (1 for exist)
|
||||
|
||||
|
|
|
@ -581,3 +581,14 @@ Why: This driver has been superseded by g_mass_storage.
|
|||
Who: Alan Stern <stern@rowland.harvard.edu>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: threeg and interface sysfs files in /sys/devices/platform/acer-wmi
|
||||
When: 2012
|
||||
Why: In 3.0, we can now autodetect internal 3G device and already have
|
||||
the threeg rfkill device. So, we plan to remove threeg sysfs support
|
||||
for it's no longer necessary.
|
||||
|
||||
We also plan to remove interface sysfs file that exposed which ACPI-WMI
|
||||
interface that was used by acer-wmi driver. It will replaced by
|
||||
information log when acer-wmi initial.
|
||||
Who: Lee, Chun-Yi <jlee@novell.com>
|
||||
|
|
|
@ -769,4 +769,12 @@ config INTEL_OAKTRAIL
|
|||
enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
|
||||
here; it will only load on supported platforms.
|
||||
|
||||
config SAMSUNG_Q10
|
||||
tristate "Samsung Q10 Extras"
|
||||
depends on SERIO_I8042
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This driver provides support for backlight control on Samsung Q10
|
||||
and related laptops, including Dell Latitude X200.
|
||||
|
||||
endif # X86_PLATFORM_DEVICES
|
||||
|
|
|
@ -44,3 +44,4 @@ obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
|
|||
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
|
||||
obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o
|
||||
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
|
||||
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
|
||||
|
|
|
@ -99,6 +99,7 @@ enum acer_wmi_event_ids {
|
|||
static const struct key_entry acer_wmi_keymap[] = {
|
||||
{KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
|
||||
{KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
|
||||
{KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */
|
||||
{KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
|
||||
{KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
|
||||
{KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
|
||||
|
@ -304,6 +305,10 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
|
|||
.wireless = 2,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_lenovo_ideapad_s205 = {
|
||||
.wireless = 3,
|
||||
};
|
||||
|
||||
/* The Aspire One has a dummy ACPI-WMI interface - disable it */
|
||||
static struct dmi_system_id __devinitdata acer_blacklist[] = {
|
||||
{
|
||||
|
@ -450,6 +455,15 @@ static struct dmi_system_id acer_quirks[] = {
|
|||
},
|
||||
.driver_data = &quirk_medion_md_98300,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Lenovo Ideapad S205",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
|
||||
},
|
||||
.driver_data = &quirk_lenovo_ideapad_s205,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -542,6 +556,12 @@ struct wmi_interface *iface)
|
|||
return AE_ERROR;
|
||||
*value = result & 0x1;
|
||||
return AE_OK;
|
||||
case 3:
|
||||
err = ec_read(0x78, &result);
|
||||
if (err)
|
||||
return AE_ERROR;
|
||||
*value = result & 0x1;
|
||||
return AE_OK;
|
||||
default:
|
||||
err = ec_read(0xA, &result);
|
||||
if (err)
|
||||
|
@ -1266,8 +1286,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
|
|||
acpi_status status;
|
||||
|
||||
status = get_u32(&state, ACER_CAP_WIRELESS);
|
||||
if (ACPI_SUCCESS(status))
|
||||
rfkill_set_sw_state(wireless_rfkill, !state);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (quirks->wireless == 3) {
|
||||
rfkill_set_hw_state(wireless_rfkill, !state);
|
||||
} else {
|
||||
rfkill_set_sw_state(wireless_rfkill, !state);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_cap(ACER_CAP_BLUETOOTH)) {
|
||||
status = get_u32(&state, ACER_CAP_BLUETOOTH);
|
||||
|
@ -1400,6 +1425,9 @@ static ssize_t show_bool_threeg(struct device *dev,
|
|||
{
|
||||
u32 result; \
|
||||
acpi_status status;
|
||||
|
||||
pr_info("This threeg sysfs will be removed in 2012"
|
||||
" - used by: %s\n", current->comm);
|
||||
if (wmi_has_guid(WMID_GUID3))
|
||||
status = wmid3_get_device_status(&result,
|
||||
ACER_WMID3_GDS_THREEG);
|
||||
|
@ -1415,8 +1443,10 @@ static ssize_t set_bool_threeg(struct device *dev,
|
|||
{
|
||||
u32 tmp = simple_strtoul(buf, NULL, 10);
|
||||
acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EINVAL;
|
||||
pr_info("This threeg sysfs will be removed in 2012"
|
||||
" - used by: %s\n", current->comm);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EINVAL;
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
|
||||
|
@ -1425,6 +1455,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
|
|||
static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
pr_info("This interface sysfs will be removed in 2012"
|
||||
" - used by: %s\n", current->comm);
|
||||
switch (interface->type) {
|
||||
case ACER_AMW0:
|
||||
return sprintf(buf, "AMW0\n");
|
||||
|
|
|
@ -182,6 +182,7 @@ static const struct bios_settings_t bios_tbl[] = {
|
|||
{"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
|
||||
{"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
|
||||
{"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
|
||||
{"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
|
||||
/* Acer 531 */
|
||||
{"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
|
||||
/* Gateway */
|
||||
|
@ -703,15 +704,15 @@ MODULE_LICENSE("GPL");
|
|||
MODULE_AUTHOR("Peter Feuerer");
|
||||
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
|
||||
MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
|
||||
|
||||
module_init(acerhdf_init);
|
||||
module_exit(acerhdf_exit);
|
||||
|
|
|
@ -70,11 +70,10 @@ MODULE_LICENSE("GPL");
|
|||
* WAPF defines the behavior of the Fn+Fx wlan key
|
||||
* The significance of values is yet to be found, but
|
||||
* most of the time:
|
||||
* 0x0 will do nothing
|
||||
* 0x1 will allow to control the device with Fn+Fx key.
|
||||
* 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key
|
||||
* 0x5 like 0x1 or 0x4
|
||||
* So, if something doesn't work as you want, just try other values =)
|
||||
* Bit | Bluetooth | WLAN
|
||||
* 0 | Hardware | Hardware
|
||||
* 1 | Hardware | Software
|
||||
* 4 | Software | Software
|
||||
*/
|
||||
static uint wapf = 1;
|
||||
module_param(wapf, uint, 0444);
|
||||
|
|
|
@ -38,6 +38,24 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
|
||||
|
||||
/*
|
||||
* WAPF defines the behavior of the Fn+Fx wlan key
|
||||
* The significance of values is yet to be found, but
|
||||
* most of the time:
|
||||
* Bit | Bluetooth | WLAN
|
||||
* 0 | Hardware | Hardware
|
||||
* 1 | Hardware | Software
|
||||
* 4 | Software | Software
|
||||
*/
|
||||
static uint wapf;
|
||||
module_param(wapf, uint, 0444);
|
||||
MODULE_PARM_DESC(wapf, "WAPF value");
|
||||
|
||||
static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
|
||||
{
|
||||
driver->wapf = wapf;
|
||||
}
|
||||
|
||||
static const struct key_entry asus_nb_wmi_keymap[] = {
|
||||
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
|
||||
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
|
||||
|
@ -53,16 +71,16 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
|
|||
{ KE_KEY, 0x51, { KEY_WWW } },
|
||||
{ KE_KEY, 0x55, { KEY_CALC } },
|
||||
{ KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */
|
||||
{ KE_KEY, 0x5D, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x5E, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x5F, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
|
||||
{ KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
|
||||
{ KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
|
||||
{ KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
|
||||
{ KE_KEY, 0x7E, { KEY_BLUETOOTH } },
|
||||
{ KE_KEY, 0x7D, { KEY_BLUETOOTH } },
|
||||
{ KE_KEY, 0x7E, { KEY_BLUETOOTH } },
|
||||
{ KE_KEY, 0x82, { KEY_CAMERA } },
|
||||
{ KE_KEY, 0x88, { KEY_RFKILL } },
|
||||
{ KE_KEY, 0x8A, { KEY_PROG1 } },
|
||||
|
@ -81,6 +99,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
|
|||
.keymap = asus_nb_wmi_keymap,
|
||||
.input_name = "Asus WMI hotkeys",
|
||||
.input_phys = ASUS_NB_WMI_FILE "/input0",
|
||||
.quirks = asus_nb_wmi_quirks,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
|
@ -66,6 +67,8 @@ MODULE_LICENSE("GPL");
|
|||
#define NOTIFY_BRNUP_MAX 0x1f
|
||||
#define NOTIFY_BRNDOWN_MIN 0x20
|
||||
#define NOTIFY_BRNDOWN_MAX 0x2e
|
||||
#define NOTIFY_KBD_BRTUP 0xc4
|
||||
#define NOTIFY_KBD_BRTDWN 0xc5
|
||||
|
||||
/* WMI Methods */
|
||||
#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */
|
||||
|
@ -93,6 +96,7 @@ MODULE_LICENSE("GPL");
|
|||
/* Wireless */
|
||||
#define ASUS_WMI_DEVID_HW_SWITCH 0x00010001
|
||||
#define ASUS_WMI_DEVID_WIRELESS_LED 0x00010002
|
||||
#define ASUS_WMI_DEVID_CWAP 0x00010003
|
||||
#define ASUS_WMI_DEVID_WLAN 0x00010011
|
||||
#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
|
||||
#define ASUS_WMI_DEVID_GPS 0x00010015
|
||||
|
@ -102,6 +106,12 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
/* Leds */
|
||||
/* 0x000200XX and 0x000400XX */
|
||||
#define ASUS_WMI_DEVID_LED1 0x00020011
|
||||
#define ASUS_WMI_DEVID_LED2 0x00020012
|
||||
#define ASUS_WMI_DEVID_LED3 0x00020013
|
||||
#define ASUS_WMI_DEVID_LED4 0x00020014
|
||||
#define ASUS_WMI_DEVID_LED5 0x00020015
|
||||
#define ASUS_WMI_DEVID_LED6 0x00020016
|
||||
|
||||
/* Backlight and Brightness */
|
||||
#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
|
||||
|
@ -174,13 +184,18 @@ struct asus_wmi {
|
|||
|
||||
struct led_classdev tpd_led;
|
||||
int tpd_led_wk;
|
||||
struct led_classdev kbd_led;
|
||||
int kbd_led_wk;
|
||||
struct workqueue_struct *led_workqueue;
|
||||
struct work_struct tpd_led_work;
|
||||
struct work_struct kbd_led_work;
|
||||
|
||||
struct asus_rfkill wlan;
|
||||
struct asus_rfkill bluetooth;
|
||||
struct asus_rfkill wimax;
|
||||
struct asus_rfkill wwan3g;
|
||||
struct asus_rfkill gps;
|
||||
struct asus_rfkill uwb;
|
||||
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct mutex hotplug_lock;
|
||||
|
@ -205,6 +220,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
|
|||
asus->inputdev->phys = asus->driver->input_phys;
|
||||
asus->inputdev->id.bustype = BUS_HOST;
|
||||
asus->inputdev->dev.parent = &asus->platform_device->dev;
|
||||
set_bit(EV_REP, asus->inputdev->evbit);
|
||||
|
||||
err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
|
||||
if (err)
|
||||
|
@ -359,30 +375,80 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
|
|||
return read_tpd_led_state(asus);
|
||||
}
|
||||
|
||||
static int asus_wmi_led_init(struct asus_wmi *asus)
|
||||
static void kbd_led_update(struct work_struct *work)
|
||||
{
|
||||
int rv;
|
||||
int ctrl_param = 0;
|
||||
struct asus_wmi *asus;
|
||||
|
||||
if (read_tpd_led_state(asus) < 0)
|
||||
return 0;
|
||||
asus = container_of(work, struct asus_wmi, kbd_led_work);
|
||||
|
||||
asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
|
||||
if (!asus->led_workqueue)
|
||||
return -ENOMEM;
|
||||
INIT_WORK(&asus->tpd_led_work, tpd_led_update);
|
||||
/*
|
||||
* bits 0-2: level
|
||||
* bit 7: light on/off
|
||||
*/
|
||||
if (asus->kbd_led_wk > 0)
|
||||
ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
|
||||
|
||||
asus->tpd_led.name = "asus::touchpad";
|
||||
asus->tpd_led.brightness_set = tpd_led_set;
|
||||
asus->tpd_led.brightness_get = tpd_led_get;
|
||||
asus->tpd_led.max_brightness = 1;
|
||||
asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
|
||||
}
|
||||
|
||||
rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
|
||||
if (rv) {
|
||||
destroy_workqueue(asus->led_workqueue);
|
||||
return rv;
|
||||
static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* bits 0-2: level
|
||||
* bit 7: light on/off
|
||||
* bit 8-10: environment (0: dark, 1: normal, 2: light)
|
||||
* bit 17: status unknown
|
||||
*/
|
||||
retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
|
||||
0xFFFF);
|
||||
|
||||
/* Unknown status is considered as off */
|
||||
if (retval == 0x8000)
|
||||
retval = 0;
|
||||
|
||||
if (retval >= 0) {
|
||||
if (level)
|
||||
*level = retval & 0x80 ? retval & 0x7F : 0;
|
||||
if (env)
|
||||
*env = (retval >> 8) & 0x7F;
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void kbd_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct asus_wmi *asus;
|
||||
|
||||
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
|
||||
|
||||
if (value > asus->kbd_led.max_brightness)
|
||||
value = asus->kbd_led.max_brightness;
|
||||
else if (value < 0)
|
||||
value = 0;
|
||||
|
||||
asus->kbd_led_wk = value;
|
||||
queue_work(asus->led_workqueue, &asus->kbd_led_work);
|
||||
}
|
||||
|
||||
static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct asus_wmi *asus;
|
||||
int retval, value;
|
||||
|
||||
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
|
||||
|
||||
retval = kbd_led_read(asus, &value, NULL);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void asus_wmi_led_exit(struct asus_wmi *asus)
|
||||
|
@ -393,6 +459,48 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
|
|||
destroy_workqueue(asus->led_workqueue);
|
||||
}
|
||||
|
||||
static int asus_wmi_led_init(struct asus_wmi *asus)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
|
||||
if (!asus->led_workqueue)
|
||||
return -ENOMEM;
|
||||
|
||||
if (read_tpd_led_state(asus) >= 0) {
|
||||
INIT_WORK(&asus->tpd_led_work, tpd_led_update);
|
||||
|
||||
asus->tpd_led.name = "asus::touchpad";
|
||||
asus->tpd_led.brightness_set = tpd_led_set;
|
||||
asus->tpd_led.brightness_get = tpd_led_get;
|
||||
asus->tpd_led.max_brightness = 1;
|
||||
|
||||
rv = led_classdev_register(&asus->platform_device->dev,
|
||||
&asus->tpd_led);
|
||||
if (rv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (kbd_led_read(asus, NULL, NULL) >= 0) {
|
||||
INIT_WORK(&asus->kbd_led_work, kbd_led_update);
|
||||
|
||||
asus->kbd_led.name = "asus::kbd_backlight";
|
||||
asus->kbd_led.brightness_set = kbd_led_set;
|
||||
asus->kbd_led.brightness_get = kbd_led_get;
|
||||
asus->kbd_led.max_brightness = 3;
|
||||
|
||||
rv = led_classdev_register(&asus->platform_device->dev,
|
||||
&asus->kbd_led);
|
||||
}
|
||||
|
||||
error:
|
||||
if (rv)
|
||||
asus_wmi_led_exit(asus);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PCI hotplug (for wlan rfkill)
|
||||
*/
|
||||
|
@ -729,6 +837,16 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
|
|||
rfkill_destroy(asus->wwan3g.rfkill);
|
||||
asus->wwan3g.rfkill = NULL;
|
||||
}
|
||||
if (asus->gps.rfkill) {
|
||||
rfkill_unregister(asus->gps.rfkill);
|
||||
rfkill_destroy(asus->gps.rfkill);
|
||||
asus->gps.rfkill = NULL;
|
||||
}
|
||||
if (asus->uwb.rfkill) {
|
||||
rfkill_unregister(asus->uwb.rfkill);
|
||||
rfkill_destroy(asus->uwb.rfkill);
|
||||
asus->uwb.rfkill = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int asus_wmi_rfkill_init(struct asus_wmi *asus)
|
||||
|
@ -763,6 +881,18 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
|
|||
if (result && result != -ENODEV)
|
||||
goto exit;
|
||||
|
||||
result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
|
||||
RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
|
||||
|
||||
if (result && result != -ENODEV)
|
||||
goto exit;
|
||||
|
||||
result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
|
||||
RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
|
||||
|
||||
if (result && result != -ENODEV)
|
||||
goto exit;
|
||||
|
||||
if (!asus->driver->hotplug_wireless)
|
||||
goto exit;
|
||||
|
||||
|
@ -797,8 +927,8 @@ exit:
|
|||
* Hwmon device
|
||||
*/
|
||||
static ssize_t asus_hwmon_pwm1(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
u32 value;
|
||||
|
@ -809,7 +939,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
value |= 0xFF;
|
||||
value &= 0xFF;
|
||||
|
||||
if (value == 1) /* Low Speed */
|
||||
value = 85;
|
||||
|
@ -825,7 +955,26 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
|
|||
return sprintf(buf, "%d\n", value);
|
||||
}
|
||||
|
||||
static ssize_t asus_hwmon_temp1(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
|
||||
|
||||
return sprintf(buf, "%d\n", value);
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
|
||||
|
||||
static ssize_t
|
||||
show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
|
@ -836,12 +985,13 @@ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
|
|||
|
||||
static struct attribute *hwmon_attributes[] = {
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_name.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct platform_device *pdev = to_platform_device(dev->parent);
|
||||
|
@ -852,6 +1002,8 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
|
|||
|
||||
if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
|
||||
dev_id = ASUS_WMI_DEVID_FAN_CTRL;
|
||||
else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
|
||||
dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
|
||||
|
||||
if (dev_id != -1) {
|
||||
int err = asus_wmi_get_devstate(asus, dev_id, &value);
|
||||
|
@ -869,9 +1021,13 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
|
|||
* - reverved bits are non-zero
|
||||
* - sfun and presence bit are not set
|
||||
*/
|
||||
if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
|
||||
if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
|
||||
|| (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
|
||||
ok = false;
|
||||
} else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
|
||||
/* If value is zero, something is clearly wrong */
|
||||
if (value == 0)
|
||||
ok = false;
|
||||
}
|
||||
|
||||
return ok ? attr->mode : 0;
|
||||
|
@ -904,6 +1060,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
|
|||
pr_err("Could not register asus hwmon device\n");
|
||||
return PTR_ERR(hwmon);
|
||||
}
|
||||
dev_set_drvdata(hwmon, asus);
|
||||
asus->hwmon_device = hwmon;
|
||||
result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
|
||||
if (result)
|
||||
|
@ -1060,6 +1217,8 @@ static void asus_wmi_notify(u32 value, void *context)
|
|||
acpi_status status;
|
||||
int code;
|
||||
int orig_code;
|
||||
unsigned int key_value = 1;
|
||||
bool autorelease = 1;
|
||||
|
||||
status = wmi_get_event_data(value, &response);
|
||||
if (status != AE_OK) {
|
||||
|
@ -1075,6 +1234,13 @@ static void asus_wmi_notify(u32 value, void *context)
|
|||
code = obj->integer.value;
|
||||
orig_code = code;
|
||||
|
||||
if (asus->driver->key_filter) {
|
||||
asus->driver->key_filter(asus->driver, &code, &key_value,
|
||||
&autorelease);
|
||||
if (code == ASUS_WMI_KEY_IGNORE)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
|
||||
code = NOTIFY_BRNUP_MIN;
|
||||
else if (code >= NOTIFY_BRNDOWN_MIN &&
|
||||
|
@ -1084,7 +1250,8 @@ static void asus_wmi_notify(u32 value, void *context)
|
|||
if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
|
||||
if (!acpi_video_backlight_support())
|
||||
asus_wmi_backlight_notify(asus, orig_code);
|
||||
} else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
|
||||
} else if (!sparse_keymap_report_event(asus->inputdev, code,
|
||||
key_value, autorelease))
|
||||
pr_info("Unknown key %x pressed\n", code);
|
||||
|
||||
exit:
|
||||
|
@ -1164,14 +1331,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
|
|||
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int value;
|
||||
int value, rv;
|
||||
|
||||
if (!count || sscanf(buf, "%i", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < 0 || value > 2)
|
||||
return -EINVAL;
|
||||
|
||||
return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
|
||||
rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
|
||||
|
@ -1234,7 +1405,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
|
|||
|
||||
/* We don't know yet what to do with this version... */
|
||||
if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
|
||||
pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
|
||||
pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
|
||||
asus->spec = rv;
|
||||
}
|
||||
|
||||
|
@ -1266,6 +1437,12 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* CWAP allow to define the behavior of the Fn+F2 key,
|
||||
* this method doesn't seems to be present on Eee PCs */
|
||||
if (asus->driver->wapf >= 0)
|
||||
asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
|
||||
asus->driver->wapf, NULL);
|
||||
|
||||
return asus_wmi_sysfs_init(asus->platform_device);
|
||||
}
|
||||
|
||||
|
@ -1568,6 +1745,14 @@ static int asus_hotk_restore(struct device *device)
|
|||
bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
|
||||
rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
|
||||
}
|
||||
if (asus->gps.rfkill) {
|
||||
bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
|
||||
rfkill_set_sw_state(asus->gps.rfkill, bl);
|
||||
}
|
||||
if (asus->uwb.rfkill) {
|
||||
bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
|
||||
rfkill_set_sw_state(asus->uwb.rfkill, bl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1604,7 +1789,7 @@ static int asus_wmi_probe(struct platform_device *pdev)
|
|||
|
||||
static bool used;
|
||||
|
||||
int asus_wmi_register_driver(struct asus_wmi_driver *driver)
|
||||
int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
|
||||
{
|
||||
struct platform_driver *platform_driver;
|
||||
struct platform_device *platform_device;
|
||||
|
|
|
@ -29,12 +29,15 @@
|
|||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define ASUS_WMI_KEY_IGNORE (-1)
|
||||
|
||||
struct module;
|
||||
struct key_entry;
|
||||
struct asus_wmi;
|
||||
|
||||
struct asus_wmi_driver {
|
||||
bool hotplug_wireless;
|
||||
int wapf;
|
||||
|
||||
const char *name;
|
||||
struct module *owner;
|
||||
|
@ -44,6 +47,10 @@ struct asus_wmi_driver {
|
|||
const struct key_entry *keymap;
|
||||
const char *input_name;
|
||||
const char *input_phys;
|
||||
/* Returns new code, value, and autorelease values in arguments.
|
||||
* Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
|
||||
void (*key_filter) (struct asus_wmi_driver *driver, int *code,
|
||||
unsigned int *value, bool *autorelease);
|
||||
|
||||
int (*probe) (struct platform_device *device);
|
||||
void (*quirks) (struct asus_wmi_driver *driver);
|
||||
|
|
|
@ -612,7 +612,6 @@ static int __init dell_init(void)
|
|||
if (!bufferpage)
|
||||
goto fail_buffer;
|
||||
buffer = page_address(bufferpage);
|
||||
mutex_init(&buffer_mutex);
|
||||
|
||||
ret = dell_setup_rfkill();
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
|
|||
*/
|
||||
|
||||
static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
|
||||
{ KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
|
||||
|
||||
{ KE_KEY, 0xe045, { KEY_PROG1 } },
|
||||
{ KE_KEY, 0xe009, { KEY_EJECTCD } },
|
||||
|
||||
|
@ -85,6 +87,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
|
|||
{ KE_IGNORE, 0xe013, { KEY_RESERVED } },
|
||||
|
||||
{ KE_IGNORE, 0xe020, { KEY_MUTE } },
|
||||
|
||||
/* Shortcut and audio panel keys */
|
||||
{ KE_IGNORE, 0xe025, { KEY_RESERVED } },
|
||||
{ KE_IGNORE, 0xe026, { KEY_RESERVED } },
|
||||
|
||||
{ KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
|
||||
{ KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
|
||||
{ KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
|
||||
|
@ -92,6 +99,9 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
|
|||
{ KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
|
||||
{ KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
|
||||
{ KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
|
||||
{ KE_IGNORE, 0xe0f7, { KEY_MUTE } },
|
||||
{ KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
|
||||
{ KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
|
||||
{ KE_END, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ MODULE_PARM_DESC(hotplug_wireless,
|
|||
"If your laptop needs that, please report to "
|
||||
"acpi4asus-user@lists.sourceforge.net.");
|
||||
|
||||
/* Values for T101MT "Home" key */
|
||||
#define HOME_PRESS 0xe4
|
||||
#define HOME_HOLD 0xea
|
||||
#define HOME_RELEASE 0xe5
|
||||
|
||||
static const struct key_entry eeepc_wmi_keymap[] = {
|
||||
/* Sleep already handled via generic ACPI code */
|
||||
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
|
||||
|
@ -71,6 +76,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
|
|||
{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
|
||||
{ KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
|
||||
{ KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */
|
||||
{ KE_KEY, 0xe8, { KEY_SCREENLOCK } },
|
||||
{ KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
|
||||
{ KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
|
||||
|
@ -81,6 +87,25 @@ static const struct key_entry eeepc_wmi_keymap[] = {
|
|||
{ KE_END, 0},
|
||||
};
|
||||
|
||||
static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
|
||||
unsigned int *value, bool *autorelease)
|
||||
{
|
||||
switch (*code) {
|
||||
case HOME_PRESS:
|
||||
*value = 1;
|
||||
*autorelease = 0;
|
||||
break;
|
||||
case HOME_HOLD:
|
||||
*code = ASUS_WMI_KEY_IGNORE;
|
||||
break;
|
||||
case HOME_RELEASE:
|
||||
*code = HOME_PRESS;
|
||||
*value = 0;
|
||||
*autorelease = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
|
||||
void *context, void **retval)
|
||||
{
|
||||
|
@ -141,6 +166,7 @@ static void eeepc_dmi_check(struct asus_wmi_driver *driver)
|
|||
static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
|
||||
{
|
||||
driver->hotplug_wireless = hotplug_wireless;
|
||||
driver->wapf = -1;
|
||||
eeepc_dmi_check(driver);
|
||||
}
|
||||
|
||||
|
@ -151,6 +177,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
|
|||
.keymap = eeepc_wmi_keymap,
|
||||
.input_name = "Eee PC WMI hotkeys",
|
||||
.input_phys = EEEPC_WMI_FILE "/input0",
|
||||
.key_filter = eeepc_wmi_key_filter,
|
||||
.probe = eeepc_wmi_probe,
|
||||
.quirks = eeepc_wmi_quirks,
|
||||
};
|
||||
|
|
|
@ -32,13 +32,22 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#define IDEAPAD_RFKILL_DEV_NUM (3)
|
||||
|
||||
#define CFG_BT_BIT (16)
|
||||
#define CFG_3G_BIT (17)
|
||||
#define CFG_WIFI_BIT (18)
|
||||
#define CFG_CAMERA_BIT (19)
|
||||
|
||||
struct ideapad_private {
|
||||
struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
|
||||
struct platform_device *platform_device;
|
||||
struct input_dev *inputdev;
|
||||
struct backlight_device *blightdev;
|
||||
unsigned long cfg;
|
||||
};
|
||||
|
||||
static acpi_handle ideapad_handle;
|
||||
|
@ -155,7 +164,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
|
|||
}
|
||||
|
||||
/*
|
||||
* camera power
|
||||
* sysfs
|
||||
*/
|
||||
static ssize_t show_ideapad_cam(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -186,6 +195,44 @@ static ssize_t store_ideapad_cam(struct device *dev,
|
|||
|
||||
static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
|
||||
|
||||
static ssize_t show_ideapad_cfg(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ideapad_private *priv = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "0x%.8lX\n", priv->cfg);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
|
||||
|
||||
static struct attribute *ideapad_attributes[] = {
|
||||
&dev_attr_camera_power.attr,
|
||||
&dev_attr_cfg.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static mode_t ideapad_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int idx)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct ideapad_private *priv = dev_get_drvdata(dev);
|
||||
bool supported;
|
||||
|
||||
if (attr == &dev_attr_camera_power.attr)
|
||||
supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
|
||||
else
|
||||
supported = true;
|
||||
|
||||
return supported ? attr->mode : 0;
|
||||
}
|
||||
|
||||
static struct attribute_group ideapad_attribute_group = {
|
||||
.is_visible = ideapad_is_visible,
|
||||
.attrs = ideapad_attributes
|
||||
};
|
||||
|
||||
/*
|
||||
* Rfkill
|
||||
*/
|
||||
|
@ -197,9 +244,9 @@ struct ideapad_rfk_data {
|
|||
};
|
||||
|
||||
const struct ideapad_rfk_data ideapad_rfk_data[] = {
|
||||
{ "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
|
||||
{ "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
|
||||
{ "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
|
||||
{ "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
|
||||
{ "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH },
|
||||
{ "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN },
|
||||
};
|
||||
|
||||
static int ideapad_rfk_set(void *data, bool blocked)
|
||||
|
@ -265,8 +312,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
|
||||
int dev)
|
||||
static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
|
||||
{
|
||||
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
|
||||
|
||||
|
@ -280,15 +326,6 @@ static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
|
|||
/*
|
||||
* Platform device
|
||||
*/
|
||||
static struct attribute *ideapad_attributes[] = {
|
||||
&dev_attr_camera_power.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group ideapad_attribute_group = {
|
||||
.attrs = ideapad_attributes
|
||||
};
|
||||
|
||||
static int __devinit ideapad_platform_init(struct ideapad_private *priv)
|
||||
{
|
||||
int result;
|
||||
|
@ -369,7 +406,7 @@ err_free_dev:
|
|||
return error;
|
||||
}
|
||||
|
||||
static void __devexit ideapad_input_exit(struct ideapad_private *priv)
|
||||
static void ideapad_input_exit(struct ideapad_private *priv)
|
||||
{
|
||||
sparse_keymap_free(priv->inputdev);
|
||||
input_unregister_device(priv->inputdev);
|
||||
|
@ -382,6 +419,98 @@ static void ideapad_input_report(struct ideapad_private *priv,
|
|||
sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* backlight
|
||||
*/
|
||||
static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
if (read_ec_data(ideapad_handle, 0x12, &now))
|
||||
return -EIO;
|
||||
return now;
|
||||
}
|
||||
|
||||
static int ideapad_backlight_update_status(struct backlight_device *blightdev)
|
||||
{
|
||||
if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
|
||||
return -EIO;
|
||||
if (write_ec_cmd(ideapad_handle, 0x33,
|
||||
blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops ideapad_backlight_ops = {
|
||||
.get_brightness = ideapad_backlight_get_brightness,
|
||||
.update_status = ideapad_backlight_update_status,
|
||||
};
|
||||
|
||||
static int ideapad_backlight_init(struct ideapad_private *priv)
|
||||
{
|
||||
struct backlight_device *blightdev;
|
||||
struct backlight_properties props;
|
||||
unsigned long max, now, power;
|
||||
|
||||
if (read_ec_data(ideapad_handle, 0x11, &max))
|
||||
return -EIO;
|
||||
if (read_ec_data(ideapad_handle, 0x12, &now))
|
||||
return -EIO;
|
||||
if (read_ec_data(ideapad_handle, 0x18, &power))
|
||||
return -EIO;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = max;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
blightdev = backlight_device_register("ideapad",
|
||||
&priv->platform_device->dev,
|
||||
priv,
|
||||
&ideapad_backlight_ops,
|
||||
&props);
|
||||
if (IS_ERR(blightdev)) {
|
||||
pr_err("Could not register backlight device\n");
|
||||
return PTR_ERR(blightdev);
|
||||
}
|
||||
|
||||
priv->blightdev = blightdev;
|
||||
blightdev->props.brightness = now;
|
||||
blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
|
||||
backlight_update_status(blightdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ideapad_backlight_exit(struct ideapad_private *priv)
|
||||
{
|
||||
if (priv->blightdev)
|
||||
backlight_device_unregister(priv->blightdev);
|
||||
priv->blightdev = NULL;
|
||||
}
|
||||
|
||||
static void ideapad_backlight_notify_power(struct ideapad_private *priv)
|
||||
{
|
||||
unsigned long power;
|
||||
struct backlight_device *blightdev = priv->blightdev;
|
||||
|
||||
if (read_ec_data(ideapad_handle, 0x18, &power))
|
||||
return;
|
||||
blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
|
||||
}
|
||||
|
||||
static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
/* if we control brightness via acpi video driver */
|
||||
if (priv->blightdev == NULL) {
|
||||
read_ec_data(ideapad_handle, 0x12, &now);
|
||||
return;
|
||||
}
|
||||
|
||||
backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
|
||||
}
|
||||
|
||||
/*
|
||||
* module init/exit
|
||||
*/
|
||||
|
@ -393,10 +522,11 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
|
|||
|
||||
static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
|
||||
{
|
||||
int ret, i, cfg;
|
||||
int ret, i;
|
||||
unsigned long cfg;
|
||||
struct ideapad_private *priv;
|
||||
|
||||
if (read_method_int(adevice->handle, "_CFG", &cfg))
|
||||
if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
|
||||
return -ENODEV;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -404,6 +534,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
|
|||
return -ENOMEM;
|
||||
dev_set_drvdata(&adevice->dev, priv);
|
||||
ideapad_handle = adevice->handle;
|
||||
priv->cfg = cfg;
|
||||
|
||||
ret = ideapad_platform_init(priv);
|
||||
if (ret)
|
||||
|
@ -414,15 +545,25 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
|
|||
goto input_failed;
|
||||
|
||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
|
||||
if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
|
||||
if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
|
||||
ideapad_register_rfkill(adevice, i);
|
||||
else
|
||||
priv->rfk[i] = NULL;
|
||||
}
|
||||
ideapad_sync_rfk_state(adevice);
|
||||
|
||||
if (!acpi_video_backlight_support()) {
|
||||
ret = ideapad_backlight_init(priv);
|
||||
if (ret && ret != -ENODEV)
|
||||
goto backlight_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
backlight_failed:
|
||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
||||
ideapad_unregister_rfkill(adevice, i);
|
||||
ideapad_input_exit(priv);
|
||||
input_failed:
|
||||
ideapad_platform_exit(priv);
|
||||
platform_failed:
|
||||
|
@ -435,6 +576,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
|
|||
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
|
||||
int i;
|
||||
|
||||
ideapad_backlight_exit(priv);
|
||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
||||
ideapad_unregister_rfkill(adevice, i);
|
||||
ideapad_input_exit(priv);
|
||||
|
@ -459,12 +601,19 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|||
vpc1 = (vpc2 << 8) | vpc1;
|
||||
for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
|
||||
if (test_bit(vpc_bit, &vpc1)) {
|
||||
if (vpc_bit == 9)
|
||||
switch (vpc_bit) {
|
||||
case 9:
|
||||
ideapad_sync_rfk_state(adevice);
|
||||
else if (vpc_bit == 4)
|
||||
read_ec_data(handle, 0x12, &vpc2);
|
||||
else
|
||||
break;
|
||||
case 4:
|
||||
ideapad_backlight_notify_brightness(priv);
|
||||
break;
|
||||
case 2:
|
||||
ideapad_backlight_notify_power(priv);
|
||||
break;
|
||||
default:
|
||||
ideapad_input_report(priv, vpc_bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ static void ips_cpu_raise(struct ips_driver *ips)
|
|||
|
||||
thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
|
||||
|
||||
turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
|
||||
turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
|
||||
wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
|
||||
|
||||
turbo_override &= ~TURBO_TDP_MASK;
|
||||
|
@ -438,7 +438,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
|
|||
|
||||
thm_writew(THM_MPCPC, (new_limit * 10) / 8);
|
||||
|
||||
turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
|
||||
turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
|
||||
wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
|
||||
|
||||
turbo_override &= ~TURBO_TDP_MASK;
|
||||
|
|
|
@ -477,6 +477,8 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
|
|||
return AE_ERROR;
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
|
||||
aux1_not_found:
|
||||
if (status == AE_NOT_FOUND)
|
||||
return AE_OK;
|
||||
|
|
|
@ -493,20 +493,30 @@ static int mid_thermal_probe(struct platform_device *pdev)
|
|||
|
||||
/* Register each sensor with the generic thermal framework*/
|
||||
for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
|
||||
struct thermal_device_info *td_info = initialize_sensor(i);
|
||||
|
||||
if (!td_info) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
pinfo->tzd[i] = thermal_zone_device_register(name[i],
|
||||
0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0);
|
||||
if (IS_ERR(pinfo->tzd[i]))
|
||||
goto reg_fail;
|
||||
0, td_info, &tzd_ops, 0, 0, 0, 0);
|
||||
if (IS_ERR(pinfo->tzd[i])) {
|
||||
kfree(td_info);
|
||||
ret = PTR_ERR(pinfo->tzd[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
pinfo->pdev = pdev;
|
||||
platform_set_drvdata(pdev, pinfo);
|
||||
return 0;
|
||||
|
||||
reg_fail:
|
||||
ret = PTR_ERR(pinfo->tzd[i]);
|
||||
while (--i >= 0)
|
||||
err:
|
||||
while (--i >= 0) {
|
||||
kfree(pinfo->tzd[i]->devdata);
|
||||
thermal_zone_device_unregister(pinfo->tzd[i]);
|
||||
}
|
||||
configure_adc(0);
|
||||
kfree(pinfo);
|
||||
return ret;
|
||||
|
@ -524,8 +534,10 @@ static int mid_thermal_remove(struct platform_device *pdev)
|
|||
int i;
|
||||
struct platform_info *pinfo = platform_get_drvdata(pdev);
|
||||
|
||||
for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
|
||||
for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
|
||||
kfree(pinfo->tzd[i]->devdata);
|
||||
thermal_zone_device_unregister(pinfo->tzd[i]);
|
||||
}
|
||||
|
||||
kfree(pinfo);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
|
|
@ -637,15 +637,13 @@ end_function:
|
|||
return error;
|
||||
}
|
||||
|
||||
const struct pci_device_id rar_pci_id_tbl[] = {
|
||||
static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = {
|
||||
{ PCI_VDEVICE(INTEL, 0x4110) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
|
||||
|
||||
const struct pci_device_id *my_id_table = rar_pci_id_tbl;
|
||||
|
||||
/* field for registering driver to PCI device */
|
||||
static struct pci_driver rar_pci_driver = {
|
||||
.name = "rar_register_driver",
|
||||
|
|
|
@ -725,7 +725,7 @@ static void ipc_remove(struct pci_dev *pdev)
|
|||
intel_scu_devices_destroy();
|
||||
}
|
||||
|
||||
static const struct pci_device_id pci_ids[] = {
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
|
||||
{ 0,}
|
||||
|
|
|
@ -538,6 +538,15 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
|
|||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{
|
||||
.ident = "MSI U270",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"Micro-Star International Co., Ltd."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"),
|
||||
},
|
||||
.callback = dmi_check_cb
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -996,3 +1005,4 @@ 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:*");
|
||||
MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*");
|
||||
|
|
|
@ -272,6 +272,7 @@ static int __init msi_wmi_init(void)
|
|||
err_free_backlight:
|
||||
backlight_device_unregister(backlight);
|
||||
err_free_input:
|
||||
sparse_keymap_free(msi_wmi_input_dev);
|
||||
input_unregister_device(msi_wmi_input_dev);
|
||||
err_uninstall_notifier:
|
||||
wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
|
||||
|
|
|
@ -520,6 +520,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
|||
},
|
||||
.callback = dmi_check_cb,
|
||||
},
|
||||
{
|
||||
.ident = "N510",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N510"),
|
||||
},
|
||||
.callback = dmi_check_cb,
|
||||
},
|
||||
{
|
||||
.ident = "X125",
|
||||
.matches = {
|
||||
|
@ -600,6 +610,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
|||
},
|
||||
.callback = dmi_check_cb,
|
||||
},
|
||||
{
|
||||
.ident = "N150/N210/N220",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR,
|
||||
"SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
|
||||
},
|
||||
.callback = dmi_check_cb,
|
||||
},
|
||||
{
|
||||
.ident = "N150/N210/N220/N230",
|
||||
.matches = {
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Driver for Samsung Q10 and related laptops: controls the backlight
|
||||
*
|
||||
* Copyright (c) 2011 Frederick van der Wyck <fvanderwyck@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/i8042.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#define SAMSUNGQ10_BL_MAX_INTENSITY 255
|
||||
#define SAMSUNGQ10_BL_DEFAULT_INTENSITY 185
|
||||
|
||||
#define SAMSUNGQ10_BL_8042_CMD 0xbe
|
||||
#define SAMSUNGQ10_BL_8042_DATA { 0x89, 0x91 }
|
||||
|
||||
static int samsungq10_bl_brightness;
|
||||
|
||||
static bool force;
|
||||
module_param(force, bool, 0);
|
||||
MODULE_PARM_DESC(force,
|
||||
"Disable the DMI check and force the driver to be loaded");
|
||||
|
||||
static int samsungq10_bl_set_intensity(struct backlight_device *bd)
|
||||
{
|
||||
|
||||
int brightness = bd->props.brightness;
|
||||
unsigned char c[3] = SAMSUNGQ10_BL_8042_DATA;
|
||||
|
||||
c[2] = (unsigned char)brightness;
|
||||
i8042_lock_chip();
|
||||
i8042_command(c, (0x30 << 8) | SAMSUNGQ10_BL_8042_CMD);
|
||||
i8042_unlock_chip();
|
||||
samsungq10_bl_brightness = brightness;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsungq10_bl_get_intensity(struct backlight_device *bd)
|
||||
{
|
||||
return samsungq10_bl_brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops samsungq10_bl_ops = {
|
||||
.get_brightness = samsungq10_bl_get_intensity,
|
||||
.update_status = samsungq10_bl_set_intensity,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int samsungq10_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsungq10_resume(struct device *dev)
|
||||
{
|
||||
|
||||
struct backlight_device *bd = dev_get_drvdata(dev);
|
||||
|
||||
samsungq10_bl_set_intensity(bd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define samsungq10_suspend NULL
|
||||
#define samsungq10_resume NULL
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
|
||||
samsungq10_suspend, samsungq10_resume);
|
||||
|
||||
static int __devinit samsungq10_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bd;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
|
||||
bd = backlight_device_register("samsung", &pdev->dev, NULL,
|
||||
&samsungq10_bl_ops, &props);
|
||||
if (IS_ERR(bd))
|
||||
return PTR_ERR(bd);
|
||||
|
||||
platform_set_drvdata(pdev, bd);
|
||||
|
||||
bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
|
||||
samsungq10_bl_set_intensity(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit samsungq10_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
|
||||
samsungq10_bl_set_intensity(bd);
|
||||
|
||||
backlight_device_unregister(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver samsungq10_driver = {
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &samsungq10_pm_ops,
|
||||
},
|
||||
.probe = samsungq10_probe,
|
||||
.remove = __devexit_p(samsungq10_remove),
|
||||
};
|
||||
|
||||
static struct platform_device *samsungq10_device;
|
||||
|
||||
static int __init dmi_check_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata samsungq10_dmi_table[] = {
|
||||
{
|
||||
.ident = "Samsung Q10",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
|
||||
},
|
||||
.callback = dmi_check_callback,
|
||||
},
|
||||
{
|
||||
.ident = "Samsung Q20",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
|
||||
},
|
||||
.callback = dmi_check_callback,
|
||||
},
|
||||
{
|
||||
.ident = "Samsung Q25",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
|
||||
},
|
||||
.callback = dmi_check_callback,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Latitude X200",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
|
||||
},
|
||||
.callback = dmi_check_callback,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
|
||||
|
||||
static int __init samsungq10_init(void)
|
||||
{
|
||||
if (!force && !dmi_check_system(samsungq10_dmi_table))
|
||||
return -ENODEV;
|
||||
|
||||
samsungq10_device = platform_create_bundle(&samsungq10_driver,
|
||||
samsungq10_probe,
|
||||
NULL, 0, NULL, 0);
|
||||
|
||||
if (IS_ERR(samsungq10_device))
|
||||
return PTR_ERR(samsungq10_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit samsungq10_exit(void)
|
||||
{
|
||||
platform_device_unregister(samsungq10_device);
|
||||
platform_driver_unregister(&samsungq10_driver);
|
||||
}
|
||||
|
||||
module_init(samsungq10_init);
|
||||
module_exit(samsungq10_exit);
|
||||
|
||||
MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
|
||||
MODULE_DESCRIPTION("Samsung Q10 Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -3185,9 +3185,18 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
|
|||
|
||||
KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
|
||||
|
||||
/* (assignments unknown, please report if found) */
|
||||
KEY_UNKNOWN, KEY_UNKNOWN,
|
||||
|
||||
/*
|
||||
* The mic mute button only sends 0x1a. It does not
|
||||
* automatically mute the mic or change the mute light.
|
||||
*/
|
||||
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, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
|
||||
KEY_UNKNOWN,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -438,6 +438,8 @@ struct input_keymap_entry {
|
|||
#define KEY_WIMAX 246
|
||||
#define KEY_RFKILL 247 /* Key that controls all radios */
|
||||
|
||||
#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
|
||||
|
||||
/* Code 255 is reserved for special needs of AT keyboard driver */
|
||||
|
||||
#define BTN_MISC 0x100
|
||||
|
|
Загрузка…
Ссылка в новой задаче