diff options
Diffstat (limited to 'drivers/platform')
26 files changed, 4506 insertions, 533 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3e1b8a28871..044f430f3b4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -5,6 +5,7 @@ menuconfig X86_PLATFORM_DEVICES bool "X86 Platform Specific Device Drivers" default y + depends on X86 ---help--- Say Y here to get to see options for device drivers for various x86 platforms, including vendor-specific laptop extension drivers. @@ -151,6 +152,7 @@ config MSI_LAPTOP depends on ACPI depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL + depends on SERIO_I8042 ---help--- This is a driver for laptops built by MSI (MICRO-STAR INTERNATIONAL): @@ -181,6 +183,8 @@ config COMPAL_LAPTOP depends on ACPI depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL + depends on HWMON + depends on POWER_SUPPLY ---help--- This is a driver for laptops built by Compal: @@ -215,6 +219,13 @@ config SONYPI_COMPAT ---help--- Build the sonypi driver compatibility code into the sony-laptop driver. +config IDEAPAD_ACPI + tristate "Lenovo IdeaPad ACPI Laptop Extras" + depends on ACPI + depends on RFKILL + help + This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. + config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI @@ -520,6 +531,7 @@ config TOSHIBA_BT_RFKILL config ACPI_CMPC tristate "CMPC Laptop Extras" depends on X86 && ACPI + depends on RFKILL || RFKILL=n select INPUT select BACKLIGHT_CLASS_DEVICE default n @@ -537,4 +549,43 @@ config INTEL_SCU_IPC some embedded Intel x86 platforms. This is not needed for PC-type machines. +config GPIO_INTEL_PMIC + bool "Intel PMIC GPIO support" + depends on INTEL_SCU_IPC && GPIOLIB + ---help--- + Say Y here to support GPIO via the SCU IPC interface + on Intel MID platforms. + +config RAR_REGISTER + bool "Restricted Access Region Register Driver" + depends on PCI && X86_MRST + default n + ---help--- + This driver allows other kernel drivers access to the + contents of the restricted access region control registers. + + The restricted access region control registers + (rar_registers) are used to pass address and + locking information on restricted access regions + to other drivers that use restricted access regions. + + The restricted access regions are regions of memory + on the Intel MID Platform that are not accessible to + the x86 processor, but are accessible to dedicated + processors on board peripheral devices. + + The purpose of the restricted access regions is to + protect sensitive data from compromise by unauthorized + programs running on the x86 processor. + +config INTEL_IPS + tristate "Intel Intelligent Power Sharing" + depends on ACPI + ---help--- + Intel Calpella platforms support dynamic power sharing between the + CPU and GPU, maximizing performance in a given TDP. This driver, + along with the CPU frequency and i915 drivers, provides that + functionality. If in doubt, say Y here; it will only load on + supported platforms. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 8770bfe7143..85fb2b84f57 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_ACERHDF) += acerhdf.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o +obj-$(CONFIG_IDEAPAD_ACPI) += ideapad_acpi.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o @@ -26,3 +27,7 @@ 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 +obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o +obj-$(CONFIG_INTEL_IPS) += intel_ips.o +obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o + diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 1ea6c434d33..2badee2fdee 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -50,17 +50,6 @@ MODULE_LICENSE("GPL"); #define ACER_INFO KERN_INFO ACER_LOGPREFIX /* - * The following defines quirks to get some specific functions to work - * which are known to not be supported over ACPI-WMI (such as the mail LED - * on WMID based Acer's) - */ -struct acer_quirks { - const char *vendor; - const char *model; - u16 quirks; -}; - -/* * Magic Number * Meaning is unknown - this number is required for writing to ACPI for AMW0 * (it's also used in acerhk when directly accessing the BIOS) @@ -200,7 +189,7 @@ static void set_quirks(void) static int dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; - return 0; + return 1; } static struct quirk_entry quirk_unknown = { @@ -555,6 +544,7 @@ static acpi_status AMW0_find_mailled(void) obj->buffer.length == sizeof(struct wmab_ret)) { ret = *((struct wmab_ret *) obj->buffer.pointer); } else { + kfree(out.pointer); return AE_ERROR; } @@ -570,7 +560,7 @@ static acpi_status AMW0_set_capabilities(void) { struct wmab_args args; struct wmab_ret ret; - acpi_status status = AE_OK; + acpi_status status; struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -593,12 +583,13 @@ static acpi_status AMW0_set_capabilities(void) if (ACPI_FAILURE(status)) return status; - obj = (union acpi_object *) out.pointer; + obj = out.pointer; if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == sizeof(struct wmab_ret)) { ret = *((struct wmab_ret *) obj->buffer.pointer); } else { - return AE_ERROR; + status = AE_ERROR; + goto out; } if (ret.eax & 0x1) @@ -607,23 +598,26 @@ static acpi_status AMW0_set_capabilities(void) args.ebx = 2 << 8; args.ebx |= ACER_AMW0_BLUETOOTH_MASK; + /* + * It's ok to use existing buffer for next wmab_execute call. + * But we need to kfree(out.pointer) if next wmab_execute fail. + */ status = wmab_execute(&args, &out); if (ACPI_FAILURE(status)) - return status; + goto out; obj = (union acpi_object *) out.pointer; if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == sizeof(struct wmab_ret)) { ret = *((struct wmab_ret *) obj->buffer.pointer); } else { - return AE_ERROR; + status = AE_ERROR; + goto out; } if (ret.eax & 0x1) interface->capability |= ACER_CAP_BLUETOOTH; - kfree(out.pointer); - /* * This appears to be safe to enable, since all Wistron based laptops * appear to use the same EC register for brightness, even if they @@ -632,7 +626,10 @@ static acpi_status AMW0_set_capabilities(void) if (quirks->brightness >= 0) interface->capability |= ACER_CAP_BRIGHTNESS; - return AE_OK; + status = AE_OK; +out: + kfree(out.pointer); + return status; } static struct wmi_interface AMW0_interface = { @@ -772,6 +769,7 @@ static acpi_status WMID_set_capabilities(void) obj->buffer.length == sizeof(u32)) { devices = *((u32 *) obj->buffer.pointer); } else { + kfree(out.pointer); return AE_ERROR; } @@ -788,6 +786,7 @@ static acpi_status WMID_set_capabilities(void) if (!(devices & 0x20)) max_brightness = 0x9; + kfree(out.pointer); return status; } @@ -1084,8 +1083,7 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr, } } -static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR, - show_interface, NULL); +static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL); /* * debugfs functions @@ -1095,6 +1093,7 @@ static u32 get_wmid_devices(void) struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; acpi_status status; + u32 devices = 0; status = wmi_query_block(WMID_GUID2, 1, &out); if (ACPI_FAILURE(status)) @@ -1103,10 +1102,11 @@ static u32 get_wmid_devices(void) obj = (union acpi_object *) out.pointer; if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == sizeof(u32)) { - return *((u32 *) obj->buffer.pointer); - } else { - return 0; + devices = *((u32 *) obj->buffer.pointer); } + + kfree(out.pointer); + return devices; } /* @@ -1327,22 +1327,31 @@ static int __init acer_wmi_init(void) "generic video driver\n"); } - if (platform_driver_register(&acer_platform_driver)) { + err = platform_driver_register(&acer_platform_driver); + if (err) { printk(ACER_ERR "Unable to register platform driver.\n"); goto error_platform_register; } + acer_platform_device = platform_device_alloc("acer-wmi", -1); - platform_device_add(acer_platform_device); + if (!acer_platform_device) { + err = -ENOMEM; + goto error_device_alloc; + } + + err = platform_device_add(acer_platform_device); + if (err) + goto error_device_add; err = create_sysfs(); if (err) - return err; + goto error_create_sys; if (wmi_has_guid(WMID_GUID2)) { interface->debug.wmid_devices = get_wmid_devices(); err = create_debugfs(); if (err) - return err; + goto error_create_debugfs; } /* Override any initial settings with values from the commandline */ @@ -1350,15 +1359,23 @@ static int __init acer_wmi_init(void) return 0; +error_create_debugfs: + remove_sysfs(acer_platform_device); +error_create_sys: + platform_device_del(acer_platform_device); +error_device_add: + platform_device_put(acer_platform_device); +error_device_alloc: + platform_driver_unregister(&acer_platform_driver); error_platform_register: - return -ENODEV; + return err; } static void __exit acer_wmi_exit(void) { remove_sysfs(acer_platform_device); remove_debugfs(); - platform_device_del(acer_platform_device); + platform_device_unregister(acer_platform_device); platform_driver_unregister(&acer_platform_driver); printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n"); diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 7b2384d674d..60f9cfcac93 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.22" +#define DRV_VER "0.5.24" /* * According to the Atom N270 datasheet, @@ -92,9 +92,9 @@ static unsigned int fanstate = ACERHDF_FAN_AUTO; static char force_bios[16]; static char force_product[16]; static unsigned int prev_interval; -struct thermal_zone_device *thz_dev; -struct thermal_cooling_device *cl_dev; -struct platform_device *acerhdf_dev; +static struct thermal_zone_device *thz_dev; +static struct thermal_cooling_device *cl_dev; +static struct platform_device *acerhdf_dev; module_param(kernelmode, uint, 0); MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); @@ -112,14 +112,12 @@ module_param_string(force_product, force_product, 16, 0); MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); /* - * cmd_off: to switch the fan completely off - * chk_off: to check if the fan is off + * cmd_off: to switch the fan completely off and check if the fan is off * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then * the fan speed depending on the temperature */ struct fancmd { u8 cmd_off; - u8 chk_off; u8 cmd_auto; }; @@ -136,47 +134,81 @@ struct bios_settings_t { /* Register addresses and values for different BIOS versions */ static const struct bios_settings_t bios_tbl[] = { /* AOA110 */ - {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} }, - {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} }, - {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, + {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, + {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, + {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, + {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, /* AOA150 */ - {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, + {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, /* Acer 1410 */ - {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, /* Acer 1810xx */ - {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, + {"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 531 */ + {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} }, /* Gateway */ - {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, - {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, - {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, - {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, + {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, + {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} }, + {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, + {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, /* Packard Bell */ - {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, - {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, - {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, + {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, + {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, + {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, + {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, + {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, /* pewpew-terminator */ - {"", "", "", 0, 0, {0, 0, 0} } + {"", "", "", 0, 0, {0, 0} } }; static const struct bios_settings_t *bios_cfg __read_mostly; @@ -200,7 +232,7 @@ static int acerhdf_get_fanstate(int *state) if (ec_read(bios_cfg->fanreg, &fan)) return -EINVAL; - if (fan != bios_cfg->cmd.chk_off) + if (fan != bios_cfg->cmd.cmd_off) *state = ACERHDF_FAN_AUTO; else *state = ACERHDF_FAN_OFF; @@ -374,7 +406,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, } /* bind callback functions to thermalzone */ -struct thermal_zone_device_ops acerhdf_dev_ops = { +static struct thermal_zone_device_ops acerhdf_dev_ops = { .bind = acerhdf_bind, .unbind = acerhdf_unbind, .get_temp = acerhdf_get_ec_temp, @@ -449,7 +481,7 @@ err_out: } /* bind fan callbacks to fan device */ -struct thermal_cooling_device_ops acerhdf_cooling_ops = { +static struct thermal_cooling_device_ops acerhdf_cooling_ops = { .get_max_state = acerhdf_get_max_state, .get_cur_state = acerhdf_get_cur_state, .set_cur_state = acerhdf_set_cur_state, @@ -518,6 +550,10 @@ static int acerhdf_check_hardware(void) version = dmi_get_system_info(DMI_BIOS_VERSION); product = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!vendor || !version || !product) { + pr_err("error getting hardware information\n"); + return -EINVAL; + } pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); @@ -579,17 +615,26 @@ static int acerhdf_register_platform(void) return err; acerhdf_dev = platform_device_alloc("acerhdf", -1); - platform_device_add(acerhdf_dev); + if (!acerhdf_dev) { + err = -ENOMEM; + goto err_device_alloc; + } + err = platform_device_add(acerhdf_dev); + if (err) + goto err_device_add; return 0; + +err_device_add: + platform_device_put(acerhdf_dev); +err_device_alloc: + platform_driver_unregister(&acerhdf_driver); + return err; } static void acerhdf_unregister_platform(void) { - if (!acerhdf_dev) - return; - - platform_device_del(acerhdf_dev); + platform_device_unregister(acerhdf_dev); platform_driver_unregister(&acerhdf_driver); } @@ -633,7 +678,7 @@ static int __init acerhdf_init(void) err = acerhdf_register_platform(); if (err) - goto err_unreg; + goto out_err; err = acerhdf_register_thermal(); if (err) @@ -646,7 +691,7 @@ err_unreg: acerhdf_unregister_platform(); out_err: - return -ENODEV; + return err; } static void __exit acerhdf_exit(void) @@ -662,11 +707,13 @@ 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*: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_init(acerhdf_init); module_exit(acerhdf_exit); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index efe8f638890..b756e07d41b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -76,18 +76,18 @@ MODULE_LICENSE("GPL"); * So, if something doesn't work as you want, just try other values =) */ static uint wapf = 1; -module_param(wapf, uint, 0644); +module_param(wapf, uint, 0444); MODULE_PARM_DESC(wapf, "WAPF value"); static int wlan_status = 1; static int bluetooth_status = 1; -module_param(wlan_status, int, 0644); +module_param(wlan_status, int, 0444); MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " "(0 = disabled, 1 = enabled, -1 = don't do anything). " "default is 1"); -module_param(bluetooth_status, int, 0644); +module_param(bluetooth_status, int, 0444); MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " "(0 = disabled, 1 = enabled, -1 = don't do anything). " "default is 1"); @@ -297,7 +297,7 @@ static int write_acpi_int_ret(acpi_handle handle, const char *method, int val, acpi_status status; if (!handle) - return 0; + return -1; params.count = 1; params.pointer = &in_obj; @@ -796,10 +796,11 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) { - if (write_acpi_int(asus->handle, METHOD_LEDD, value)) + if (write_acpi_int(asus->handle, METHOD_LEDD, value)) { pr_warning("LED display write failed\n"); - else - asus->ledd_status = (u32) value; + return -ENODEV; + } + asus->ledd_status = (u32) value; } return rv; } @@ -1123,7 +1124,7 @@ static int asus_input_init(struct asus_laptop *asus) input = input_allocate_device(); if (!input) { pr_info("Unable to allocate input device\n"); - return 0; + return -ENOMEM; } input->name = "Asus Laptop extra buttons"; input->phys = ASUS_LAPTOP_FILE "/input0"; @@ -1134,20 +1135,20 @@ static int asus_input_init(struct asus_laptop *asus) error = sparse_keymap_setup(input, asus_keymap, NULL); if (error) { pr_err("Unable to setup input device keymap\n"); - goto err_keymap; + goto err_free_dev; } error = input_register_device(input); if (error) { pr_info("Unable to register input device\n"); - goto err_device; + goto err_free_keymap; } asus->inputdev = input; return 0; -err_keymap: +err_free_keymap: sparse_keymap_free(input); -err_device: +err_free_dev: input_free_device(input); return error; } @@ -1397,8 +1398,10 @@ static int asus_laptop_get_info(struct asus_laptop *asus) } } asus->name = kstrdup(string, GFP_KERNEL); - if (!asus->name) + if (!asus->name) { + kfree(buffer.pointer); return -ENOMEM; + } if (*string) pr_notice(" %s model detected\n", string); diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 92fd30c9379..e058c2ba2a1 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -1330,6 +1330,9 @@ static int asus_hotk_get_info(void) hotk->model = P30; printk(KERN_NOTICE " Samsung P30 detected, supported\n"); + hotk->methods = &model_conf[hotk->model]; + kfree(model); + return 0; } else { hotk->model = M2E; printk(KERN_NOTICE " unsupported model %s, trying " @@ -1339,8 +1342,6 @@ static int asus_hotk_get_info(void) kfree(model); return -ENODEV; } - hotk->methods = &model_conf[hotk->model]; - return AE_OK; } hotk->methods = &model_conf[hotk->model]; printk(KERN_NOTICE " %s model detected, supported\n", string); @@ -1374,7 +1375,7 @@ static int asus_hotk_get_info(void) kfree(model); - return AE_OK; + return 0; } static int asus_hotk_check(void) diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 3bf399fe2bb..341cbfef93e 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -208,7 +208,7 @@ static ssize_t cmpc_accel_sensitivity_store(struct device *dev, return strnlen(buf, count); } -struct device_attribute cmpc_accel_sensitivity_attr = { +static struct device_attribute cmpc_accel_sensitivity_attr = { .attr = { .name = "sensitivity", .mode = 0660 }, .show = cmpc_accel_sensitivity_show, .store = cmpc_accel_sensitivity_store @@ -573,16 +573,17 @@ static int cmpc_ipml_add(struct acpi_device *acpi) 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)) { + /* + * If RFKILL is disabled, rfkill_alloc will return ERR_PTR(-ENODEV). + * This is OK, however, since all other uses of the device will not + * derefence it. + */ + if (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); diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 71ff1545a93..d071ce05632 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -24,17 +24,50 @@ */ /* - * comapl-laptop.c - Compal laptop support. + * compal-laptop.c - Compal laptop support. + * + * This driver exports a few files in /sys/devices/platform/compal-laptop/: + * wake_up_XXX Whether or not we listen to such wake up events (rw) + * + * In addition to these platform device attributes the driver + * registers itself in the Linux backlight control, power_supply, rfkill + * and hwmon subsystem and is available to userspace under: + * + * /sys/class/backlight/compal-laptop/ + * /sys/class/power_supply/compal-laptop/ + * /sys/class/rfkill/rfkillX/ + * /sys/class/hwmon/hwmonX/ + * + * Notes on the power_supply battery interface: + * - the "minimum" design voltage is *the* design voltage + * - the ambient temperature is the average battery temperature + * and the value is an educated guess (see commented code below) * - * The driver registers itself with the rfkill subsystem and - * the Linux backlight control subsystem. * * This driver might work on other laptops produced by Compal. If you * want to try it you can pass force=1 as argument to the module which * will force it to load even when the DMI data doesn't identify the - * laptop as FL9x. + * laptop as compatible. + * + * Lots of data available at: + * http://service1.marasst.com/Compal/JHL90_91/Service%20Manual/ + * JHL90%20service%20manual-Final-0725.pdf + * + * + * + * Support for the Compal JHL90 added by Roald Frederickx + * (roald.frederickx@gmail.com): + * Driver got large revision. Added functionalities: backlight + * power, wake_on_XXX, a hwmon and power_supply interface. + * + * In case this gets merged into the kernel source: I want to dedicate this + * to Kasper Meerts, the awesome guy who showed me Linux and C! */ +/* NOTE: currently the wake_on_XXX, hwmon and power_supply interfaces are + * only enabled on a JHL90 board until it is verified that they work on the + * other boards too. See the extra_features variable. */ + #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -43,71 +76,296 @@ #include <linux/backlight.h> #include <linux/platform_device.h> #include <linux/rfkill.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/power_supply.h> +#include <linux/fb.h> + + +/* ======= */ +/* Defines */ +/* ======= */ +#define DRIVER_NAME "compal-laptop" +#define DRIVER_VERSION "0.2.7" + +#define BACKLIGHT_LEVEL_ADDR 0xB9 +#define BACKLIGHT_LEVEL_MAX 7 +#define BACKLIGHT_STATE_ADDR 0x59 +#define BACKLIGHT_STATE_ON_DATA 0x |