Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (34 commits) classmate-laptop: add support for Classmate PC ACPI devices hp-wmi: Fix two memleaks acer-wmi, msi-wmi: Remove needless DMI MODULE_ALIAS dell-wmi: do not keep driver loaded on unsupported boxes wmi: Free the allocated acpi objects through wmi_get_event_data drivers/platform/x86/acerhdf.c: check BIOS information whether it begins with string of table acerhdf: add new BIOS versions acerhdf: limit modalias matching to supported toshiba_acpi: convert to seq_file asus_acpi: convert to seq_file ACPI: do not select ACPI_DOCK from ATA_ACPI sony-laptop: enumerate rfkill devices using SN06 sony-laptop: rfkill support for newer models ACPI: fix OSC regression that caused aer and pciehp not to load MAINTAINERS: add maintainer for msi-wmi driver fujitu-laptop: fix tests of acpi_evaluate_integer() return value arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c: avoid cross-CPU interrupts by using smp_call_function_any() ACPI: processor: remove _PDC object list from struct acpi_processor ACPI: processor: change acpi_processor_set_pdc() interface ACPI: processor: open code acpi_processor_cleanup_pdc ...
This commit is contained in:
commit
71492fd1bd
32 changed files with 1435 additions and 667 deletions
11
MAINTAINERS
11
MAINTAINERS
|
@ -1472,6 +1472,12 @@ L: linux-scsi@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/scsi/fnic/
|
||||
|
||||
CMPC ACPI DRIVER
|
||||
M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
|
||||
M: Daniel Oliveira Nascimento <don@syst.com.br>
|
||||
S: Supported
|
||||
F: drivers/platform/x86/classmate-laptop.c
|
||||
|
||||
CODA FILE SYSTEM
|
||||
M: Jan Harkes <jaharkes@cs.cmu.edu>
|
||||
M: coda@cs.cmu.edu
|
||||
|
@ -3646,6 +3652,11 @@ W: http://0pointer.de/lennart/tchibo.html
|
|||
S: Maintained
|
||||
F: drivers/platform/x86/msi-laptop.c
|
||||
|
||||
MSI WMI SUPPORT
|
||||
M: Anisse Astier <anisse@astier.eu>
|
||||
S: Supported
|
||||
F: drivers/platform/x86/msi-wmi.c
|
||||
|
||||
MULTIFUNCTION DEVICES (MFD)
|
||||
M: Samuel Ortiz <sameo@linux.intel.com>
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
|
||||
|
|
|
@ -132,6 +132,12 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
|
|||
extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
|
||||
#endif
|
||||
|
||||
static inline bool arch_has_acpi_pdc(void) { return true; }
|
||||
static inline void arch_acpi_set_pdc_bits(u32 *buf)
|
||||
{
|
||||
buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
|
||||
}
|
||||
|
||||
#define acpi_unlazy_tlb(x)
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
|
|
|
@ -18,10 +18,6 @@ obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
|
|||
obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o
|
||||
obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
|
||||
|
||||
ifneq ($(CONFIG_ACPI_PROCESSOR),)
|
||||
obj-y += acpi-processor.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_IA64_PALINFO) += palinfo.o
|
||||
obj-$(CONFIG_IOSAPIC) += iosapic.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* arch/ia64/kernel/acpi-processor.c
|
||||
*
|
||||
* Copyright (C) 2005 Intel Corporation
|
||||
* Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
* - Added _PDC for platforms with Intel CPUs
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <acpi/processor.h>
|
||||
#include <asm/acpi.h>
|
||||
|
||||
static void init_intel_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
union acpi_object *obj;
|
||||
u32 *buf;
|
||||
|
||||
/* allocate and initialize pdc. It will be used later. */
|
||||
obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
|
||||
if (!obj_list) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
if (!obj) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj_list);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = kmalloc(12, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj);
|
||||
kfree(obj_list);
|
||||
return;
|
||||
}
|
||||
|
||||
buf[0] = ACPI_PDC_REVISION_ID;
|
||||
buf[1] = 1;
|
||||
buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
|
||||
/*
|
||||
* The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so
|
||||
* that OSPM is capable of native ACPI throttling software
|
||||
* coordination using BIOS supplied _TSD info.
|
||||
*/
|
||||
buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
|
||||
|
||||
obj->type = ACPI_TYPE_BUFFER;
|
||||
obj->buffer.length = 12;
|
||||
obj->buffer.pointer = (u8 *) buf;
|
||||
obj_list->count = 1;
|
||||
obj_list->pointer = obj;
|
||||
pr->pdc = obj_list;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize _PDC data based on the CPU vendor */
|
||||
void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
pr->pdc = NULL;
|
||||
init_intel_pdc(pr);
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
|
||||
|
||||
void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
if (pr->pdc) {
|
||||
kfree(pr->pdc->pointer->buffer.pointer);
|
||||
kfree(pr->pdc->pointer);
|
||||
kfree(pr->pdc);
|
||||
pr->pdc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
|
|
@ -142,6 +142,32 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
|
|||
return max_cstate;
|
||||
}
|
||||
|
||||
static inline bool arch_has_acpi_pdc(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
return (c->x86_vendor == X86_VENDOR_INTEL ||
|
||||
c->x86_vendor == X86_VENDOR_CENTAUR);
|
||||
}
|
||||
|
||||
static inline void arch_acpi_set_pdc_bits(u32 *buf)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
buf[2] |= ACPI_PDC_C_CAPABILITY_SMP;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_EST))
|
||||
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_ACPI))
|
||||
buf[2] |= ACPI_PDC_T_FFH;
|
||||
|
||||
/*
|
||||
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
|
||||
*/
|
||||
if (!cpu_has(c, X86_FEATURE_MWAIT))
|
||||
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_ACPI */
|
||||
|
||||
#define acpi_lapic 0
|
||||
|
|
|
@ -4,7 +4,7 @@ obj-$(CONFIG_ACPI) += boot.o
|
|||
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o
|
||||
|
||||
ifneq ($(CONFIG_ACPI_PROCESSOR),)
|
||||
obj-y += cstate.o processor.o
|
||||
obj-y += cstate.o
|
||||
endif
|
||||
|
||||
$(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Intel Corporation
|
||||
* Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
* - Added _PDC for platforms with Intel CPUs
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <acpi/processor.h>
|
||||
#include <asm/acpi.h>
|
||||
|
||||
static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
union acpi_object *obj;
|
||||
u32 *buf;
|
||||
|
||||
/* allocate and initialize pdc. It will be used later. */
|
||||
obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
|
||||
if (!obj_list) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
if (!obj) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj_list);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = kmalloc(12, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj);
|
||||
kfree(obj_list);
|
||||
return;
|
||||
}
|
||||
|
||||
buf[0] = ACPI_PDC_REVISION_ID;
|
||||
buf[1] = 1;
|
||||
buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
|
||||
|
||||
/*
|
||||
* The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so
|
||||
* that OSPM is capable of native ACPI throttling software
|
||||
* coordination using BIOS supplied _TSD info.
|
||||
*/
|
||||
buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
|
||||
if (cpu_has(c, X86_FEATURE_EST))
|
||||
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_ACPI))
|
||||
buf[2] |= ACPI_PDC_T_FFH;
|
||||
|
||||
/*
|
||||
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
|
||||
*/
|
||||
if (!cpu_has(c, X86_FEATURE_MWAIT))
|
||||
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
|
||||
|
||||
obj->type = ACPI_TYPE_BUFFER;
|
||||
obj->buffer.length = 12;
|
||||
obj->buffer.pointer = (u8 *) buf;
|
||||
obj_list->count = 1;
|
||||
obj_list->pointer = obj;
|
||||
pr->pdc = obj_list;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize _PDC data based on the CPU vendor */
|
||||
void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(pr->id);
|
||||
|
||||
pr->pdc = NULL;
|
||||
if (c->x86_vendor == X86_VENDOR_INTEL ||
|
||||
c->x86_vendor == X86_VENDOR_CENTAUR)
|
||||
init_intel_pdc(pr, c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
|
||||
|
||||
void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
if (pr->pdc) {
|
||||
kfree(pr->pdc->pointer->buffer.pointer);
|
||||
kfree(pr->pdc->pointer);
|
||||
kfree(pr->pdc);
|
||||
pr->pdc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
|
|
@ -190,9 +190,11 @@ static void do_drv_write(void *_cmd)
|
|||
|
||||
static void drv_read(struct drv_cmd *cmd)
|
||||
{
|
||||
int err;
|
||||
cmd->val = 0;
|
||||
|
||||
smp_call_function_single(cpumask_any(cmd->mask), do_drv_read, cmd, 1);
|
||||
err = smp_call_function_any(cmd->mask, do_drv_read, cmd, 1);
|
||||
WARN_ON_ONCE(err); /* smp_call_function_any() was buggy? */
|
||||
}
|
||||
|
||||
static void drv_write(struct drv_cmd *cmd)
|
||||
|
|
|
@ -32,6 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o
|
|||
#
|
||||
acpi-y += bus.o glue.o
|
||||
acpi-y += scan.o
|
||||
acpi-y += processor_pdc.o
|
||||
acpi-y += ec.o
|
||||
acpi-$(CONFIG_ACPI_DOCK) += dock.o
|
||||
acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
|
||||
|
|
|
@ -185,6 +185,12 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
|
|||
acpi_osi_setup("!Windows 2006");
|
||||
return 0;
|
||||
}
|
||||
static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
|
||||
acpi_osi_setup("!Windows 2009");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
||||
{
|
||||
|
@ -211,6 +217,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = dmi_disable_osi_win7,
|
||||
.ident = "ASUS K50IJ",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
|
||||
|
|
|
@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
|
|||
union acpi_object *out_obj;
|
||||
u8 uuid[16];
|
||||
u32 errors;
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
||||
if (!context)
|
||||
return AE_ERROR;
|
||||
|
@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
|
|||
in_params[3].buffer.length = context->cap.length;
|
||||
in_params[3].buffer.pointer = context->cap.pointer;
|
||||
|
||||
status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret);
|
||||
status = acpi_evaluate_object(handle, "_OSC", &input, &output);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
/* return buffer should have the same length as cap buffer */
|
||||
if (context->ret.length != context->cap.length)
|
||||
if (!output.length)
|
||||
return AE_NULL_OBJECT;
|
||||
|
||||
out_obj = context->ret.pointer;
|
||||
if (out_obj->type != ACPI_TYPE_BUFFER) {
|
||||
out_obj = output.pointer;
|
||||
if (out_obj->type != ACPI_TYPE_BUFFER
|
||||
|| out_obj->buffer.length != context->cap.length) {
|
||||
acpi_print_osc_error(handle, context,
|
||||
"_OSC evaluation returned wrong type");
|
||||
status = AE_TYPE;
|
||||
|
@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
|
|||
goto out_kfree;
|
||||
}
|
||||
out_success:
|
||||
return AE_OK;
|
||||
context->ret.length = out_obj->buffer.length;
|
||||
context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
|
||||
if (!context->ret.pointer) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto out_kfree;
|
||||
}
|
||||
memcpy(context->ret.pointer, out_obj->buffer.pointer,
|
||||
context->ret.length);
|
||||
status = AE_OK;
|
||||
|
||||
out_kfree:
|
||||
kfree(context->ret.pointer);
|
||||
context->ret.pointer = NULL;
|
||||
kfree(output.pointer);
|
||||
if (status != AE_OK)
|
||||
context->ret.pointer = NULL;
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_run_osc);
|
||||
|
@ -888,6 +898,8 @@ static int __init acpi_bus_init(void)
|
|||
goto error1;
|
||||
}
|
||||
|
||||
acpi_early_processor_set_pdc();
|
||||
|
||||
/*
|
||||
* Maybe EC region is required at bus_scan/acpi_get_devices. So it
|
||||
* is necessary to enable it as early as possible.
|
||||
|
|
|
@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
|
|||
/* MSI EC needs special treatment, enable it */
|
||||
static int ec_flag_msi(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
|
||||
EC_FLAGS_MSI = 1;
|
||||
EC_FLAGS_VALIDATE_ECDT = 1;
|
||||
return 0;
|
||||
|
@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
|
|||
DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
|
||||
{
|
||||
ec_flag_msi, "MSI hardware", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"),
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL},
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL},
|
||||
{
|
||||
ec_flag_msi, "MSI hardware", {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL},
|
||||
{
|
||||
ec_flag_msi, "MSI hardware", {
|
||||
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
|
||||
{
|
||||
ec_validate_ecdt, "ASUS hardware", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
|
||||
|
|
|
@ -43,6 +43,7 @@ int acpi_power_transition(struct acpi_device *device, int state);
|
|||
extern int acpi_power_nocheck;
|
||||
|
||||
int acpi_wakeup_device_init(void);
|
||||
void acpi_early_processor_set_pdc(void);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Embedded Controller
|
||||
|
|
|
@ -124,29 +124,6 @@ static const struct file_operations acpi_processor_info_fops = {
|
|||
|
||||
DEFINE_PER_CPU(struct acpi_processor *, processors);
|
||||
struct acpi_processor_errata errata __read_mostly;
|
||||
static int set_no_mwait(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "%s detected - "
|
||||
"disabling mwait for CPU C-states\n", id->ident);
|
||||
idle_nomwait = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
|
||||
{
|
||||
set_no_mwait, "IFL91 board", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
|
||||
{
|
||||
set_no_mwait, "Extensa 5220", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Errata Handling
|
||||
|
@ -276,45 +253,6 @@ static int acpi_processor_errata(struct acpi_processor *pr)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Common ACPI processor functions
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* _PDC is required for a BIOS-OS handshake for most of the newer
|
||||
* ACPI processor features.
|
||||
*/
|
||||
static int acpi_processor_set_pdc(struct acpi_processor *pr)
|
||||
{
|
||||
struct acpi_object_list *pdc_in = pr->pdc;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
if (!pdc_in)
|
||||
return status;
|
||||
if (idle_nomwait) {
|
||||
/*
|
||||
* If mwait is disabled for CPU C-states, the C2C3_FFH access
|
||||
* mode will be disabled in the parameter of _PDC object.
|
||||
* Of course C1_FFH access mode will also be disabled.
|
||||
*/
|
||||
union acpi_object *obj;
|
||||
u32 *buffer = NULL;
|
||||
|
||||
obj = pdc_in->pointer;
|
||||
buffer = (u32 *)(obj->buffer.pointer);
|
||||
buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
|
||||
|
||||
}
|
||||
status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Could not evaluate _PDC, using legacy perf. control...\n"));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
FS Interface (/proc)
|
||||
-------------------------------------------------------------------------- */
|
||||
|
@ -825,9 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
|
|||
}
|
||||
|
||||
/* _PDC call should be done before doing anything else (if reqd.). */
|
||||
arch_acpi_processor_init_pdc(pr);
|
||||
acpi_processor_set_pdc(pr);
|
||||
arch_acpi_processor_cleanup_pdc(pr);
|
||||
acpi_processor_set_pdc(pr->handle);
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
acpi_processor_ppc_has_changed(pr, 0);
|
||||
|
@ -1145,11 +1081,6 @@ static int __init acpi_processor_init(void)
|
|||
if (!acpi_processor_dir)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
/*
|
||||
* Check whether the system is DMI table. If yes, OSPM
|
||||
* should not use mwait for CPU-states.
|
||||
*/
|
||||
dmi_check_system(processor_idle_dmi_table);
|
||||
result = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (result < 0)
|
||||
goto out_proc;
|
||||
|
|
165
drivers/acpi/processor_pdc.c
Normal file
165
drivers/acpi/processor_pdc.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Intel Corporation
|
||||
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Alex Chiang <achiang@hp.com>
|
||||
* - Unified x86/ia64 implementations
|
||||
* Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
* - Added _PDC for platforms with Intel CPUs
|
||||
*/
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/processor.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_pdc");
|
||||
|
||||
static int set_no_mwait(const struct dmi_system_id *id)
|
||||
{
|
||||
printk(KERN_NOTICE PREFIX "%s detected - "
|
||||
"disabling mwait for CPU C-states\n", id->ident);
|
||||
idle_nomwait = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
|
||||
{
|
||||
set_no_mwait, "IFL91 board", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
|
||||
{
|
||||
set_no_mwait, "Extensa 5220", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
static void acpi_set_pdc_bits(u32 *buf)
|
||||
{
|
||||
buf[0] = ACPI_PDC_REVISION_ID;
|
||||
buf[1] = 1;
|
||||
|
||||
/* Enable coordination with firmware's _TSD info */
|
||||
buf[2] = ACPI_PDC_SMP_T_SWCOORD;
|
||||
|
||||
/* Twiddle arch-specific bits needed for _PDC */
|
||||
arch_acpi_set_pdc_bits(buf);
|
||||
}
|
||||
|
||||
static struct acpi_object_list *acpi_processor_alloc_pdc(void)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
union acpi_object *obj;
|
||||
u32 *buf;
|
||||
|
||||
/* allocate and initialize pdc. It will be used later. */
|
||||
obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
|
||||
if (!obj_list) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
if (!obj) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = kmalloc(12, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "Memory allocation error\n");
|
||||
kfree(obj);
|
||||
kfree(obj_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acpi_set_pdc_bits(buf);
|
||||
|
||||
obj->type = ACPI_TYPE_BUFFER;
|
||||
obj->buffer.length = 12;
|
||||
obj->buffer.pointer = (u8 *) buf;
|
||||
obj_list->count = 1;
|
||||
obj_list->pointer = obj;
|
||||
|
||||
return obj_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* _PDC is required for a BIOS-OS handshake for most of the newer
|
||||
* ACPI processor features.
|
||||
*/
|
||||
static int
|
||||
acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (idle_nomwait) {
|
||||
/*
|
||||
* If mwait is disabled for CPU C-states, the C2C3_FFH access
|
||||
* mode will be disabled in the parameter of _PDC object.
|
||||
* Of course C1_FFH access mode will also be disabled.
|
||||
*/
|
||||
union acpi_object *obj;
|
||||
u32 *buffer = NULL;
|
||||
|
||||
obj = pdc_in->pointer;
|
||||
buffer = (u32 *)(obj->buffer.pointer);
|
||||
buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
|
||||
|
||||
}
|
||||
status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Could not evaluate _PDC, using legacy perf. control.\n"));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void acpi_processor_set_pdc(acpi_handle handle)
|
||||
{
|
||||
struct acpi_object_list *obj_list;
|
||||
|
||||
if (arch_has_acpi_pdc() == false)
|
||||
return;
|
||||
|
||||
obj_list = acpi_processor_alloc_pdc();
|
||||
if (!obj_list)
|
||||
return;
|
||||
|
||||
acpi_processor_eval_pdc(handle, obj_list);
|
||||
|
||||
kfree(obj_list->pointer->buffer.pointer);
|
||||
kfree(obj_list->pointer);
|
||||
kfree(obj_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
|
||||
|
||||
static acpi_status
|
||||
early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
acpi_processor_set_pdc(handle);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void acpi_early_processor_set_pdc(void)
|
||||
{
|
||||
/*
|
||||
* Check whether the system is DMI table. If yes, OSPM
|
||||
* should not use mwait for CPU-states.
|
||||
*/
|
||||
dmi_check_system(processor_idle_dmi_table);
|
||||
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
early_init_pdc, NULL, NULL, NULL);
|
||||
}
|
|
@ -40,7 +40,6 @@ config ATA_VERBOSE_ERROR
|
|||
config ATA_ACPI
|
||||
bool "ATA ACPI Support"
|
||||
depends on ACPI && PCI
|
||||
select ACPI_DOCK
|
||||
default y
|
||||
help
|
||||
This option adds support for ATA-related ACPI objects.
|
||||
|
|
|
@ -464,4 +464,16 @@ config TOSHIBA_BT_RFKILL
|
|||
|
||||
If you have a modern Toshiba laptop with a Bluetooth and an
|
||||
RFKill switch (such as the Portege R500), say Y.
|
||||
|
||||
config ACPI_CMPC
|
||||
tristate "CMPC Laptop Extras"
|
||||
depends on X86 && ACPI
|
||||
select INPUT
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
default n
|
||||
help
|
||||
Support for Intel Classmate PC ACPI devices, including some
|
||||
keys as input device, backlight device, tablet and accelerometer
|
||||
devices.
|
||||
|
||||
endif # X86_PLATFORM_DEVICES
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
|
||||
obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
|
||||
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
|
||||
obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
|
||||
obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
|
||||
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
|
||||
obj-$(CONFIG_DELL_WMI) += dell-wmi.o
|
||||
|
|
|
@ -96,9 +96,6 @@ struct acer_quirks {
|
|||
MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
|
||||
MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3");
|
||||
|
||||
/* Temporary workaround until the WMI sysfs interface goes in */
|
||||
MODULE_ALIAS("dmi:*:*Acer*:*:");
|
||||
|
||||
/*
|
||||
* Interface capability flags
|
||||
*/
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
*/
|
||||
#undef START_IN_KERNEL_MODE
|
||||
|
||||
#define DRV_VER "0.5.20"
|
||||
#define DRV_VER "0.5.22"
|
||||
|
||||
/*
|
||||
* According to the Atom N270 datasheet,
|
||||
|
@ -156,19 +156,25 @@ static const struct bios_settings_t bios_tbl[] = {
|
|||
{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} },
|
||||
/* Acer 1410 */
|
||||
{"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} },
|
||||
/* special BIOS / other */
|
||||
{"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 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} },
|
||||
/* 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", "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} },
|
||||
/* 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} },
|
||||
/* pewpew-terminator */
|
||||
{"", "", "", 0, 0, {0, 0, 0} }
|
||||
};
|
||||
|
@ -486,13 +492,26 @@ static struct platform_driver acerhdf_driver = {
|
|||
.remove = acerhdf_remove,
|
||||
};
|
||||
|
||||
/* checks if str begins with start */
|
||||
static int str_starts_with(const char *str, const char *start)
|
||||
{
|
||||
unsigned long str_len = 0, start_len = 0;
|
||||
|
||||
str_len = strlen(str);
|
||||
start_len = strlen(start);
|
||||
|
||||
if (str_len >= start_len &&
|
||||
!strncmp(str, start, start_len))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check hardware */
|
||||
static int acerhdf_check_hardware(void)
|
||||
{
|
||||
char const *vendor, *version, *product;
|
||||
int i;
|
||||
unsigned long prod_len = 0;
|
||||
const struct bios_settings_t *bt = NULL;
|
||||
|
||||
/* get BIOS data */
|
||||
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
|
||||
|
@ -514,20 +533,20 @@ static int acerhdf_check_hardware(void)
|
|||
kernelmode = 0;
|
||||
}
|
||||
|
||||
prod_len = strlen(product);
|
||||
|
||||
if (verbose)
|
||||
pr_info("BIOS info: %s %s, product: %s\n",
|
||||
vendor, version, product);
|
||||
|
||||
/* search BIOS version and vendor in BIOS settings table */
|
||||
for (i = 0; bios_tbl[i].version[0]; i++) {
|
||||
if (strlen(bios_tbl[i].product) >= prod_len &&
|
||||
!strncmp(bios_tbl[i].product, product,
|
||||
strlen(bios_tbl[i].product)) &&
|
||||
!strcmp(bios_tbl[i].vendor, vendor) &&
|
||||
!strcmp(bios_tbl[i].version, version)) {
|
||||
bios_cfg = &bios_tbl[i];
|
||||
for (bt = bios_tbl; bt->vendor[0]; bt++) {
|
||||
/*
|
||||
* check if actual hardware BIOS vendor, product and version
|
||||
* IDs start with the strings of BIOS table entry
|
||||
*/
|
||||
if (str_starts_with(vendor, bt->vendor) &&
|
||||
str_starts_with(product, bt->product) &&
|
||||
str_starts_with(version, bt->version)) {
|
||||
bios_cfg = bt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -640,9 +659,14 @@ static void __exit acerhdf_exit(void)
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Peter Feuerer");
|
||||
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:*:");
|
||||
MODULE_ALIAS("dmi:*:*Gateway*:*:");
|
||||
MODULE_ALIAS("dmi:*:*Packard Bell*:*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
|
||||
MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
|
||||
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_init(acerhdf_init);
|
||||
module_exit(acerhdf_exit);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
|
@ -513,26 +514,12 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
|
|||
return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
|
||||
}
|
||||
|
||||
/*
|
||||
* We write our info in page, we begin at offset off and cannot write more
|
||||
* than count bytes. We set eof to 1 if we handle those 2 values. We return the
|
||||
* number of bytes written in page
|
||||
*/
|
||||
static int
|
||||
proc_read_info(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int asus_info_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int len = 0;
|
||||
int temp;
|
||||
char buf[16]; /* enough for all info */
|
||||
/*
|
||||
* We use the easy way, we don't care of off and count,
|
||||
* so we don't set eof to 1
|
||||
*/
|
||||
|
||||
len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
|
||||
len += sprintf(page + len, "Model reference : %s\n",
|
||||
hotk->methods->name);
|
||||
seq_printf(m, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
|
||||
seq_printf(m, "Model reference : %s\n", hotk->methods->name);
|
||||
/*
|
||||
* The SFUN method probably allows the original driver to get the list
|
||||
* of features supported by a given model. For now, 0x0100 or 0x0800
|
||||
|
@ -540,8 +527,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
|
|||
* The significance of others is yet to be found.
|
||||
*/
|
||||
if (read_acpi_int(hotk->handle, "SFUN", &temp))
|
||||
len +=
|
||||
sprintf(page + len, "SFUN value : 0x%04x\n", temp);
|
||||
seq_printf(m, "SFUN value : 0x%04x\n", temp);
|
||||
/*
|
||||
* Another value for userspace: the ASYM method returns 0x02 for
|
||||
* battery low and 0x04 for battery critical, its readings tend to be
|
||||
|
@ -550,30 +536,34 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
|
|||
* silently ignored.
|
||||
*/
|
||||
if (read_acpi_int(hotk->handle, "ASYM", &temp))
|
||||
len +=
|
||||
sprintf(page + len, "ASYM value : 0x%04x\n", temp);
|
||||
seq_printf(m, "ASYM value : 0x%04x\n", temp);
|
||||
if (asus_info) {
|
||||
snprintf(buf, 16, "%d", asus_info->length);
|
||||
len += sprintf(page + len, "DSDT length : %s\n", buf);
|
||||
snprintf(buf, 16, "%d", asus_info->checksum);
|
||||
len += sprintf(page + len, "DSDT checksum : %s\n", buf);
|
||||
snprintf(buf, 16, "%d", asus_info->revision);
|
||||
len += sprintf(page + len, "DSDT revision : %s\n", buf);
|
||||
snprintf(buf, 7, "%s", asus_info->oem_id);
|
||||
len += sprintf(page + len, "OEM id : %s\n", buf);
|
||||
snprintf(buf, 9, "%s", asus_info->oem_table_id);
|
||||
len += sprintf(page + len, "OEM table id : %s\n", buf);
|
||||
snprintf(buf, 16, "%x", asus_info->oem_revision);
|
||||
len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
|
||||
snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
|
||||
len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
|
||||
snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
|
||||
len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
|
||||
seq_printf(m, "DSDT length : %d\n", asus_info->length);
|
||||
seq_printf(m, "DSDT checksum : %d\n", asus_info->checksum);
|
||||
seq_printf(m, "DSDT revision : %d\n", asus_info->revision);
|
||||
seq_printf(m, "OEM id : %.*s\n", ACPI_OEM_ID_SIZE, asus_info->oem_id);
|
||||
seq_printf(m, "OEM table id : %.*s\n", ACPI_OEM_TABLE_ID_SIZE, asus_info->oem_table_id);
|
||||
seq_printf(m, "OEM revision : 0x%x\n", asus_info->oem_revision);
|
||||
seq_printf(m, "ASL comp vendor id : %.*s\n", ACPI_NAME_SIZE, asus_info->asl_compiler_id);
|
||||
seq_printf(m, "ASL comp revision : 0x%x\n", asus_info->asl_compiler_revision);
|
||||
}
|
||||
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asus_info_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, asus_info_proc_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations asus_info_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = asus_info_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* /proc handlers
|
||||
* We write our info in page, we begin at offset off and cannot write more
|
||||
|
@ -639,34 +629,48 @@ write_led(const char __user *buffer, unsigned long count,
|
|||
/*
|
||||
* Proc handlers for MLED
|
||||
*/
|
||||
static int
|
||||
proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int mled_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n",
|
||||
read_led(hotk->methods->mled_status, MLED_ON));
|
||||
seq_printf(m, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_mled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int mled_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mled_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t mled_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
|
||||
}
|
||||
|
||||
static const struct file_operations mled_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mled_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = mled_proc_write,
|
||||
};
|
||||
|
||||
/*
|
||||
* Proc handlers for LED display
|
||||
*/
|
||||
static int
|
||||
proc_read_ledd(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int ledd_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "0x%08x\n", hotk->ledd_status);
|
||||
seq_printf(m, "0x%08x\n", hotk->ledd_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_ledd(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int ledd_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, ledd_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t ledd_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int rv, value;
|
||||
|
||||
|
@ -682,61 +686,104 @@ proc_write_ledd(struct file *file, const char __user *buffer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static const struct file_operations ledd_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ledd_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = ledd_proc_write,
|
||||
};
|
||||
|
||||
/*
|
||||
* Proc handlers for WLED
|
||||
*/
|
||||
static int
|
||||
proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int wled_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n",
|
||||
read_led(hotk->methods->wled_status, WLED_ON));
|
||||
seq_printf(m, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_wled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int wled_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wled_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t wled_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
|
||||
}
|
||||
|
||||
static const struct file_operations wled_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = wled_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = wled_proc_write,
|
||||
};
|
||||
|
||||
/*
|
||||
* Proc handlers for Bluetooth
|
||||
*/
|
||||
static int
|
||||
proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int bluetooth_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON));
|
||||
seq_printf(m, "%d\n", read_led(hotk->methods->bt_status, BT_ON));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_bluetooth(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int bluetooth_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, bluetooth_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t bluetooth_proc_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *pos)
|
||||
{
|
||||
/* Note: mt_bt_switch controls both internal Bluetooth adapter's
|
||||
presence and its LED */
|
||||
return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
|
||||
}
|
||||
|
||||
static const struct file_operations bluetooth_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = bluetooth_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = bluetooth_proc_write,
|
||||
};
|
||||
|
||||
/*
|
||||
* Proc handlers for TLED
|
||||
*/
|
||||
static int
|
||||
proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int tled_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n",
|
||||
read_led(hotk->methods->tled_status, TLED_ON));
|
||||
seq_printf(m, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_tled(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int tled_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, tled_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t tled_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
|
||||
}
|
||||
|
||||
static const struct file_operations tled_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tled_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = tled_proc_write,
|
||||
};
|
||||
|
||||
static int get_lcd_state(void)
|
||||
{
|
||||
int lcd = 0;
|
||||
|
@ -829,16 +876,19 @@ static int set_lcd_state(int value)
|
|||
|
||||
}
|
||||
|
||||
static int
|
||||
proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int lcd_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n", get_lcd_state());
|
||||
seq_printf(m, "%d\n", get_lcd_state());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_lcd(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int lcd_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, lcd_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t lcd_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int rv, value;
|
||||
|
||||
|
@ -848,6 +898,15 @@ proc_write_lcd(struct file *file, const char __user *buffer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static const struct file_operations lcd_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = lcd_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = lcd_proc_write,
|
||||
};
|
||||
|
||||
static int read_brightness(struct backlight_device *bd)
|
||||
{
|
||||
int value;
|
||||
|
@ -907,16 +966,19 @@ static int set_brightness_status(struct backlight_device *bd)
|
|||
return set_brightness(bd->props.brightness);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int brn_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return sprintf(page, "%d\n", read_brightness(NULL));
|
||||
seq_printf(m, "%d\n", read_brightness(NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_write_brn(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int brn_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, brn_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t brn_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int rv, value;
|
||||
|
||||
|
@ -929,6 +991,15 @@ proc_write_brn(struct file *file, const char __user *buffer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static const struct file_operations brn_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = brn_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = brn_proc_write,
|
||||
};
|
||||
|
||||
static void set_display(int value)
|
||||
{
|
||||
/* no sanity check needed for now */
|
||||
|
@ -942,9 +1013,7 @@ static void set_display(int value)
|
|||
* Now, *this* one could be more user-friendly, but so far, no-one has
|
||||
* complained. The significance of bits is the same as in proc_write_disp()
|
||||
*/
|
||||
static int
|
||||
proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
static int disp_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
|
@ -952,7 +1021,13 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
|
|||
printk(KERN_WARNING
|
||||
"Asus ACPI: Error reading display status\n");
|
||||
value &= 0x07; /* needed for some models, shouldn't hurt others */
|
||||
return sprintf(page, "%d\n", value);
|
||||
seq_printf(m, "%d\n", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disp_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, disp_proc_show, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -961,9 +1036,8 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
|
|||
* (bitwise) of these will suffice. I never actually tested 3 displays hooked
|
||||
* up simultaneously, so be warned. See the acpi4asus README for more info.
|
||||
*/
|
||||
static int
|
||||
proc_write_disp(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static ssize_t disp_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int rv, value;
|
||||
|
||||
|
@ -973,25 +1047,27 @@ proc_write_disp(struct file *file, const char __user *buffer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
typedef int (proc_writefunc) (struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data);
|
||||
static const struct file_operations disp_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = disp_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = disp_proc_write,
|
||||
};
|
||||
|
||||
static int
|
||||
asus_proc_add(char *name, proc_writefunc *writefunc,
|
||||
proc_readfunc *readfunc, mode_t mode,
|
||||
asus_proc_add(char *name, const struct file_operations *proc_fops, mode_t mode,
|
||||
struct acpi_device *device)
|
||||
{
|
||||
struct proc_dir_entry *proc =
|
||||
create_proc_entry(name, mode, acpi_device_dir(device));
|
||||
struct proc_dir_entry *proc;
|
||||
|
||||
proc = proc_create_data(name, mode, acpi_device_dir(device),
|
||||
proc_fops, acpi_driver_data(device));
|
||||
if (!proc) {
|
||||
printk(KERN_WARNING " Unable to create %s fs entry\n", name);
|
||||
return -1;
|
||||
}
|
||||
proc->write_proc = writefunc;
|
||||
proc->read_proc = readfunc;
|
||||
proc->data = acpi_driver_data(device);
|
||||
proc->uid = asus_uid;
|
||||
proc->gid = asus_gid;
|
||||
return 0;
|
||||
|
@ -1020,10 +1096,9 @@ static int asus_hotk_add_fs(struct acpi_device *device)
|
|||
if (!acpi_device_dir(device))
|
||||
return -ENODEV;
|
||||
|
||||
proc = create_proc_entry(PROC_INFO, mode, acpi_device_dir(device));
|
||||
proc = proc_create(PROC_INFO, mode, acpi_device_dir(device),
|
||||
&asus_info_proc_fops);
|
||||
if (proc) {
|
||||
proc->read_proc = proc_read_info;
|
||||
proc->data = acpi_driver_data(device);
|
||||
proc->uid = asus_uid;
|
||||
proc->gid = asus_gid;
|
||||
} else {
|
||||
|
@ -1032,28 +1107,23 @@ static int asus_hotk_add_fs(struct acpi_device *device)
|
|||
}
|
||||
|
||||
if (hotk->methods->mt_wled) {
|
||||
asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled,
|
||||
mode, device);
|
||||
asus_proc_add(PROC_WLED, &wled_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if (hotk->methods->mt_ledd) {
|
||||
asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd,
|
||||
mode, device);
|
||||
asus_proc_add(PROC_LEDD, &ledd_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if (hotk->methods->mt_mled) {
|
||||
asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled,
|
||||
mode, device);
|
||||
asus_proc_add(PROC_MLED, &mled_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if (hotk->methods->mt_tled) {
|
||||
asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled,
|
||||
mode, device);
|
||||
asus_proc_add(PROC_TLED, &tled_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if (hotk->methods->mt_bt_switch) {
|
||||
asus_proc_add(PROC_BT, &proc_write_bluetooth,
|
||||
&proc_read_bluetooth, mode, device);
|
||||
asus_proc_add(PROC_BT, &bluetooth_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1061,19 +1131,16 @@ static int asus_hotk_add_fs(struct acpi_device *device)
|
|||
* accessible from the keyboard
|
||||
*/
|
||||
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
|
||||
asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode,
|
||||
device);
|
||||
asus_proc_add(PROC_LCD, &lcd_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
|
||||
(hotk->methods->brightness_get && hotk->methods->brightness_set)) {
|
||||
asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode,
|
||||
device);
|
||||
asus_proc_add(PROC_BRN, &brn_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
if (hotk->methods->display_set) {
|
||||
asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp,
|
||||
mode, device);
|
||||
asus_proc_add(PROC_DISP, &disp_proc_fops, mode, device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
609
drivers/platform/x86/classmate-laptop.c
Normal file
609
drivers/platform/x86/classmate-laptop.c
Normal file
|
@ -0,0 +1,609 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
struct cmpc_accel {
|
||||
int sensitivity;
|
||||
};
|
||||
|
||||
#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5
|
||||
|
||||
|
||||
/*
|
||||
* Generic input device code.
|
||||
*/
|
||||
|
||||
typedef void (*input_device_init)(struct input_dev *dev);
|
||||
|
||||
static int cmpc_add_acpi_notify_device(struct acpi_device *acpi, char *name,
|
||||
input_device_init idev_init)
|
||||
{
|
||||
struct input_dev *inputdev;
|
||||
int error;
|
||||
|
||||
inputdev = input_allocate_device();
|
||||
if (!inputdev)
|
||||
return -ENOMEM;
|
||||
inputdev->name = name;
|
||||
inputdev->dev.parent = &acpi->dev;
|
||||
idev_init(inputdev);
|
||||
error = input_register_device(inputdev);
|
||||
if (error) {
|
||||
input_free_device(inputdev);
|
||||
return error;
|
||||
}
|
||||
dev_set_drvdata(&acpi->dev, inputdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi)
|
||||
{
|
||||
struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
|
||||
input_unregister_device(inputdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accelerometer code.
|
||||
*/
|
||||
static acpi_status cmpc_start_accel(acpi_handle handle)
|
||||
{
|
||||
union acpi_object param[2];
|
||||
struct acpi_object_list input;
|
||||
acpi_status status;
|
||||
|
||||
param[0].type = ACPI_TYPE_INTEGER;
|
||||
param[0].integer.value = 0x3;
|
||||
param[1].type = ACPI_TYPE_INTEGER;
|
||||
input.count = 2;
|
||||
input.pointer = param;
|
||||
status = acpi_evaluate_object(handle, "ACMD", &input, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status cmpc_stop_accel(acpi_handle handle)
|
||||
{
|
||||
union acpi_object param[2];
|
||||
struct acpi_object_list input;
|
||||
acpi_status status;
|
||||
|
||||
param[0].type = ACPI_TYPE_INTEGER;
|
||||
param[0].integer.value = 0x4;
|
||||
param[1].type = ACPI_TYPE_INTEGER;
|
||||
input.count = 2;
|
||||
input.pointer = param;
|
||||
status = acpi_evaluate_object(handle, "ACMD", &input, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status cmpc_accel_set_sensitivity(acpi_handle handle, int val)
|
||||
{
|
||||
union acpi_object param[2];
|
||||
struct acpi_object_list input;
|
||||
|
||||
param[0].type = ACPI_TYPE_INTEGER;
|
||||
param[0].integer.value = 0x02;
|
||||
param[1].type = ACPI_TYPE_INTEGER;
|
||||
param[1].integer.value = val;
|
||||
input.count = 2;
|
||||
input.pointer = param;
|
||||
return acpi_evaluate_object(handle, "ACMD", &input, NULL);
|
||||
}
|
||||
|
||||
static acpi_status cmpc_get_accel(acpi_handle handle,
|
||||
unsigned char *x,
|
||||
unsigned char *y,
|
||||
unsigned char *z)
|
||||
{
|
||||
union acpi_object param[2];
|
||||
struct acpi_object_list input;
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, 0 };
|
||||
unsigned char *locs;
|
||||
acpi_status status;
|
||||
|
||||
param[0].type = ACPI_TYPE_INTEGER;
|
||||
param[0].integer.value = 0x01;
|
||||
param[1].type = ACPI_TYPE_INTEGER;
|
||||
input.count = 2;
|
||||
input.pointer = param;
|
||||
status = acpi_evaluate_object(handle, "ACMD", &input, &output);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
union acpi_object *obj;
|
||||
obj = output.pointer;
|
||||
locs = obj->buffer.pointer;
|
||||
*x = locs[0];
|
||||
*y = locs[1];
|
||||
*z = locs[2];
|
||||
kfree(output.pointer);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void cmpc_accel_handler(struct acpi_device *dev, u32 event)
|
||||
{
|
||||
if (event == 0x81) {
|
||||
unsigned char x, y, z;
|
||||
acpi_status status;
|
||||
|
||||
status = cmpc_get_accel(dev->handle, &x, &y, &z);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
struct input_dev *inputdev = dev_get_drvdata(&dev->dev);
|
||||
|
||||
input_report_abs(inputdev, ABS_X, x);
|
||||
input_report_abs(inputdev, ABS_Y, y);
|
||||
input_report_abs(inputdev, ABS_Z, z);
|
||||
input_sync(inputdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t cmpc_accel_sensitivity_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct acpi_device *acpi;
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
|
||||
acpi = to_acpi_device(dev);
|
||||
inputdev = dev_get_drvdata(&acpi->dev);
|
||||
accel = dev_get_drvdata(&inputdev->dev);
|
||||
|
||||
return sprintf(buf, "%d\n", accel->sensitivity);
|
||||
}
|
||||
|
||||
static ssize_t cmpc_accel_sensitivity_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct acpi_device *acpi;
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
unsigned long sensitivity;
|
||||
int r;
|
||||
|
||||
acpi = to_acpi_device(dev);
|
||||
inputdev = dev_get_drvdata(&acpi->dev);
|
||||
accel = dev_get_drvdata(&inputdev->dev);
|
||||
|
||||
r = strict_strtoul(buf, 0, &sensitivity);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
accel->sensitivity = sensitivity;
|
||||
cmpc_accel_set_sensitivity(acpi->handle, sensitivity);
|
||||
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
struct device_attribute cmpc_accel_sensitivity_attr = {
|
||||
.attr = { .name = "sensitivity", .mode = 0660 },
|
||||
.show = cmpc_accel_sensitivity_show,
|
||||
.store = cmpc_accel_sensitivity_store
|
||||
};
|
||||
|
||||
static int cmpc_accel_open(struct input_dev *input)
|
||||
{
|
||||
struct acpi_device *acpi;
|
||||
|
||||
acpi = to_acpi_device(input->dev.parent);
|
||||
if (ACPI_SUCCESS(cmpc_start_accel(acpi->handle)))
|
||||
return 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void cmpc_accel_close(struct input_dev *input)
|
||||
{
|
||||
struct acpi_device *acpi;
|
||||
|
||||
acpi = to_acpi_device(input->dev.parent);
|
||||
cmpc_stop_accel(acpi->handle);
|
||||
}
|
||||
|
||||
static void cmpc_accel_idev_init(struct input_dev *inputdev)
|
||||
{
|
||||
set_bit(EV_ABS, inputdev->evbit);
|
||||
input_set_abs_params(inputdev, ABS_X, 0, 255, 8, 0);
|
||||
input_set_abs_params(inputdev, ABS_Y, 0, 255, 8, 0);
|
||||
input_set_abs_params(inputdev, ABS_Z, 0, 255, 8, 0);
|
||||
inputdev->open = cmpc_accel_open;
|
||||
inputdev->close = cmpc_accel_close;
|
||||
}
|
||||
|
||||
static int cmpc_accel_add(struct acpi_device *acpi)
|
||||
{
|
||||
int error;
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
|
||||
accel = kmalloc(sizeof(*accel), GFP_KERNEL);
|
||||
if (!accel)
|
||||
return -ENOMEM;
|
||||
|
||||
accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT;
|
||||
cmpc_accel_set_sensitivity(acpi->handle, accel->sensitivity);
|
||||
|
||||
error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
|
||||
if (error)
|
||||
goto failed_file;
|
||||
|
||||
error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel",
|
||||
cmpc_accel_idev_init);
|
||||
if (error)
|
||||
goto failed_input;
|
||||
|
||||
inputdev = dev_get_drvdata(&acpi->dev);
|
||||
dev_set_drvdata(&inputdev->dev, accel);
|
||||
|
||||
return 0;
|
||||
|
||||
failed_input:
|
||||
device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
|
||||
failed_file:
|
||||
kfree(accel);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmpc_accel_remove(struct acpi_device *acpi, int type)
|
||||
{
|
||||
struct input_dev *inputdev;
|
||||
struct cmpc_accel *accel;
|
||||
|
||||
inputdev = dev_get_drvdata(&acpi->dev);
|
||||
accel = dev_get_drvdata(&inputdev->dev);
|
||||
|
||||
device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr);
|
||||
return cmpc_remove_acpi_notify_device(acpi);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cmpc_accel_device_ids[] = {
|
||||
{"ACCE0000", 0},
|
||||
{"", 0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids);
|
||||
|
||||
static struct acpi_driver cmpc_accel_acpi_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cmpc_accel",
|
||||
.class = "cmpc_accel",
|
||||
.ids = cmpc_accel_device_ids,
|
||||
.ops = {
|
||||
.add = cmpc_accel_add,
|
||||
.remove = cmpc_accel_remove,
|
||||
.notify = cmpc_accel_handler,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Tablet mode code.
|
||||
*/
|
||||
static acpi_status cmpc_get_tablet(acpi_handle handle,
|
||||
unsigned long long *value)
|
||||
{
|
||||
union acpi_object param;
|
||||
struct acpi_object_list input;
|
||||
unsigned long long output;
|
||||
acpi_status status;
|
||||
|
||||
param.type = ACPI_TYPE_INTEGER;
|
||||
param.integer.value = 0x01;
|
||||
input.count = 1;
|
||||
input.pointer = ¶m;
|
||||
status = acpi_evaluate_integer(handle, "TCMD", &input, &output);
|
||||
if (ACPI_SUCCESS(status))
|
||||
*value = output;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void cmpc_tablet_handler(struct acpi_device *dev, u32 event)
|
||||
{
|
||||
unsigned long long val = 0;
|
||||
struct input_dev *inputdev = dev_get_drvdata(&dev->dev);
|
||||
|
||||
if (event == 0x81) {
|
||||
if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val)))
|
||||
input_report_switch(inputdev, SW_TABLET_MODE, !val);
|
||||
}
|
||||
}
|
||||
|
||||
static void cmpc_tablet_idev_init(struct input_dev *inputdev)
|
||||
{
|
||||
unsigned long long val = 0;
|
||||
struct acpi_device *acpi;
|
||||
|
||||
set_bit(EV_SW, inputdev->evbit);
|
||||
set_bit(SW_TABLET_MODE, inputdev->swbit);
|
||||
|
||||
acpi = to_acpi_device(inputdev->dev.parent);
|
||||
if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
|
||||
input_report_switch(inputdev, SW_TABLET_MODE, !val);
|
||||
}
|
||||
|
||||
static int cmpc_tablet_add(struct acpi_device *acpi)
|
||||
{
|
||||
return cmpc_add_acpi_notify_device(acpi, "cmpc_tablet",
|
||||
cmpc_tablet_idev_init);
|
||||
}
|
||||
|
||||
static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
|
||||
{
|
||||
return cmpc_remove_acpi_notify_device(acpi);
|
||||
}
|
||||
|
||||
static int cmpc_tablet_resume(struct acpi_device *acpi)
|
||||
{
|
||||
struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
|
||||
unsigned long long val = 0;
|
||||
if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
|
||||
input_report_switch(inputdev, SW_TABLET_MODE, !val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cmpc_tablet_device_ids[] = {
|
||||
{"TBLT0000", 0},
|
||||
{"", 0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids);
|
||||
|
||||
static struct acpi_driver cmpc_tablet_acpi_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cmpc_tablet",
|
||||
.class = "cmpc_tablet",
|
||||
.ids = cmpc_tablet_device_ids,
|
||||
.ops = {
|
||||
.add = cmpc_tablet_add,
|
||||
.remove = cmpc_tablet_remove,
|
||||
.resume = cmpc_tablet_resume,
|
||||
.notify = cmpc_tablet_handler,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Backlight code.
|
||||
*/
|
||||
|
||||
static acpi_status cmpc_get_brightness(acpi_handle handle,
|
||||
unsigned long long *value)
|
||||
{
|
||||
union acpi_object param;
|
||||
struct acpi_object_list input;
|
||||
unsigned long long output;
|
||||
acpi_status status;
|
||||
|
||||
param.type = ACPI_TYPE_INTEGER;
|
||||
param.integer.value = 0xC0;
|
||||
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_brightness(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 = 0xC0;
|
||||
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 int cmpc_bl_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
unsigned long long brightness;
|
||||
|
||||
handle = bl_get_data(bd);
|
||||
status = cmpc_get_brightness(handle, &brightness);
|
||||
if (ACPI_SUCCESS(status))
|
||||
return brightness;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmpc_bl_update_status(struct backlight_device *bd)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
|
||||
handle = bl_get_data(bd);
|
||||
status = cmpc_set_brightness(handle, bd->props.brightness);
|
||||
if (ACPI_SUCCESS(status))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct backlight_ops cmpc_bl_ops = {
|
||||
.get_brightness = cmpc_bl_get_brightness,
|
||||
.update_status = cmpc_bl_update_status
|
||||
};
|
||||
|
||||
static int cmpc_bl_add(struct acpi_device *acpi)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
|
||||
bd = backlight_device_register("cmpc_bl", &acpi->dev,
|
||||
acpi->handle, &cmpc_bl_ops);
|
||||
bd->props.max_brightness = 7;
|
||||
dev_set_drvdata(&acpi->dev, bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmpc_bl_remove(struct acpi_device *acpi, int type)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
|
||||
bd = dev_get_drvdata(&acpi->dev);
|
||||
backlight_device_unregister(bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cmpc_device_ids[] = {
|
||||
{"IPML200", 0},
|
||||
{"", 0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, cmpc_device_ids);
|
||||
|
||||
static struct acpi_driver cmpc_bl_acpi_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cmpc",
|
||||
.class = "cmpc",
|
||||
.ids = cmpc_device_ids,
|
||||
.ops = {
|
||||
.add = cmpc_bl_add,
|
||||
.remove = cmpc_bl_remove
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Extra keys code.
|
||||
*/
|
||||
static int cmpc_keys_codes[] = {
|
||||
KEY_UNKNOWN,
|
||||
KEY_WLAN,
|
||||
KEY_SWITCHVIDEOMODE,
|
||||
KEY_BRIGHTNESSDOWN,
|
||||
KEY_BRIGHTNESSUP,
|
||||
KEY_VENDOR,
|
||||
KEY_MAX
|
||||
};
|
||||
|
||||
static void cmpc_keys_handler(struct acpi_device *dev, u32 event)
|
||||
{
|
||||
struct input_dev *inputdev;
|
||||
int code = KEY_MAX;
|
||||
|
||||
if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes))
|
||||
code = cmpc_keys_codes[event & 0x0F];
|
||||
inputdev = dev_get_drvdata(&dev->dev);;
|
||||
input_report_key(inputdev, code, !(event & 0x10));
|
||||
}
|
||||
|
||||
static void cmpc_keys_idev_init(struct input_dev *inputdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_bit(EV_KEY, inputdev->evbit);
|
||||
for (i = 0; cmpc_keys_codes[i] != KEY_MAX; i++)
|
||||
set_bit(cmpc_keys_codes[i], inputdev->keybit);
|
||||
}
|
||||
|
||||
static int cmpc_keys_add(struct acpi_device *acpi)
|
||||
{
|
||||
return cmpc_add_acpi_notify_device(acpi, "cmpc_keys",
|
||||
cmpc_keys_idev_init);
|
||||
}
|
||||
|
||||
static int cmpc_keys_remove(struct acpi_device *acpi, int type)
|
||||
{
|
||||
return cmpc_remove_acpi_notify_device(acpi);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id cmpc_keys_device_ids[] = {
|
||||
{"FnBT0000", 0},
|
||||
{"", 0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids);
|
||||
|
||||
static struct acpi_driver cmpc_keys_acpi_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cmpc_keys",
|
||||
.class = "cmpc_keys",
|
||||
.ids = cmpc_keys_device_ids,
|
||||
.ops = {
|
||||
.add = cmpc_keys_add,
|
||||
.remove = cmpc_keys_remove,
|
||||
.notify = cmpc_keys_handler,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* General init/exit code.
|
||||
*/
|
||||
|
||||
static int cmpc_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = acpi_bus_register_driver(&cmpc_keys_acpi_driver);
|
||||
if (r)
|
||||
goto failed_keys;
|
||||
|
||||
r = acpi_bus_register_driver(&cmpc_bl_acpi_driver);
|
||||
if (r)
|
||||
goto failed_bl;
|
||||
|
||||
r = acpi_bus_register_driver(&cmpc_tablet_acpi_driver);
|
||||
if (r)
|
||||
goto failed_tablet;
|
||||
|
||||
r = acpi_bus_register_driver(&cmpc_accel_acpi_driver);
|
||||
if (r)
|
||||
goto failed_accel;
|
||||
|
||||
return r;
|
||||
|
||||
failed_accel:
|
||||
acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver);
|
||||
|
||||
failed_tablet:
|
||||
acpi_bus_unregister_driver(&cmpc_bl_acpi_driver);
|
||||
|
||||
failed_bl:
|
||||
acpi_bus_unregister_driver(&cmpc_keys_acpi_driver);
|
||||
|
||||
failed_keys:
|
||||
return r;
|
||||
}
|
||||
|
||||
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_keys_acpi_driver);
|
||||
}
|
||||
|
||||
module_init(cmpc_init);
|
||||
module_exit(cmpc_exit);
|
|
@ -238,6 +238,7 @@ static void dell_wmi_notify(u32 value, void *context)
|
|||
input_sync(dell_wmi_input_dev);
|
||||
}
|
||||
}
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,37 +325,34 @@ static int __init dell_wmi_init(void)
|
|||
int err;
|
||||
|
||||
if (wmi_has_guid(DELL_EVENT_GUID)) {
|
||||
|
||||
dmi_walk(find_hk_type, NULL);
|
||||
|
||||
err = dell_wmi_input_setup();
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = wmi_install_notify_handler(DELL_EVENT_GUID,
|
||||
dell_wmi_notify, NULL);
|
||||
if (err) {
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
printk(KERN_ERR "dell-wmi: Unable to register"
|
||||
" notify handler - %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
acpi_video = acpi_video_backlight_support();
|
||||
|
||||
} else
|
||||
printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dmi_walk(find_hk_type, NULL);
|
||||
acpi_video = acpi_video_backlight_support();
|
||||
|
||||
err = dell_wmi_input_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = wmi_install_notify_handler(DELL_EVENT_GUID,
|
||||
dell_wmi_notify, NULL);
|
||||
if (err) {
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
printk(KERN_ERR
|
||||
"dell-wmi: Unable to register notify handler - %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dell_wmi_exit(void)
|
||||
{
|
||||
if (wmi_has_guid(DELL_EVENT_GUID)) {
|
||||
wmi_remove_notify_handler(DELL_EVENT_GUID);
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
}
|
||||
wmi_remove_notify_handler(DELL_EVENT_GUID);
|
||||
input_unregister_device(dell_wmi_input_dev);
|
||||
}
|
||||
|
||||
module_init(dell_wmi_init);
|
||||
|
|
|
@ -376,8 +376,8 @@ static int get_lcd_level(void)
|
|||
|
||||
status =
|
||||
acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
fujitsu->brightness_level = state & 0x0fffffff;
|
||||
|
||||
|
@ -398,8 +398,8 @@ static int get_max_brightness(void)
|
|||
|
||||
status =
|
||||
acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (ACPI_FAILURE(status))
|
||||
return -1;
|
||||
|
||||
fujitsu->max_brightness = state;
|
||||
|
||||
|
|
|
@ -134,10 +134,15 @@ static int hp_wmi_perform_query(int query, int write, int value)
|
|||
|
||||
obj = output.pointer;
|
||||
|
||||
if (!obj || obj->type != ACPI_TYPE_BUFFER)
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
else if (obj->type != ACPI_TYPE_BUFFER) {
|
||||
kfree(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bios_return = *((struct bios_return *)obj->buffer.pointer);
|
||||
kfree(obj);
|
||||
if (bios_return.return_code > 0)
|
||||
return bios_return.return_code * -1;
|
||||
else
|
||||
|
@ -340,10 +345,12 @@ static void hp_wmi_notify(u32 value, void *context)
|
|||
|
||||
if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
|
||||
printk(KERN_INFO "HP WMI: Unknown response received\n");
|
||||
kfree(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
eventcode = *((u8 *) obj->buffer.pointer);
|
||||
kfree(obj);
|
||||
if (eventcode == 0x4)
|
||||
eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
|
||||
0);
|
||||
|
@ -381,6 +388,8 @@ static void hp_wmi_notify(u32 value, void *context)
|
|||
} else
|
||||
printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
|
||||
eventcode);
|
||||
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
static int __init hp_wmi_input_setup(void)
|
||||
|
|
|
@ -34,16 +34,6 @@ MODULE_LICENSE("GPL");
|
|||
MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
|
||||
MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
|
||||
|
||||
/* Temporary workaround until the WMI sysfs interface goes in
|
||||
{ "svn", DMI_SYS_VENDOR },
|
||||
{ "pn", DMI_PRODUCT_NAME },
|
||||
{ "pvr", DMI_PRODUCT_VERSION },
|
||||
{ "rvn", DMI_BOARD_VENDOR },
|
||||
{ "rn", DMI_BOARD_NAME },
|
||||
*/
|
||||
|
||||
MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*");
|
||||
|
||||
#define DRV_NAME "msi-wmi"
|
||||
#define DRV_PFX DRV_NAME ": "
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ enum sony_nc_rfkill {
|
|||
N_SONY_RFKILL,
|
||||
};
|
||||
|
||||
static int sony_rfkill_handle;
|
||||
static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
|
||||
static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
|
||||
static void sony_nc_rfkill_update(void);
|
||||
|
@ -232,6 +233,7 @@ static int sony_laptop_input_index[] = {
|
|||
56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
|
||||
57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
|
||||
-1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
|
||||
58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */
|
||||
};
|
||||
|
||||
static int sony_laptop_input_keycode_map[] = {
|
||||
|
@ -293,6 +295,7 @@ static int sony_laptop_input_keycode_map[] = {
|
|||
KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
|
||||
KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
|
||||
KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
|
||||
KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */
|
||||
};
|
||||
|
||||
/* release buttons after a short delay if pressed */
|
||||
|
@ -890,6 +893,8 @@ static struct sony_nc_event sony_100_events[] = {
|
|||
{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
|
||||
{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
|
||||
{ 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
|
||||
{ 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
|
||||
{ 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -961,7 +966,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|||
else
|
||||
sony_laptop_report_input_event(ev);
|
||||
}
|
||||
} else if (sony_find_snc_handle(0x124) == ev) {
|
||||
} else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
|
||||
sony_nc_rfkill_update();
|
||||
return;
|
||||
}
|
||||
|
@ -1067,7 +1072,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked)
|
|||
if (!blocked)
|
||||
argument |= 0xff0000;
|
||||
|
||||
return sony_call_snc_handle(0x124, argument, &result);
|
||||
return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
|
||||
}
|
||||
|
||||
static const struct rfkill_ops sony_rfkill_ops = {
|
||||
|
@ -1110,7 +1115,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
|
|||
if (!rfk)
|
||||
return -ENOMEM;
|
||||
|
||||
sony_call_snc_handle(0x124, 0x200, &result);
|
||||
sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
|
||||
hwblock = !(result & 0x1);
|
||||
rfkill_set_hw_state(rfk, hwblock);
|
||||
|
||||
|
@ -1129,7 +1134,7 @@ static void sony_nc_rfkill_update()
|
|||
int result;
|
||||
bool hwblock;
|
||||
|
||||
sony_call_snc_handle(0x124, 0x200, &result);
|
||||
sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
|
||||
hwblock = !(result & 0x1);
|
||||
|
||||
for (i = 0; i < N_SONY_RFKILL; i++) {
|
||||
|
@ -1145,36 +1150,79 @@ static void sony_nc_rfkill_update()
|
|||
continue;
|
||||
}
|
||||
|
||||
sony_call_snc_handle(0x124, argument, &result);
|
||||
sony_call_snc_handle(sony_rfkill_handle, argument, &result);
|
||||
rfkill_set_states(sony_rfkill_devices[i],
|
||||
!(result & 0xf), false);
|
||||
}
|
||||
}
|
||||
|
||||
static int sony_nc_rfkill_setup(struct acpi_device *device)
|
||||
static void sony_nc_rfkill_setup(struct acpi_device *device)
|
||||
{
|
||||
int result, ret;
|
||||
int offset;
|
||||
u8 dev_code, i;
|
||||
acpi_status status;
|
||||
struct acpi_object_list params;
|
||||
union acpi_object in_obj;
|
||||
union acpi_object *device_enum;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
if (sony_find_snc_handle(0x124) == -1)
|
||||
return -1;
|
||||
offset = sony_find_snc_handle(0x124);
|
||||
if (offset == -1) {
|
||||
offset = sony_find_snc_handle(0x135);
|
||||
if (offset == -1)
|
||||
return;
|
||||
else
|
||||
sony_rfkill_handle = 0x135;
|
||||
} else
|
||||
sony_rfkill_handle = 0x124;
|
||||
dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
|
||||
|
||||
ret = sony_call_snc_handle(0x124, 0xb00, &result);
|
||||
if (ret) {
|
||||
printk(KERN_INFO DRV_PFX
|
||||
"Unable to enumerate rfkill devices: %x\n", ret);
|
||||
return ret;
|
||||
/* need to read the whole buffer returned by the acpi call to SN06
|
||||
* here otherwise we may miss some features
|
||||
*/
|
||||
params.count = 1;
|
||||
params.pointer = &in_obj;
|
||||
in_obj.type = ACPI_TYPE_INTEGER;
|
||||
in_obj.integer.value = offset;
|
||||
status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms,
|
||||
&buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dprintk("Radio device enumeration failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (result & 0x1)
|
||||
sony_nc_setup_rfkill(device, SONY_WIFI);
|
||||
if (result & 0x2)
|
||||
sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
|
||||
if (result & 0x1c)
|
||||
sony_nc_setup_rfkill(device, SONY_WWAN);
|
||||
if (result & 0x20)
|
||||
sony_nc_setup_rfkill(device, SONY_WIMAX);
|
||||
device_enum = (union acpi_object *) buffer.pointer;
|
||||
if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) {
|
||||
printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n",
|
||||
device_enum->type);
|
||||
goto out_no_enum;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* the buffer is filled with magic numbers describing the devices
|
||||
* available, 0xff terminates the enumeration
|
||||
*/
|
||||
while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff &&
|
||||
i < device_enum->buffer.length) {
|
||||
i++;
|
||||
dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
|
||||
|
||||
if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
|
||||
sony_nc_setup_rfkill(device, SONY_WIFI);
|
||||
|
||||
if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
|
||||
sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
|
||||
|
||||
if ((0xf0 & dev_code) == 0x20 &&
|
||||
!sony_rfkill_devices[SONY_WWAN])
|
||||
sony_nc_setup_rfkill(device, SONY_WWAN);
|
||||
|
||||
if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
|
||||
sony_nc_setup_rfkill(device, SONY_WIMAX);
|
||||
}
|
||||
|
||||
out_no_enum:
|
||||
kfree(buffer.pointer);
|
||||
return;
|
||||
}
|
||||
|
||||
static int sony_nc_add(struct acpi_device *device)
|
||||
|
|
|
@ -47,22 +47,6 @@ MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras");
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("wmi:C364AC71-36DB-495A-8494-B439D472A505");
|
||||
|
||||
static int tc1100_probe(struct platform_device *device);
|
||||
static int tc1100_remove(struct platform_device *device);
|
||||
static int tc1100_suspend(struct platform_device *device, pm_message_t state);
|
||||
static int tc1100_resume(struct platform_device *device);
|
||||
|
||||
static struct platform_driver tc1100_driver = {
|
||||
.driver = {
|
||||
.name = "tc1100-wmi",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tc1100_probe,
|
||||
.remove = tc1100_remove,
|
||||
.suspend = tc1100_suspend,
|
||||
.resume = tc1100_resume,
|
||||
};
|
||||
|
||||
static struct platform_device *tc1100_device;
|
||||
|
||||
struct tc1100_data {
|
||||
|
@ -183,51 +167,35 @@ static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
|
|||
show_set_bool(wireless, TC1100_INSTANCE_WIRELESS);
|
||||
show_set_bool(jogdial, TC1100_INSTANCE_JOGDIAL);
|
||||
|
||||
static void remove_fs(void)
|
||||
{
|
||||
device_remove_file(&tc1100_device->dev, &dev_attr_wireless);
|
||||
device_remove_file(&tc1100_device->dev, &dev_attr_jogdial);
|
||||
}
|
||||
static struct attribute *tc1100_attributes[] = {
|
||||
&dev_attr_wireless.attr,
|
||||
&dev_attr_jogdial.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int add_fs(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = device_create_file(&tc1100_device->dev, &dev_attr_wireless);
|
||||
if (ret)
|
||||
goto add_sysfs_error;
|
||||
|
||||
ret = device_create_file(&tc1100_device->dev, &dev_attr_jogdial);
|
||||
if (ret)
|
||||
goto add_sysfs_error;
|
||||
|
||||
return ret;
|
||||
|
||||
add_sysfs_error:
|
||||
remove_fs();
|
||||
return ret;
|
||||
}
|
||||
static struct attribute_group tc1100_attribute_group = {
|
||||
.attrs = tc1100_attributes,
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Model
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static int tc1100_probe(struct platform_device *device)
|
||||
static int __init tc1100_probe(struct platform_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result = add_fs();
|
||||
return result;
|
||||
return sysfs_create_group(&device->dev.kobj, &tc1100_attribute_group);
|
||||
}
|
||||
|
||||
|
||||
static int tc1100_remove(struct platform_device *device)
|
||||
static int __devexit tc1100_remove(struct platform_device *device)
|
||||
{
|
||||
remove_fs();
|
||||
sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc1100_suspend(struct platform_device *dev, pm_message_t state)
|
||||
#ifdef CONFIG_PM
|
||||
static int tc1100_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -239,10 +207,10 @@ static int tc1100_suspend(struct platform_device *dev, pm_message_t state)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc1100_resume(struct platform_device *dev)
|
||||
static int tc1100_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -254,34 +222,61 @@ static int tc1100_resume(struct platform_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tc1100_pm_ops = {
|
||||
.suspend = tc1100_suspend,
|
||||
.resume = tc1100_resume,
|
||||
.freeze = tc1100_suspend,
|
||||
.restore = tc1100_resume,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver tc1100_driver = {
|
||||
.driver = {
|
||||
.name = "tc1100-wmi",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &tc1100_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.remove = __devexit_p(tc1100_remove),
|
||||
};
|
||||
|
||||
static int __init tc1100_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
int error;
|
||||
|
||||
if (!wmi_has_guid(GUID))
|
||||
return -ENODEV;
|
||||
|
||||
result = platform_driver_register(&tc1100_driver);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
tc1100_device = platform_device_alloc("tc1100-wmi", -1);
|
||||
platform_device_add(tc1100_device);
|
||||
if (!tc1100_device)
|
||||
return -ENOMEM;
|
||||
|
||||
error = platform_device_add(tc1100_device);
|
||||
if (error)
|
||||
goto err_device_put;
|
||||
|
||||
error = platform_driver_probe(&tc1100_driver, tc1100_probe);
|
||||
if (error)
|
||||
goto err_device_del;
|
||||
|
||||
printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras loaded\n");
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
err_device_del:
|
||||
platform_device_del(tc1100_device);
|
||||
err_device_put:
|
||||
platform_device_put(tc1100_device);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void __exit tc1100_exit(void)
|
||||
{
|
||||
platform_device_del(tc1100_device);
|
||||
platform_device_unregister(tc1100_device);
|
||||
platform_driver_unregister(&tc1100_driver);
|
||||
|
||||
printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras unloaded\n");
|
||||
}
|
||||
|
||||
module_init(tc1100_init);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rfkill.h>
|
||||
|
@ -357,63 +358,6 @@ static int force_fan;
|
|||
static int last_key_event;
|
||||
static int key_event_valid;
|
||||
|
||||
typedef struct _ProcItem {
|
||||
const char *name;
|
||||
char *(*read_func) (char *);
|
||||
unsigned long (*write_func) (const char *, unsigned long);
|
||||
} ProcItem;
|
||||
|
||||
/* proc file handlers
|
||||
*/
|
||||
|
||||
static int
|
||||
dispatch_read(char *page, char **start, off_t off, int count, int *eof,
|
||||
ProcItem * item)
|
||||
{
|
||||
char *p = page;
|
||||
int len;
|
||||
|
||||
if (off == 0)
|
||||
p = item->read_func(p);
|
||||
|
||||
/* ISSUE: I don't understand this code */
|
||||
len = (p - page);
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
dispatch_write(struct file *file, const char __user * buffer,
|
||||
unsigned long count, ProcItem * item)
|
||||
{
|
||||
int result;
|
||||
char *tmp_buffer;
|
||||
|
||||
/* Arg buffer points to userspace memory, which can't be accessed
|
||||
* directly. Since we're making a copy, zero-terminate the
|
||||
* destination so that sscanf can be used on it safely.
|
||||
*/
|
||||
tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!tmp_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(tmp_buffer, buffer, count)) {
|
||||
result = -EFAULT;
|
||||
} else {
|
||||
tmp_buffer[count] = 0;
|
||||
result = item->write_func(tmp_buffer, count);
|
||||
}
|
||||
kfree(tmp_buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int get_lcd(struct backlight_device *bd)
|
||||
{
|
||||
u32 hci_result;
|
||||
|
@ -426,19 +370,24 @@ static int get_lcd(struct backlight_device *bd)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
static char *read_lcd(char *p)
|
||||
static int lcd_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int value = get_lcd(NULL);
|
||||
|
||||
if (value >= 0) {
|
||||
p += sprintf(p, "brightness: %d\n", value);
|
||||
p += sprintf(p, "brightness_levels: %d\n",
|
||||
seq_printf(m, "brightness: %d\n", value);
|
||||
seq_printf(m, "brightness_levels: %d\n",
|
||||
HCI_LCD_BRIGHTNESS_LEVELS);
|
||||
} else {
|
||||
printk(MY_ERR "Error reading LCD brightness\n");
|
||||
}
|
||||
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, lcd_proc_show, NULL);
|
||||
}
|
||||
|
||||
static int set_lcd(int value)
|
||||
|
@ -458,12 +407,20 @@ static int set_lcd_status(struct backlight_device *bd)
|
|||
return set_lcd(bd->props.brightness);
|
||||
}
|
||||
|
||||
static unsigned long write_lcd(const char *buffer, unsigned long count)
|
||||
static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
char cmd[42];
|
||||
size_t len;
|
||||
int value;
|
||||
int ret;
|
||||
|
||||
if (sscanf(buffer, " brightness : %i", &value) == 1 &&
|
||||
len = min(count, sizeof(cmd) - 1);
|
||||
if (copy_from_user(cmd, buf, len))
|
||||
return -EFAULT;
|
||||
cmd[len] = '\0';
|
||||
|
||||
if (sscanf(cmd, " brightness : %i", &value) == 1 &&
|
||||
value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
|
||||
ret = set_lcd(value);
|
||||
if (ret == 0)
|
||||
|
@ -474,7 +431,16 @@ static unsigned long write_lcd(const char *buffer, unsigned long count)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static char *read_video(char *p)
|
||||
static const struct file_operations lcd_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = lcd_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = lcd_proc_write,
|
||||
};
|
||||
|
||||
static int video_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
u32 hci_result;
|
||||
u32 value;
|
||||
|
@ -484,18 +450,25 @@ static char *read_video(char *p)
|
|||
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
|
||||
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
|
||||
int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
|
||||
p += sprintf(p, "lcd_out: %d\n", is_lcd);
|
||||
p += sprintf(p, "crt_out: %d\n", is_crt);
|
||||
p += sprintf(p, "tv_out: %d\n", is_tv);
|
||||
seq_printf(m, "lcd_out: %d\n", is_lcd);
|
||||
seq_printf(m, "crt_out: %d\n", is_crt);
|
||||
seq_printf(m, "tv_out: %d\n", is_tv);
|
||||
} else {
|
||||
printk(MY_ERR "Error reading video out status\n");
|
||||
}
|
||||
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long write_video(const char *buffer, unsigned long count)
|
||||
static int video_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, video_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t video_proc_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
char *cmd, *buffer;
|
||||
int value;
|
||||
int remain = count;
|
||||
int lcd_out = -1;
|
||||
|
@ -504,6 +477,17 @@ static unsigned long write_video(const char *buffer, unsigned long count)
|
|||
u32 hci_result;
|
||||
u32 video_out;
|
||||
|
||||
cmd = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(cmd, buf, count)) {
|
||||
kfree(cmd);
|
||||
return -EFAULT;
|
||||
}
|
||||
cmd[count] = '\0';
|
||||
|
||||
buffer = cmd;
|
||||
|
||||
/* scan expression. Multiple expressions may be delimited with ;
|
||||
*
|
||||
* NOTE: to keep scanning simple, invalid fields are ignored
|
||||
|
@ -523,6 +507,8 @@ static unsigned long write_video(const char *buffer, unsigned long count)
|
|||
while (remain && *(buffer - 1) != ';');
|
||||
}
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
|
||||
if (hci_result == HCI_SUCCESS) {
|
||||
unsigned int new_video_out = video_out;
|
||||
|
@ -543,28 +529,50 @@ static unsigned long write_video(const char *buffer, unsigned long count)
|
|||
return count;
|
||||
}
|
||||
|
||||
static char *read_fan(char *p)
|
||||
static const struct file_operations video_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = video_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = video_proc_write,
|
||||
};
|
||||
|
||||
static int fan_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
u32 hci_result;
|
||||
u32 value;
|
||||
|
||||
hci_read1(HCI_FAN, &value, &hci_result);
|
||||
if (hci_result == HCI_SUCCESS) {
|
||||
p += sprintf(p, "running: %d\n", (value > 0));
|
||||
p += sprintf(p, "force_on: %d\n", force_fan);
|
||||
seq_printf(m, "running: %d\n", (value > 0));
|
||||
seq_printf(m, "force_on: %d\n", force_fan);
|
||||
} else {
|
||||
printk(MY_ERR "Error reading fan status\n");
|
||||
}
|
||||
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long write_fan(const char *buffer, unsigned long count)
|
||||
static int fan_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, fan_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t fan_proc_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
char cmd[42];
|
||||
size_t len;
|
||||
int value;
|
||||
u32 hci_result;
|
||||
|
||||
if (sscanf(buffer, " force_on : %i", &value) == 1 &&
|
||||
len = min(count, sizeof(cmd) - 1);
|
||||
if (copy_from_user(cmd, buf, len))
|
||||
return -EFAULT;
|
||||
cmd[len] = '\0';
|
||||
|
||||
if (sscanf(cmd, " force_on : %i", &value) == 1 &&
|
||||
value >= 0 && value <= 1) {
|
||||
hci_write1(HCI_FAN, value, &hci_result);
|
||||
if (hci_result != HCI_SUCCESS)
|
||||
|
@ -578,7 +586,16 @@ static unsigned long write_fan(const char *buffer, unsigned long count)
|
|||
return count;
|
||||
}
|
||||
|
||||
static char *read_keys(char *p)
|
||||
static const struct file_operations fan_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = fan_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = fan_proc_write,
|
||||
};
|
||||
|
||||
static int keys_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
u32 hci_result;
|
||||
u32 value;
|
||||
|
@ -602,18 +619,30 @@ static char *read_keys(char *p)
|
|||
}
|
||||
}
|
||||
|
||||
p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
|
||||
p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
|
||||
|
||||
end:
|
||||
return p;
|
||||
seq_printf(m, "hotkey_ready: %d\n", key_event_valid);
|
||||
seq_printf(m, "hotkey: 0x%04x\n", last_key_event);
|
||||
end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long write_keys(const char *buffer, unsigned long count)
|
||||
static int keys_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, keys_proc_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t keys_proc_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
char cmd[42];
|
||||
size_t len;
|
||||
int value;
|
||||
|
||||
if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) {
|
||||
len = min(count, sizeof(cmd) - 1);
|
||||
if (copy_from_user(cmd, buf, len))
|
||||
return -EFAULT;
|
||||
cmd[len] = '\0';
|
||||
|
||||
if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
|
||||
key_event_valid = 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
|
@ -622,52 +651,58 @@ static unsigned long write_keys(const char *buffer, unsigned long count)
|
|||
return count;
|
||||
}
|
||||
|
||||
static char *read_version(char *p)
|
||||
static const struct file_operations keys_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = keys_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = keys_proc_write,
|
||||
};
|
||||
|
||||
static int version_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
|
||||
p += sprintf(p, "proc_interface: %d\n",
|
||||
PROC_INTERFACE_VERSION);
|
||||
return p;
|
||||
seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION);
|
||||
seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, version_proc_show, PDE(inode)->data);
|
||||
}
|
||||
|
||||
static const struct file_operations version_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = version_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
/* proc and module init
|
||||
*/
|
||||
|
||||
#define PROC_TOSHIBA "toshiba"
|
||||
|
||||
static ProcItem proc_items[] = {
|
||||
{"lcd", read_lcd, write_lcd},
|
||||
{"video", read_video, write_video},
|
||||
{"fan", read_fan, write_fan},
|
||||
{"keys", read_keys, write_keys},
|
||||
{"version", read_version, NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static acpi_status __init add_device(void)
|
||||
{
|
||||
struct proc_dir_entry *proc;
|
||||
ProcItem *item;
|
||||
|
||||
for (item = proc_items; item->name; ++item) {
|
||||
proc = create_proc_read_entry(item->name,
|
||||
S_IFREG | S_IRUGO | S_IWUSR,
|
||||
toshiba_proc_dir,
|
||||
(read_proc_t *) dispatch_read,
|
||||
item);
|
||||
if (proc && item->write_func)
|
||||
proc->write_proc = (write_proc_t *) dispatch_write;
|
||||
}
|
||||
proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
|
||||
proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
|
||||
proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
|
||||
proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
|
||||
proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status remove_device(void)
|
||||
{
|
||||
ProcItem *item;
|
||||
|
||||
for (item = proc_items; item->name; ++item)
|
||||
remove_proc_entry(item->name, toshiba_proc_dir);
|
||||
remove_proc_entry("lcd", toshiba_proc_dir);
|
||||
remove_proc_entry("video", toshiba_proc_dir);
|
||||
remove_proc_entry("fan", toshiba_proc_dir);
|
||||
remove_proc_entry("keys", toshiba_proc_dir);
|
||||
remove_proc_entry("version", toshiba_proc_dir);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -540,8 +540,8 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
|
|||
/**
|
||||
* wmi_get_event_data - Get WMI data associated with an event
|
||||
*
|
||||
* @event - Event to find
|
||||
* &out - Buffer to hold event data
|
||||
* @event: Event to find
|
||||
* @out: Buffer to hold event data. out->pointer should be freed with kfree()
|
||||
*
|
||||
* Returns extra data associated with an event in WMI.
|
||||
*/
|
||||
|
|
|
@ -224,8 +224,6 @@ struct acpi_processor {
|
|||
struct acpi_processor_throttling throttling;
|
||||
struct acpi_processor_limit limit;
|
||||
struct thermal_cooling_device *cdev;
|
||||
/* the _PDC objects for this processor, if any */
|
||||
struct acpi_object_list *pdc;
|
||||
};
|
||||
|
||||
struct acpi_processor_errata {
|
||||
|
@ -257,9 +255,6 @@ int acpi_processor_notify_smm(struct module *calling_module);
|
|||
DECLARE_PER_CPU(struct acpi_processor *, processors);
|
||||
extern struct acpi_processor_errata errata;
|
||||
|
||||
void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
|
||||
void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr);
|
||||
|
||||
#ifdef ARCH_HAS_POWER_INIT
|
||||
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
|
||||
unsigned int cpu);
|
||||
|
@ -325,6 +320,9 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
|
|||
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
/* in processor_pdc.c */
|
||||
void acpi_processor_set_pdc(acpi_handle handle);
|
||||
|
||||
/* in processor_throttling.c */
|
||||
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
|
||||
int acpi_processor_get_throttling_info(struct acpi_processor *pr);
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
#define SONYPI_EVENT_VOLUME_INC_PRESSED 69
|
||||
#define SONYPI_EVENT_VOLUME_DEC_PRESSED 70
|
||||
#define SONYPI_EVENT_BRIGHTNESS_PRESSED 71
|
||||
#define SONYPI_EVENT_MEDIA_PRESSED 72
|
||||
|
||||
/* get/set brightness */
|
||||
#define SONYPI_IOCGBRT _IOR('v', 0, __u8)
|
||||
|
|
Loading…
Reference in a new issue