mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-12-01 08:00:42 +00:00
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: (28 commits) ACPI: check battery status on resume for un/plug events during sleep ACPICA: Fix incorrect handling of PCI Express Root Bridge _HID ACPI: asus_acpi: don't printk on writing garbage to proc files ACPI: asus_acpi: fix proc files parsing ACPI: SCI interrupt source override ACPI: fix printk format warnings ACPI: fix section for CPU init functions ACPI: update comments in motherboard.c ACPI: acpi_pci_link_set() can allocate with either GFP_ATOMIC or GFP_KERNEL ACPI: fix potential OOPS in power driver with CONFIG_ACPI_DEBUG ACPI: ibm_acpi: delete obsolete documentation ACPI: created a dedicated workqueue for notify() execution ACPI: Remove deferred execution from global lock acquire wakeup path MSI S270 Laptop support: backlight, wlan, bluetooth states ACPI: EC: export ec_transaction() for msi-laptop driver ACPI: EC: Simplify acpi_hw_low_level*() with inb()/outb(). ACPI: EC: Unify poll and interrupt gpe handlers ACPI: EC: Unify poll and interrupt mode transaction functions ACPI: EC: Remove unused variables and duplicated code ACPI: EC: Remove unnecessary delay added by previous transation patch. ...
This commit is contained in:
commit
0b269d8462
@ -30,9 +30,10 @@ detailed description):
|
|||||||
- ACPI sounds
|
- ACPI sounds
|
||||||
- temperature sensors
|
- temperature sensors
|
||||||
- Experimental: embedded controller register dump
|
- Experimental: embedded controller register dump
|
||||||
- Experimental: LCD brightness control
|
- LCD brightness control
|
||||||
- Experimental: volume control
|
- Volume control
|
||||||
- Experimental: fan speed, fan enable/disable
|
- Experimental: fan speed, fan enable/disable
|
||||||
|
- Experimental: WAN enable and disable
|
||||||
|
|
||||||
A compatibility table by model and feature is maintained on the web
|
A compatibility table by model and feature is maintained on the web
|
||||||
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
||||||
@ -52,40 +53,7 @@ Installation
|
|||||||
|
|
||||||
If you are compiling this driver as included in the Linux kernel
|
If you are compiling this driver as included in the Linux kernel
|
||||||
sources, simply enable the CONFIG_ACPI_IBM option (Power Management /
|
sources, simply enable the CONFIG_ACPI_IBM option (Power Management /
|
||||||
ACPI / IBM ThinkPad Laptop Extras). The rest of this section describes
|
ACPI / IBM ThinkPad Laptop Extras).
|
||||||
how to install this driver when downloaded from the web site.
|
|
||||||
|
|
||||||
First, you need to get a kernel with ACPI support up and running.
|
|
||||||
Please refer to http://acpi.sourceforge.net/ for help with this
|
|
||||||
step. How successful you will be depends a lot on you ThinkPad model,
|
|
||||||
the kernel you are using and any additional patches applied. The
|
|
||||||
kernel provided with your distribution may not be good enough. I
|
|
||||||
needed to compile a 2.6.7 kernel with the 20040715 ACPI patch to get
|
|
||||||
ACPI working reliably on my ThinkPad X40. Old ThinkPad models may not
|
|
||||||
be supported at all.
|
|
||||||
|
|
||||||
Assuming you have the basic ACPI support working (e.g. you can see the
|
|
||||||
/proc/acpi directory), follow the following steps to install this
|
|
||||||
driver:
|
|
||||||
|
|
||||||
- unpack the archive:
|
|
||||||
|
|
||||||
tar xzvf ibm-acpi-x.y.tar.gz; cd ibm-acpi-x.y
|
|
||||||
|
|
||||||
- compile the driver:
|
|
||||||
|
|
||||||
make
|
|
||||||
|
|
||||||
- install the module in your kernel modules directory:
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
- load the module:
|
|
||||||
|
|
||||||
modprobe ibm_acpi
|
|
||||||
|
|
||||||
After loading the module, check the "dmesg" output for any error messages.
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
@ -523,13 +491,8 @@ registers contain the current battery capacity, etc. If you experiment
|
|||||||
with this, do send me your results (including some complete dumps with
|
with this, do send me your results (including some complete dumps with
|
||||||
a description of the conditions when they were taken.)
|
a description of the conditions when they were taken.)
|
||||||
|
|
||||||
EXPERIMENTAL: LCD brightness control -- /proc/acpi/ibm/brightness
|
LCD brightness control -- /proc/acpi/ibm/brightness
|
||||||
-----------------------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
This feature is marked EXPERIMENTAL because the implementation
|
|
||||||
directly accesses hardware registers and may not work as expected. USE
|
|
||||||
WITH CAUTION! To use this feature, you need to supply the
|
|
||||||
experimental=1 parameter when loading the module.
|
|
||||||
|
|
||||||
This feature allows software control of the LCD brightness on ThinkPad
|
This feature allows software control of the LCD brightness on ThinkPad
|
||||||
models which don't have a hardware brightness slider. The available
|
models which don't have a hardware brightness slider. The available
|
||||||
@ -542,13 +505,8 @@ commands are:
|
|||||||
The <level> number range is 0 to 7, although not all of them may be
|
The <level> number range is 0 to 7, although not all of them may be
|
||||||
distinct. The current brightness level is shown in the file.
|
distinct. The current brightness level is shown in the file.
|
||||||
|
|
||||||
EXPERIMENTAL: Volume control -- /proc/acpi/ibm/volume
|
Volume control -- /proc/acpi/ibm/volume
|
||||||
-----------------------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
This feature is marked EXPERIMENTAL because the implementation
|
|
||||||
directly accesses hardware registers and may not work as expected. USE
|
|
||||||
WITH CAUTION! To use this feature, you need to supply the
|
|
||||||
experimental=1 parameter when loading the module.
|
|
||||||
|
|
||||||
This feature allows volume control on ThinkPad models which don't have
|
This feature allows volume control on ThinkPad models which don't have
|
||||||
a hardware volume knob. The available commands are:
|
a hardware volume knob. The available commands are:
|
||||||
@ -611,6 +569,23 @@ with the following command:
|
|||||||
|
|
||||||
echo 'level <level>' > /proc/acpi/ibm/thermal
|
echo 'level <level>' > /proc/acpi/ibm/thermal
|
||||||
|
|
||||||
|
EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
This feature is marked EXPERIMENTAL because the implementation
|
||||||
|
directly accesses hardware registers and may not work as expected. USE
|
||||||
|
WITH CAUTION! To use this feature, you need to supply the
|
||||||
|
experimental=1 parameter when loading the module.
|
||||||
|
|
||||||
|
This feature shows the presence and current state of a WAN (Sierra
|
||||||
|
Wireless EV-DO) device. If WAN is installed, the following commands can
|
||||||
|
be used:
|
||||||
|
|
||||||
|
echo enable > /proc/acpi/ibm/wan
|
||||||
|
echo disable > /proc/acpi/ibm/wan
|
||||||
|
|
||||||
|
It was tested on a Lenovo Thinkpad X60. It should probably work on other
|
||||||
|
Thinkpad models which come with this module installed.
|
||||||
|
|
||||||
Multiple Commands, Module Parameters
|
Multiple Commands, Module Parameters
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -1998,6 +1998,13 @@ M: rubini@ipvvis.unipv.it
|
|||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
MSI LAPTOP SUPPORT
|
||||||
|
P: Lennart Poettering
|
||||||
|
M: mzxreary@0pointer.de
|
||||||
|
L: https://tango.0pointer.de/mailman/listinfo/s270-linux
|
||||||
|
W: http://0pointer.de/lennart/tchibo.html
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
MTRR AND SIMILAR SUPPORT [i386]
|
MTRR AND SIMILAR SUPPORT [i386]
|
||||||
P: Richard Gooch
|
P: Richard Gooch
|
||||||
M: rgooch@atnf.csiro.au
|
M: rgooch@atnf.csiro.au
|
||||||
|
@ -332,7 +332,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
|
|||||||
/*
|
/*
|
||||||
* Parse Interrupt Source Override for the ACPI SCI
|
* Parse Interrupt Source Override for the ACPI SCI
|
||||||
*/
|
*/
|
||||||
static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger)
|
||||||
{
|
{
|
||||||
if (trigger == 0) /* compatible SCI trigger is level */
|
if (trigger == 0) /* compatible SCI trigger is level */
|
||||||
trigger = 3;
|
trigger = 3;
|
||||||
@ -352,13 +352,13 @@ static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
|
|||||||
* If GSI is < 16, this will update its flags,
|
* If GSI is < 16, this will update its flags,
|
||||||
* else it will create a new mp_irqs[] entry.
|
* else it will create a new mp_irqs[] entry.
|
||||||
*/
|
*/
|
||||||
mp_override_legacy_irq(gsi, polarity, trigger, gsi);
|
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stash over-ride to indicate we've been here
|
* stash over-ride to indicate we've been here
|
||||||
* and for later update of acpi_fadt
|
* and for later update of acpi_fadt
|
||||||
*/
|
*/
|
||||||
acpi_sci_override_gsi = gsi;
|
acpi_sci_override_gsi = bus_irq;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ acpi_parse_int_src_ovr(acpi_table_entry_header * header,
|
|||||||
acpi_table_print_madt_entry(header);
|
acpi_table_print_madt_entry(header);
|
||||||
|
|
||||||
if (intsrc->bus_irq == acpi_fadt.sci_int) {
|
if (intsrc->bus_irq == acpi_fadt.sci_int) {
|
||||||
acpi_sci_ioapic_setup(intsrc->global_irq,
|
acpi_sci_ioapic_setup(intsrc->bus_irq, intsrc->global_irq,
|
||||||
intsrc->flags.polarity,
|
intsrc->flags.polarity,
|
||||||
intsrc->flags.trigger);
|
intsrc->flags.trigger);
|
||||||
return 0;
|
return 0;
|
||||||
@ -879,7 +879,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
|||||||
* pretend we got one so we can set the SCI flags.
|
* pretend we got one so we can set the SCI flags.
|
||||||
*/
|
*/
|
||||||
if (!acpi_sci_override_gsi)
|
if (!acpi_sci_override_gsi)
|
||||||
acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
|
acpi_sci_ioapic_setup(acpi_fadt.sci_int, acpi_fadt.sci_int, 0, 0);
|
||||||
|
|
||||||
/* Fill in identity legacy mapings where no override */
|
/* Fill in identity legacy mapings where no override */
|
||||||
mp_config_acpi_legacy_irqs();
|
mp_config_acpi_legacy_irqs();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
|
||||||
#include <acpi/processor.h>
|
#include <acpi/processor.h>
|
||||||
#include <asm/acpi.h>
|
#include <asm/acpi.h>
|
||||||
@ -41,5 +42,124 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
|
|||||||
flags->bm_check = 1;
|
flags->bm_check = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
|
EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
|
||||||
|
|
||||||
|
/* The code below handles cstate entry with monitor-mwait pair on Intel*/
|
||||||
|
|
||||||
|
struct cstate_entry_s {
|
||||||
|
struct {
|
||||||
|
unsigned int eax;
|
||||||
|
unsigned int ecx;
|
||||||
|
} states[ACPI_PROCESSOR_MAX_POWER];
|
||||||
|
};
|
||||||
|
static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */
|
||||||
|
|
||||||
|
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
|
||||||
|
|
||||||
|
#define MWAIT_SUBSTATE_MASK (0xf)
|
||||||
|
#define MWAIT_SUBSTATE_SIZE (4)
|
||||||
|
|
||||||
|
#define CPUID_MWAIT_LEAF (5)
|
||||||
|
#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
|
||||||
|
#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
|
||||||
|
|
||||||
|
#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
|
||||||
|
|
||||||
|
#define NATIVE_CSTATE_BEYOND_HALT (2)
|
||||||
|
|
||||||
|
int acpi_processor_ffh_cstate_probe(unsigned int cpu,
|
||||||
|
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
|
||||||
|
{
|
||||||
|
struct cstate_entry_s *percpu_entry;
|
||||||
|
struct cpuinfo_x86 *c = cpu_data + cpu;
|
||||||
|
|
||||||
|
cpumask_t saved_mask;
|
||||||
|
int retval;
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
unsigned int edx_part;
|
||||||
|
unsigned int cstate_type; /* C-state type and not ACPI C-state type */
|
||||||
|
unsigned int num_cstate_subtype;
|
||||||
|
|
||||||
|
if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
|
||||||
|
percpu_entry->states[cx->index].eax = 0;
|
||||||
|
percpu_entry->states[cx->index].ecx = 0;
|
||||||
|
|
||||||
|
/* Make sure we are running on right CPU */
|
||||||
|
saved_mask = current->cpus_allowed;
|
||||||
|
retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
|
||||||
|
if (retval)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
/* Check whether this particular cx_type (in CST) is supported or not */
|
||||||
|
cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1;
|
||||||
|
edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
|
||||||
|
num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
|
||||||
|
retval = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
|
||||||
|
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
|
||||||
|
!(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
|
||||||
|
retval = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
|
||||||
|
|
||||||
|
/* Use the hint in CST */
|
||||||
|
percpu_entry->states[cx->index].eax = cx->address;
|
||||||
|
|
||||||
|
if (!mwait_supported[cstate_type]) {
|
||||||
|
mwait_supported[cstate_type] = 1;
|
||||||
|
printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
|
||||||
|
"state\n", cx->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
set_cpus_allowed(current, saved_mask);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
|
||||||
|
|
||||||
|
void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
|
||||||
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
struct cstate_entry_s *percpu_entry;
|
||||||
|
|
||||||
|
percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
|
||||||
|
mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
|
||||||
|
percpu_entry->states[cx->index].ecx);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);
|
||||||
|
|
||||||
|
static int __init ffh_cstate_init(void)
|
||||||
|
{
|
||||||
|
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||||
|
if (c->x86_vendor != X86_VENDOR_INTEL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit ffh_cstate_exit(void)
|
||||||
|
{
|
||||||
|
if (cpu_cstate_entry) {
|
||||||
|
free_percpu(cpu_cstate_entry);
|
||||||
|
cpu_cstate_entry = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_initcall(ffh_cstate_init);
|
||||||
|
__exitcall(ffh_cstate_exit);
|
||||||
|
@ -236,18 +236,26 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
|
|||||||
* We execute MONITOR against need_resched and enter optimized wait state
|
* We execute MONITOR against need_resched and enter optimized wait state
|
||||||
* through MWAIT. Whenever someone changes need_resched, we would be woken
|
* through MWAIT. Whenever someone changes need_resched, we would be woken
|
||||||
* up from MWAIT (without an IPI).
|
* up from MWAIT (without an IPI).
|
||||||
|
*
|
||||||
|
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
||||||
|
* capability.
|
||||||
*/
|
*/
|
||||||
|
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
||||||
|
{
|
||||||
|
if (!need_resched()) {
|
||||||
|
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
||||||
|
smp_mb();
|
||||||
|
if (!need_resched())
|
||||||
|
__mwait(eax, ecx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
|
||||||
static void mwait_idle(void)
|
static void mwait_idle(void)
|
||||||
{
|
{
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
while (!need_resched())
|
||||||
while (!need_resched()) {
|
mwait_idle_with_hints(0, 0);
|
||||||
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
|
||||||
smp_mb();
|
|
||||||
if (need_resched())
|
|
||||||
break;
|
|
||||||
__mwait(0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
|
void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
|
||||||
|
@ -238,18 +238,26 @@ void cpu_idle (void)
|
|||||||
* We execute MONITOR against need_resched and enter optimized wait state
|
* We execute MONITOR against need_resched and enter optimized wait state
|
||||||
* through MWAIT. Whenever someone changes need_resched, we would be woken
|
* through MWAIT. Whenever someone changes need_resched, we would be woken
|
||||||
* up from MWAIT (without an IPI).
|
* up from MWAIT (without an IPI).
|
||||||
|
*
|
||||||
|
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
||||||
|
* capability.
|
||||||
*/
|
*/
|
||||||
|
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
||||||
|
{
|
||||||
|
if (!need_resched()) {
|
||||||
|
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
||||||
|
smp_mb();
|
||||||
|
if (!need_resched())
|
||||||
|
__mwait(eax, ecx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default MONITOR/MWAIT with no hints, used for default C1 state */
|
||||||
static void mwait_idle(void)
|
static void mwait_idle(void)
|
||||||
{
|
{
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
while (!need_resched())
|
||||||
while (!need_resched()) {
|
mwait_idle_with_hints(0,0);
|
||||||
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
|
||||||
smp_mb();
|
|
||||||
if (need_resched())
|
|
||||||
break;
|
|
||||||
__mwait(0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
|
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
|
||||||
|
@ -138,6 +138,7 @@ struct asus_hotk {
|
|||||||
S2x, //S200 (J1 reported), Victor MP-XP7210
|
S2x, //S200 (J1 reported), Victor MP-XP7210
|
||||||
W1N, //W1000N
|
W1N, //W1000N
|
||||||
W5A, //W5A
|
W5A, //W5A
|
||||||
|
W3V, //W3030V
|
||||||
xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
|
xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
|
||||||
//(Centrino)
|
//(Centrino)
|
||||||
END_MODEL
|
END_MODEL
|
||||||
@ -376,6 +377,17 @@ static struct model_data model_conf[END_MODEL] = {
|
|||||||
.display_get = "\\ADVG"},
|
.display_get = "\\ADVG"},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
.name = "W3V",
|
||||||
|
.mt_mled = "MLED",
|
||||||
|
.mt_wled = "WLED",
|
||||||
|
.mt_lcd_switch = xxN_PREFIX "_Q10",
|
||||||
|
.lcd_status = "\\BKLT",
|
||||||
|
.brightness_set = "SPLV",
|
||||||
|
.brightness_get = "GPLV",
|
||||||
|
.display_set = "SDSP",
|
||||||
|
.display_get = "\\INFB"},
|
||||||
|
|
||||||
|
{
|
||||||
.name = "xxN",
|
.name = "xxN",
|
||||||
.mt_mled = "MLED",
|
.mt_mled = "MLED",
|
||||||
/* WLED present, but not controlled by ACPI */
|
/* WLED present, but not controlled by ACPI */
|
||||||
@ -555,11 +567,11 @@ static int
|
|||||||
write_led(const char __user * buffer, unsigned long count,
|
write_led(const char __user * buffer, unsigned long count,
|
||||||
char *ledname, int ledmask, int invert)
|
char *ledname, int ledmask, int invert)
|
||||||
{
|
{
|
||||||
int value;
|
int rv, value;
|
||||||
int led_out = 0;
|
int led_out = 0;
|
||||||
|
|
||||||
count = parse_arg(buffer, count, &value);
|
rv = parse_arg(buffer, count, &value);
|
||||||
if (count > 0)
|
if (rv > 0)
|
||||||
led_out = value ? 1 : 0;
|
led_out = value ? 1 : 0;
|
||||||
|
|
||||||
hotk->status =
|
hotk->status =
|
||||||
@ -572,7 +584,7 @@ write_led(const char __user * buffer, unsigned long count,
|
|||||||
printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
|
printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
|
||||||
ledname);
|
ledname);
|
||||||
|
|
||||||
return count;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -607,20 +619,18 @@ static int
|
|||||||
proc_write_ledd(struct file *file, const char __user * buffer,
|
proc_write_ledd(struct file *file, const char __user * buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
int value;
|
int rv, value;
|
||||||
|
|
||||||
count = parse_arg(buffer, count, &value);
|
rv = parse_arg(buffer, count, &value);
|
||||||
if (count > 0) {
|
if (rv > 0) {
|
||||||
if (!write_acpi_int
|
if (!write_acpi_int
|
||||||
(hotk->handle, hotk->methods->mt_ledd, value, NULL))
|
(hotk->handle, hotk->methods->mt_ledd, value, NULL))
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"Asus ACPI: LED display write failed\n");
|
"Asus ACPI: LED display write failed\n");
|
||||||
else
|
else
|
||||||
hotk->ledd_status = (u32) value;
|
hotk->ledd_status = (u32) value;
|
||||||
} else if (count < 0)
|
}
|
||||||
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
|
return rv;
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -761,12 +771,12 @@ static int
|
|||||||
proc_write_lcd(struct file *file, const char __user * buffer,
|
proc_write_lcd(struct file *file, const char __user * buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
int value;
|
int rv, value;
|
||||||
|
|
||||||
count = parse_arg(buffer, count, &value);
|
rv = parse_arg(buffer, count, &value);
|
||||||
if (count > 0)
|
if (rv > 0)
|
||||||
set_lcd_state(value);
|
set_lcd_state(value);
|
||||||
return count;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_brightness(void)
|
static int read_brightness(void)
|
||||||
@ -830,18 +840,15 @@ static int
|
|||||||
proc_write_brn(struct file *file, const char __user * buffer,
|
proc_write_brn(struct file *file, const char __user * buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
int value;
|
int rv, value;
|
||||||
|
|
||||||
count = parse_arg(buffer, count, &value);
|
rv = parse_arg(buffer, count, &value);
|
||||||
if (count > 0) {
|
if (rv > 0) {
|
||||||
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
|
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
|
||||||
/* 0 <= value <= 15 */
|
/* 0 <= value <= 15 */
|
||||||
set_brightness(value);
|
set_brightness(value);
|
||||||
} else if (count < 0) {
|
|
||||||
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
|
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_display(int value)
|
static void set_display(int value)
|
||||||
@ -880,15 +887,12 @@ static int
|
|||||||
proc_write_disp(struct file *file, const char __user * buffer,
|
proc_write_disp(struct file *file, const char __user * buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
int value;
|
int rv, value;
|
||||||
|
|
||||||
count = parse_arg(buffer, count, &value);
|
rv = parse_arg(buffer, count, &value);
|
||||||
if (count > 0)
|
if (rv > 0)
|
||||||
set_display(value);
|
set_display(value);
|
||||||
else if (count < 0)
|
return rv;
|
||||||
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
|
typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
|
||||||
@ -1097,6 +1101,8 @@ static int asus_model_match(char *model)
|
|||||||
return A4G;
|
return A4G;
|
||||||
else if (strncmp(model, "W1N", 3) == 0)
|
else if (strncmp(model, "W1N", 3) == 0)
|
||||||
return W1N;
|
return W1N;
|
||||||
|
else if (strncmp(model, "W3V", 3) == 0)
|
||||||
|
return W3V;
|
||||||
else if (strncmp(model, "W5A", 3) == 0)
|
else if (strncmp(model, "W5A", 3) == 0)
|
||||||
return W5A;
|
return W5A;
|
||||||
else
|
else
|
||||||
@ -1200,9 +1206,10 @@ static int asus_hotk_get_info(void)
|
|||||||
hotk->methods->mt_wled = NULL;
|
hotk->methods->mt_wled = NULL;
|
||||||
/* L5D's WLED is not controlled by ACPI */
|
/* L5D's WLED is not controlled by ACPI */
|
||||||
else if (strncmp(string, "M2N", 3) == 0 ||
|
else if (strncmp(string, "M2N", 3) == 0 ||
|
||||||
|
strncmp(string, "W3V", 3) == 0 ||
|
||||||
strncmp(string, "S1N", 3) == 0)
|
strncmp(string, "S1N", 3) == 0)
|
||||||
hotk->methods->mt_wled = "WLED";
|
hotk->methods->mt_wled = "WLED";
|
||||||
/* M2N and S1N have a usable WLED */
|
/* M2N, S1N and W3V have a usable WLED */
|
||||||
else if (asus_info) {
|
else if (asus_info) {
|
||||||
if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
|
if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
|
||||||
hotk->methods->mled_status = NULL;
|
hotk->methods->mled_status = NULL;
|
||||||
|
@ -64,6 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
|
|||||||
|
|
||||||
static int acpi_battery_add(struct acpi_device *device);
|
static int acpi_battery_add(struct acpi_device *device);
|
||||||
static int acpi_battery_remove(struct acpi_device *device, int type);
|
static int acpi_battery_remove(struct acpi_device *device, int type);
|
||||||
|
static int acpi_battery_resume(struct acpi_device *device, int status);
|
||||||
|
|
||||||
static struct acpi_driver acpi_battery_driver = {
|
static struct acpi_driver acpi_battery_driver = {
|
||||||
.name = ACPI_BATTERY_DRIVER_NAME,
|
.name = ACPI_BATTERY_DRIVER_NAME,
|
||||||
@ -71,6 +72,7 @@ static struct acpi_driver acpi_battery_driver = {
|
|||||||
.ids = ACPI_BATTERY_HID,
|
.ids = ACPI_BATTERY_HID,
|
||||||
.ops = {
|
.ops = {
|
||||||
.add = acpi_battery_add,
|
.add = acpi_battery_add,
|
||||||
|
.resume = acpi_battery_resume,
|
||||||
.remove = acpi_battery_remove,
|
.remove = acpi_battery_remove,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -753,6 +755,18 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this is needed to learn about changes made in suspended state */
|
||||||
|
static int acpi_battery_resume(struct acpi_device *device, int state)
|
||||||
|
{
|
||||||
|
struct acpi_battery *battery;
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
battery = device->driver_data;
|
||||||
|
return acpi_battery_check(battery);
|
||||||
|
}
|
||||||
|
|
||||||
static int __init acpi_battery_init(void)
|
static int __init acpi_battery_init(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
1108
drivers/acpi/ec.c
1108
drivers/acpi/ec.c
File diff suppressed because it is too large
Load Diff
@ -342,20 +342,8 @@ static u32 acpi_ev_global_lock_handler(void *context)
|
|||||||
if (acquired) {
|
if (acquired) {
|
||||||
|
|
||||||
/* Got the lock, now wake all threads waiting for it */
|
/* Got the lock, now wake all threads waiting for it */
|
||||||
|
|
||||||
acpi_gbl_global_lock_acquired = TRUE;
|
acpi_gbl_global_lock_acquired = TRUE;
|
||||||
|
acpi_ev_global_lock_thread(context);
|
||||||
/* Run the Global Lock thread which will signal all waiting threads */
|
|
||||||
|
|
||||||
status =
|
|
||||||
acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER,
|
|
||||||
acpi_ev_global_lock_thread, context);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
ACPI_EXCEPTION((AE_INFO, status,
|
|
||||||
"Could not queue Global Lock thread"));
|
|
||||||
|
|
||||||
return (ACPI_INTERRUPT_NOT_HANDLED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ACPI_INTERRUPT_HANDLED);
|
return (ACPI_INTERRUPT_HANDLED);
|
||||||
|
@ -225,13 +225,12 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
|||||||
if (!
|
if (!
|
||||||
(ACPI_STRNCMP
|
(ACPI_STRNCMP
|
||||||
(object_hID.value, PCI_ROOT_HID_STRING,
|
(object_hID.value, PCI_ROOT_HID_STRING,
|
||||||
sizeof(PCI_ROOT_HID_STRING))
|
sizeof(PCI_ROOT_HID_STRING)))
|
||||||
||
|
||
|
||||||
!(ACPI_STRNCMP
|
!(ACPI_STRNCMP
|
||||||
(object_hID.value,
|
(object_hID.value,
|
||||||
PCI_EXPRESS_ROOT_HID_STRING,
|
PCI_EXPRESS_ROOT_HID_STRING,
|
||||||
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
|
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
|
||||||
{
|
|
||||||
|
|
||||||
/* Install a handler for this PCI root bridge */
|
/* Install a handler for this PCI root bridge */
|
||||||
|
|
||||||
|
@ -1702,13 +1702,11 @@ static struct ibm_struct ibms[] = {
|
|||||||
.name = "brightness",
|
.name = "brightness",
|
||||||
.read = brightness_read,
|
.read = brightness_read,
|
||||||
.write = brightness_write,
|
.write = brightness_write,
|
||||||
.experimental = 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "volume",
|
.name = "volume",
|
||||||
.read = volume_read,
|
.read = volume_read,
|
||||||
.write = volume_write,
|
.write = volume_write,
|
||||||
.experimental = 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "fan",
|
.name = "fan",
|
||||||
|
@ -48,6 +48,12 @@ ACPI_MODULE_NAME("acpi_motherboard")
|
|||||||
* the io ports if they really know they can use it, while
|
* the io ports if they really know they can use it, while
|
||||||
* still preventing hotplug PCI devices from using it.
|
* still preventing hotplug PCI devices from using it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01
|
||||||
|
* and PNP0C02, redundant with acpi_reserve_io_ranges().
|
||||||
|
* But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP.
|
||||||
|
*/
|
||||||
static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
|
static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
|
||||||
{
|
{
|
||||||
struct resource *requested_res = NULL;
|
struct resource *requested_res = NULL;
|
||||||
|
@ -73,6 +73,7 @@ static unsigned int acpi_irq_irq;
|
|||||||
static acpi_osd_handler acpi_irq_handler;
|
static acpi_osd_handler acpi_irq_handler;
|
||||||
static void *acpi_irq_context;
|
static void *acpi_irq_context;
|
||||||
static struct workqueue_struct *kacpid_wq;
|
static struct workqueue_struct *kacpid_wq;
|
||||||
|
static struct workqueue_struct *kacpi_notify_wq;
|
||||||
|
|
||||||
acpi_status acpi_os_initialize(void)
|
acpi_status acpi_os_initialize(void)
|
||||||
{
|
{
|
||||||
@ -91,8 +92,9 @@ acpi_status acpi_os_initialize1(void)
|
|||||||
return AE_NULL_ENTRY;
|
return AE_NULL_ENTRY;
|
||||||
}
|
}
|
||||||
kacpid_wq = create_singlethread_workqueue("kacpid");
|
kacpid_wq = create_singlethread_workqueue("kacpid");
|
||||||
|
kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
|
||||||
BUG_ON(!kacpid_wq);
|
BUG_ON(!kacpid_wq);
|
||||||
|
BUG_ON(!kacpi_notify_wq);
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +106,7 @@ acpi_status acpi_os_terminate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy_workqueue(kacpid_wq);
|
destroy_workqueue(kacpid_wq);
|
||||||
|
destroy_workqueue(kacpi_notify_wq);
|
||||||
|
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
@ -566,10 +569,7 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
|
|||||||
|
|
||||||
static void acpi_os_execute_deferred(void *context)
|
static void acpi_os_execute_deferred(void *context)
|
||||||
{
|
{
|
||||||
struct acpi_os_dpc *dpc = NULL;
|
struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
|
||||||
|
|
||||||
|
|
||||||
dpc = (struct acpi_os_dpc *)context;
|
|
||||||
if (!dpc) {
|
if (!dpc) {
|
||||||
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
|
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
|
||||||
return;
|
return;
|
||||||
@ -604,14 +604,12 @@ acpi_status acpi_os_execute(acpi_execute_type type,
|
|||||||
struct acpi_os_dpc *dpc;
|
struct acpi_os_dpc *dpc;
|
||||||
struct work_struct *task;
|
struct work_struct *task;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE("os_queue_for_execution");
|
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||||
"Scheduling function [%p(%p)] for deferred execution.\n",
|
"Scheduling function [%p(%p)] for deferred execution.\n",
|
||||||
function, context));
|
function, context));
|
||||||
|
|
||||||
if (!function)
|
if (!function)
|
||||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
return AE_BAD_PARAMETER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate/initialize DPC structure. Note that this memory will be
|
* Allocate/initialize DPC structure. Note that this memory will be
|
||||||
@ -624,26 +622,20 @@ acpi_status acpi_os_execute(acpi_execute_type type,
|
|||||||
* from the same memory.
|
* from the same memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dpc =
|
dpc = kmalloc(sizeof(struct acpi_os_dpc) +
|
||||||
kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
|
sizeof(struct work_struct), GFP_ATOMIC);
|
||||||
GFP_ATOMIC);
|
|
||||||
if (!dpc)
|
if (!dpc)
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
return AE_NO_MEMORY;
|
||||||
|
|
||||||
dpc->function = function;
|
dpc->function = function;
|
||||||
dpc->context = context;
|
dpc->context = context;
|
||||||
|
|
||||||
task = (void *)(dpc + 1);
|
task = (void *)(dpc + 1);
|
||||||
INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
|
INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
|
||||||
|
if (!queue_work((type == OSL_NOTIFY_HANDLER)?
|
||||||
if (!queue_work(kacpid_wq, task)) {
|
kacpi_notify_wq : kacpid_wq, task)) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
|
||||||
"Call to queue_work() failed.\n"));
|
|
||||||
kfree(dpc);
|
|
||||||
status = AE_ERROR;
|
status = AE_ERROR;
|
||||||
|
kfree(dpc);
|
||||||
}
|
}
|
||||||
|
return status;
|
||||||
return_ACPI_STATUS(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_os_execute);
|
EXPORT_SYMBOL(acpi_os_execute);
|
||||||
|
@ -307,7 +307,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|||||||
if (!link || !irq)
|
if (!link || !irq)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
resource = kmalloc(sizeof(*resource) + 1, GFP_ATOMIC);
|
resource = kmalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
|
||||||
if (!resource)
|
if (!resource)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -216,10 +216,8 @@ static int acpi_power_off_device(acpi_handle handle)
|
|||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
acpi_status status = AE_OK;
|
acpi_status status = AE_OK;
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
struct acpi_power_resource *resource = NULL;
|
struct acpi_power_resource *resource = NULL;
|
||||||
|
|
||||||
|
|
||||||
result = acpi_power_get_context(handle, &resource);
|
result = acpi_power_get_context(handle, &resource);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
@ -230,13 +228,13 @@ static int acpi_power_off_device(acpi_handle handle)
|
|||||||
if (resource->references) {
|
if (resource->references) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||||
"Resource [%s] is still in use, dereferencing\n",
|
"Resource [%s] is still in use, dereferencing\n",
|
||||||
device->pnp.bus_id));
|
resource->device->pnp.bus_id));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
|
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
|
||||||
device->pnp.bus_id));
|
resource->device->pnp.bus_id));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,8 +249,7 @@ static int acpi_power_off_device(acpi_handle handle)
|
|||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
|
|
||||||
/* Update the power resource's _device_ power state */
|
/* Update the power resource's _device_ power state */
|
||||||
device = resource->device;
|
resource->device->power.state = ACPI_STATE_D3;
|
||||||
device->power.state = ACPI_STATE_D3;
|
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
|
||||||
resource->name));
|
resource->name));
|
||||||
|
@ -519,7 +519,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
|
|||||||
|
|
||||||
static void *processor_device_array[NR_CPUS];
|
static void *processor_device_array[NR_CPUS];
|
||||||
|
|
||||||
static int acpi_processor_start(struct acpi_device *device)
|
static int __cpuinit acpi_processor_start(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
acpi_status status = AE_OK;
|
acpi_status status = AE_OK;
|
||||||
|
@ -219,6 +219,23 @@ static void acpi_safe_halt(void)
|
|||||||
|
|
||||||
static atomic_t c3_cpu_count;
|
static atomic_t c3_cpu_count;
|
||||||
|
|
||||||
|
/* Common C-state entry for C2, C3, .. */
|
||||||
|
static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
|
||||||
|
{
|
||||||
|
if (cstate->space_id == ACPI_CSTATE_FFH) {
|
||||||
|
/* Call into architectural FFH based C-state */
|
||||||
|
acpi_processor_ffh_cstate_enter(cstate);
|
||||||
|
} else {
|
||||||
|
int unused;
|
||||||
|
/* IO port based C-state */
|
||||||
|
inb(cstate->address);
|
||||||
|
/* Dummy wait op - must do something useless after P_LVL2 read
|
||||||
|
because chipsets cannot guarantee that STPCLK# signal
|
||||||
|
gets asserted in time to freeze execution properly. */
|
||||||
|
unused = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void acpi_processor_idle(void)
|
static void acpi_processor_idle(void)
|
||||||
{
|
{
|
||||||
struct acpi_processor *pr = NULL;
|
struct acpi_processor *pr = NULL;
|
||||||
@ -361,11 +378,7 @@ static void acpi_processor_idle(void)
|
|||||||
/* Get start time (ticks) */
|
/* Get start time (ticks) */
|
||||||
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
|
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||||
/* Invoke C2 */
|
/* Invoke C2 */
|
||||||
inb(cx->address);
|
acpi_cstate_enter(cx);
|
||||||
/* Dummy wait op - must do something useless after P_LVL2 read
|
|
||||||
because chipsets cannot guarantee that STPCLK# signal
|
|
||||||
gets asserted in time to freeze execution properly. */
|
|
||||||
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
|
||||||
/* Get end time (ticks) */
|
/* Get end time (ticks) */
|
||||||
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||||
|
|
||||||
@ -401,9 +414,7 @@ static void acpi_processor_idle(void)
|
|||||||
/* Get start time (ticks) */
|
/* Get start time (ticks) */
|
||||||
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
|
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||||
/* Invoke C3 */
|
/* Invoke C3 */
|
||||||
inb(cx->address);
|
acpi_cstate_enter(cx);
|
||||||
/* Dummy wait op (see above) */
|
|
||||||
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
|
||||||
/* Get end time (ticks) */
|
/* Get end time (ticks) */
|
||||||
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||||
if (pr->flags.bm_check) {
|
if (pr->flags.bm_check) {
|
||||||
@ -628,20 +639,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
|
static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
|
if (!pr->power.states[ACPI_STATE_C1].valid) {
|
||||||
/* Zero initialize all the C-states info. */
|
/* set the first C-State to C1 */
|
||||||
memset(pr->power.states, 0, sizeof(pr->power.states));
|
/* all processors need to support C1 */
|
||||||
|
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
|
||||||
/* set the first C-State to C1 */
|
pr->power.states[ACPI_STATE_C1].valid = 1;
|
||||||
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
|
}
|
||||||
|
/* the C0 state only exists as a filler in our array */
|
||||||
/* the C0 state only exists as a filler in our array,
|
|
||||||
* and all processors need to support C1 */
|
|
||||||
pr->power.states[ACPI_STATE_C0].valid = 1;
|
pr->power.states[ACPI_STATE_C0].valid = 1;
|
||||||
pr->power.states[ACPI_STATE_C1].valid = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,12 +665,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
|
|||||||
if (nocst)
|
if (nocst)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
current_count = 1;
|
current_count = 0;
|
||||||
|
|
||||||
/* Zero initialize C2 onwards and prepare for fresh CST lookup */
|
|
||||||
for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
|
|
||||||
memset(&(pr->power.states[i]), 0,
|
|
||||||
sizeof(struct acpi_processor_cx));
|
|
||||||
|
|
||||||
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
|
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
@ -718,22 +720,39 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
|
|||||||
(reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
|
(reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
|
|
||||||
0 : reg->address;
|
|
||||||
|
|
||||||
/* There should be an easy way to extract an integer... */
|
/* There should be an easy way to extract an integer... */
|
||||||
obj = (union acpi_object *)&(element->package.elements[1]);
|
obj = (union acpi_object *)&(element->package.elements[1]);
|
||||||
if (obj->type != ACPI_TYPE_INTEGER)
|
if (obj->type != ACPI_TYPE_INTEGER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cx.type = obj->integer.value;
|
cx.type = obj->integer.value;
|
||||||
|
/*
|
||||||
|
* Some buggy BIOSes won't list C1 in _CST -
|
||||||
|
* Let acpi_processor_get_power_info_default() handle them later
|
||||||
|
*/
|
||||||
|
if (i == 1 && cx.type != ACPI_STATE_C1)
|
||||||
|
current_count++;
|
||||||
|
|
||||||
if ((cx.type != ACPI_STATE_C1) &&
|
cx.address = reg->address;
|
||||||
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
|
cx.index = current_count + 1;
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
|
cx.space_id = ACPI_CSTATE_SYSTEMIO;
|
||||||
continue;
|
if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
|
||||||
|
if (acpi_processor_ffh_cstate_probe
|
||||||
|
(pr->id, &cx, reg) == 0) {
|
||||||
|
cx.space_id = ACPI_CSTATE_FFH;
|
||||||
|
} else if (cx.type != ACPI_STATE_C1) {
|
||||||
|
/*
|
||||||
|
* C1 is a special case where FIXED_HARDWARE
|
||||||
|
* can be handled in non-MWAIT way as well.
|
||||||
|
* In that case, save this _CST entry info.
|
||||||
|
* That is, we retain space_id of SYSTEM_IO for
|
||||||
|
* halt based C1.
|
||||||
|
* Otherwise, ignore this info and continue.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj = (union acpi_object *)&(element->package.elements[2]);
|
obj = (union acpi_object *)&(element->package.elements[2]);
|
||||||
if (obj->type != ACPI_TYPE_INTEGER)
|
if (obj->type != ACPI_TYPE_INTEGER)
|
||||||
@ -938,12 +957,18 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
|
|||||||
/* NOTE: the idle thread may not be running while calling
|
/* NOTE: the idle thread may not be running while calling
|
||||||
* this function */
|
* this function */
|
||||||
|
|
||||||
/* Adding C1 state */
|
/* Zero initialize all the C-states info. */
|
||||||
acpi_processor_get_power_info_default_c1(pr);
|
memset(pr->power.states, 0, sizeof(pr->power.states));
|
||||||
|
|
||||||
result = acpi_processor_get_power_info_cst(pr);
|
result = acpi_processor_get_power_info_cst(pr);
|
||||||
if (result == -ENODEV)
|
if (result == -ENODEV)
|
||||||
acpi_processor_get_power_info_fadt(pr);
|
acpi_processor_get_power_info_fadt(pr);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
acpi_processor_get_power_info_default(pr);
|
||||||
|
|
||||||
pr->power.count = acpi_processor_power_verify(pr);
|
pr->power.count = acpi_processor_power_verify(pr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1105,7 +1130,7 @@ static struct notifier_block acpi_processor_latency_notifier = {
|
|||||||
.notifier_call = acpi_processor_latency_notify,
|
.notifier_call = acpi_processor_latency_notify,
|
||||||
};
|
};
|
||||||
|
|
||||||
int acpi_processor_power_init(struct acpi_processor *pr,
|
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
struct acpi_device *device)
|
struct acpi_device *device)
|
||||||
{
|
{
|
||||||
acpi_status status = 0;
|
acpi_status status = 0;
|
||||||
|
@ -98,11 +98,11 @@ static int update_info_mode = UPDATE_INFO_MODE;
|
|||||||
static int update_time = UPDATE_TIME;
|
static int update_time = UPDATE_TIME;
|
||||||
static int update_time2 = UPDATE_TIME2;
|
static int update_time2 = UPDATE_TIME2;
|
||||||
|
|
||||||
module_param(capacity_mode, int, CAPACITY_UNIT);
|
module_param(capacity_mode, int, 0);
|
||||||
module_param(update_mode, int, UPDATE_MODE);
|
module_param(update_mode, int, 0);
|
||||||
module_param(update_info_mode, int, UPDATE_INFO_MODE);
|
module_param(update_info_mode, int, 0);
|
||||||
module_param(update_time, int, UPDATE_TIME);
|
module_param(update_time, int, 0);
|
||||||
module_param(update_time2, int, UPDATE_TIME2);
|
module_param(update_time2, int, 0);
|
||||||
|
|
||||||
static int acpi_sbs_add(struct acpi_device *device);
|
static int acpi_sbs_add(struct acpi_device *device);
|
||||||
static int acpi_sbs_remove(struct acpi_device *device, int type);
|
static int acpi_sbs_remove(struct acpi_device *device, int type);
|
||||||
@ -1685,10 +1685,16 @@ static int acpi_sbs_add(struct acpi_device *device)
|
|||||||
|
|
||||||
int acpi_sbs_remove(struct acpi_device *device, int type)
|
int acpi_sbs_remove(struct acpi_device *device, int type)
|
||||||
{
|
{
|
||||||
struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
|
struct acpi_sbs *sbs = NULL;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
if (!device || !sbs) {
|
if (!device) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sbs = (struct acpi_sbs *)acpi_driver_data(device);
|
||||||
|
|
||||||
|
if (!sbs) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
|
|||||||
|
|
||||||
if (header->length < sizeof(struct acpi_table_header)) {
|
if (header->length < sizeof(struct acpi_table_header)) {
|
||||||
ACPI_ERROR((AE_INFO,
|
ACPI_ERROR((AE_INFO,
|
||||||
"Table length (%X) is smaller than minimum (%X)",
|
"Table length (%X) is smaller than minimum (%zX)",
|
||||||
header->length, sizeof(struct acpi_table_header)));
|
header->length, sizeof(struct acpi_table_header)));
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
||||||
|
@ -187,7 +187,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
|
|||||||
|
|
||||||
if (table_ptr->length < sizeof(struct acpi_table_header)) {
|
if (table_ptr->length < sizeof(struct acpi_table_header)) {
|
||||||
ACPI_ERROR((AE_INFO,
|
ACPI_ERROR((AE_INFO,
|
||||||
"RSDT/XSDT length (%X) is smaller than minimum (%X)",
|
"RSDT/XSDT length (%X) is smaller than minimum (%zX)",
|
||||||
table_ptr->length,
|
table_ptr->length,
|
||||||
sizeof(struct acpi_table_header)));
|
sizeof(struct acpi_table_header)));
|
||||||
|
|
||||||
|
@ -57,4 +57,23 @@ config TIFM_7XX1
|
|||||||
To compile this driver as a module, choose M here: the module will
|
To compile this driver as a module, choose M here: the module will
|
||||||
be called tifm_7xx1.
|
be called tifm_7xx1.
|
||||||
|
|
||||||
|
config MSI_LAPTOP
|
||||||
|
tristate "MSI Laptop Extras"
|
||||||
|
depends on X86
|
||||||
|
depends on ACPI_EC
|
||||||
|
depends on BACKLIGHT_CLASS_DEVICE
|
||||||
|
---help---
|
||||||
|
This is a driver for laptops built by MSI (MICRO-STAR
|
||||||
|
INTERNATIONAL):
|
||||||
|
|
||||||
|
MSI MegaBook S270 (MS-1013)
|
||||||
|
Cytron/TCM/Medion/Tchibo MD96100/SAM2000
|
||||||
|
|
||||||
|
It adds support for Bluetooth, WLAN and LCD brightness control.
|
||||||
|
|
||||||
|
More information about this driver is available at
|
||||||
|
<http://0pointer.de/lennart/tchibo.html>.
|
||||||
|
|
||||||
|
If you have an MSI S270 laptop, say Y or M here.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -5,6 +5,7 @@ obj- := misc.o # Dummy rule to force built-in.o to be made
|
|||||||
|
|
||||||
obj-$(CONFIG_IBM_ASM) += ibmasm/
|
obj-$(CONFIG_IBM_ASM) += ibmasm/
|
||||||
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
|
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
|
||||||
|
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
|
||||||
obj-$(CONFIG_LKDTM) += lkdtm.o
|
obj-$(CONFIG_LKDTM) += lkdtm.o
|
||||||
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
|
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
|
||||||
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
|
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
|
||||||
|
395
drivers/misc/msi-laptop.c
Normal file
395
drivers/misc/msi-laptop.c
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
/*-*-linux-c-*-*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* msi-laptop.c - MSI S270 laptop support. This laptop is sold under
|
||||||
|
* various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
|
||||||
|
*
|
||||||
|
* This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
|
||||||
|
*
|
||||||
|
* lcd_level - Screen brightness: contains a single integer in the
|
||||||
|
* range 0..8. (rw)
|
||||||
|
*
|
||||||
|
* auto_brightness - Enable automatic brightness control: contains
|
||||||
|
* either 0 or 1. If set to 1 the hardware adjusts the screen
|
||||||
|
* brightness automatically when the power cord is
|
||||||
|
* plugged/unplugged. (rw)
|
||||||
|
*
|
||||||
|
* wlan - WLAN subsystem enabled: contains either 0 or 1. (ro)
|
||||||
|
*
|
||||||
|
* bluetooth - Bluetooth subsystem enabled: contains either 0 or 1
|
||||||
|
* Please note that this file is constantly 0 if no Bluetooth
|
||||||
|
* hardware is available. (ro)
|
||||||
|
*
|
||||||
|
* In addition to these platform device attributes the driver
|
||||||
|
* registers itself in the Linux backlight control subsystem and is
|
||||||
|
* available to userspace under /sys/class/backlight/msi-laptop-bl/.
|
||||||
|
*
|
||||||
|
* This driver might work on other laptops produced by MSI. If you
|
||||||
|
* want to try it you can pass force=1 as argument to the module which
|
||||||
|
* will force it to load even when the DMI data doesn't identify the
|
||||||
|
* laptop as MSI S270. YMMV.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
#include <linux/backlight.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/autoconf.h>
|
||||||
|
|
||||||
|
#define MSI_DRIVER_VERSION "0.5"
|
||||||
|
|
||||||
|
#define MSI_LCD_LEVEL_MAX 9
|
||||||
|
|
||||||
|
#define MSI_EC_COMMAND_WIRELESS 0x10
|
||||||
|
#define MSI_EC_COMMAND_LCD_LEVEL 0x11
|
||||||
|
|
||||||
|
static int force;
|
||||||
|
module_param(force, bool, 0);
|
||||||
|
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
|
||||||
|
|
||||||
|
static int auto_brightness;
|
||||||
|
module_param(auto_brightness, int, 0);
|
||||||
|
MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
|
||||||
|
|
||||||
|
/* Hardware access */
|
||||||
|
|
||||||
|
static int set_lcd_level(int level)
|
||||||
|
{
|
||||||
|
u8 buf[2];
|
||||||
|
|
||||||
|
if (level < 0 || level >= MSI_LCD_LEVEL_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
buf[0] = 0x80;
|
||||||
|
buf[1] = (u8) (level*31);
|
||||||
|
|
||||||
|
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_lcd_level(void)
|
||||||
|
{
|
||||||
|
u8 wdata = 0, rdata;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return (int) rdata / 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_auto_brightness(void)
|
||||||
|
{
|
||||||
|
u8 wdata = 4, rdata;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return !!(rdata & 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_auto_brightness(int enable)
|
||||||
|
{
|
||||||
|
u8 wdata[2], rdata;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
wdata[0] = 4;
|
||||||
|
|
||||||
|
result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
wdata[0] = 0x84;
|
||||||
|
wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0);
|
||||||
|
|
||||||
|
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_wireless_state(int *wlan, int *bluetooth)
|
||||||
|
{
|
||||||
|
u8 wdata = 0, rdata;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1);
|
||||||
|
if (result < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (wlan)
|
||||||
|
*wlan = !!(rdata & 8);
|
||||||
|
|
||||||
|
if (bluetooth)
|
||||||
|
*bluetooth = !!(rdata & 128);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Backlight device stuff */
|
||||||
|
|
||||||
|
static int bl_get_brightness(struct backlight_device *b)
|
||||||
|
{
|
||||||
|
return get_lcd_level();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int bl_update_status(struct backlight_device *b)
|
||||||
|
{
|
||||||
|
return set_lcd_level(b->props->brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct backlight_properties msibl_props = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.get_brightness = bl_get_brightness,
|
||||||
|
.update_status = bl_update_status,
|
||||||
|
.max_brightness = MSI_LCD_LEVEL_MAX-1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct backlight_device *msibl_device;
|
||||||
|
|
||||||
|
/* Platform device */
|
||||||
|
|
||||||
|
static ssize_t show_wlan(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret, enabled;
|
||||||
|
|
||||||
|
ret = get_wireless_state(&enabled, NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return sprintf(buf, "%i\n", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_bluetooth(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret, enabled;
|
||||||
|
|
||||||
|
ret = get_wireless_state(NULL, &enabled);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return sprintf(buf, "%i\n", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_lcd_level(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = get_lcd_level();
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return sprintf(buf, "%i\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_lcd_level(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
|
||||||
|
int level, ret;
|
||||||
|
|
||||||
|
if (sscanf(buf, "%i", &level) != 1 || (level < 0 || level >= MSI_LCD_LEVEL_MAX))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = set_lcd_level(level);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_auto_brightness(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = get_auto_brightness();
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return sprintf(buf, "%i\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_auto_brightness(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
|
||||||
|
int enable, ret;
|
||||||
|
|
||||||
|
if (sscanf(buf, "%i", &enable) != 1 || (enable != (enable & 1)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = set_auto_brightness(enable);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
|
||||||
|
static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness);
|
||||||
|
static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL);
|
||||||
|
static DEVICE_ATTR(wlan, 0444, show_wlan, NULL);
|
||||||
|
|
||||||
|
static struct attribute *msipf_attributes[] = {
|
||||||
|
&dev_attr_lcd_level.attr,
|
||||||
|
&dev_attr_auto_brightness.attr,
|
||||||
|
&dev_attr_bluetooth.attr,
|
||||||
|
&dev_attr_wlan.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group msipf_attribute_group = {
|
||||||
|
.attrs = msipf_attributes
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver msipf_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "msi-laptop-pf",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device *msipf_device;
|
||||||
|
|
||||||
|
/* Initialization */
|
||||||
|
|
||||||
|
static struct dmi_system_id __initdata msi_dmi_table[] = {
|
||||||
|
{
|
||||||
|
.ident = "MSI S270",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ident = "Medion MD96100",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int __init msi_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (acpi_disabled)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!force && !dmi_check_system(msi_dmi_table))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (auto_brightness < 0 || auto_brightness > 2)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Register backlight stuff */
|
||||||
|
|
||||||
|
msibl_device = backlight_device_register("msi-laptop-bl", NULL, &msibl_props);
|
||||||
|
if (IS_ERR(msibl_device))
|
||||||
|
return PTR_ERR(msibl_device);
|
||||||
|
|
||||||
|
ret = platform_driver_register(&msipf_driver);
|
||||||
|
if (ret)
|
||||||
|
goto fail_backlight;
|
||||||
|
|
||||||
|
/* Register platform stuff */
|
||||||
|
|
||||||
|
msipf_device = platform_device_alloc("msi-laptop-pf", -1);
|
||||||
|
if (!msipf_device) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto fail_platform_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = platform_device_add(msipf_device);
|
||||||
|
if (ret)
|
||||||
|
goto fail_platform_device1;
|
||||||
|
|
||||||
|
ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
|
||||||
|
if (ret)
|
||||||
|
goto fail_platform_device2;
|
||||||
|
|
||||||
|
/* Disable automatic brightness control by default because
|
||||||
|
* this module was probably loaded to do brightness control in
|
||||||
|
* software. */
|
||||||
|
|
||||||
|
if (auto_brightness != 2)
|
||||||
|
set_auto_brightness(auto_brightness);
|
||||||
|
|
||||||
|
printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_platform_device2:
|
||||||
|
|
||||||
|
platform_device_del(msipf_device);
|
||||||
|
|
||||||
|
fail_platform_device1:
|
||||||
|
|
||||||
|
platform_device_put(msipf_device);
|
||||||
|
|
||||||
|
fail_platform_driver:
|
||||||
|
|
||||||
|
platform_driver_unregister(&msipf_driver);
|
||||||
|
|
||||||
|
fail_backlight:
|
||||||
|
|
||||||
|
backlight_device_unregister(msibl_device);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit msi_cleanup(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
|
||||||
|
platform_device_unregister(msipf_device);
|
||||||
|
platform_driver_unregister(&msipf_driver);
|
||||||
|
backlight_device_unregister(msibl_device);
|
||||||
|
|
||||||
|
/* Enable automatic brightness control again */
|
||||||
|
if (auto_brightness != 2)
|
||||||
|
set_auto_brightness(1);
|
||||||
|
|
||||||
|
printk(KERN_INFO "msi-laptop: driver unloaded.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(msi_init);
|
||||||
|
module_exit(msi_cleanup);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Lennart Poettering");
|
||||||
|
MODULE_DESCRIPTION("MSI Laptop Support");
|
||||||
|
MODULE_VERSION(MSI_DRIVER_VERSION);
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -13,6 +13,7 @@
|
|||||||
#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
|
#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
|
||||||
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
|
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
|
||||||
#define ACPI_PDC_C_C1_FFH (0x0100)
|
#define ACPI_PDC_C_C1_FFH (0x0100)
|
||||||
|
#define ACPI_PDC_C_C2C3_FFH (0x0200)
|
||||||
|
|
||||||
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
|
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
|
||||||
ACPI_PDC_C_C1_HALT | \
|
ACPI_PDC_C_C1_HALT | \
|
||||||
@ -23,8 +24,10 @@
|
|||||||
ACPI_PDC_SMP_P_SWCOORD | \
|
ACPI_PDC_SMP_P_SWCOORD | \
|
||||||
ACPI_PDC_P_FFH)
|
ACPI_PDC_P_FFH)
|
||||||
|
|
||||||
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
|
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
|
||||||
ACPI_PDC_SMP_C1PT | \
|
ACPI_PDC_SMP_C1PT | \
|
||||||
ACPI_PDC_C_C1_HALT)
|
ACPI_PDC_C_C1_HALT | \
|
||||||
|
ACPI_PDC_C_C1_FFH | \
|
||||||
|
ACPI_PDC_C_C2C3_FFH)
|
||||||
|
|
||||||
#endif /* __PDC_INTEL_H__ */
|
#endif /* __PDC_INTEL_H__ */
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
#define DOMAIN_COORD_TYPE_SW_ANY 0xfd
|
#define DOMAIN_COORD_TYPE_SW_ANY 0xfd
|
||||||
#define DOMAIN_COORD_TYPE_HW_ALL 0xfe
|
#define DOMAIN_COORD_TYPE_HW_ALL 0xfe
|
||||||
|
|
||||||
|
#define ACPI_CSTATE_SYSTEMIO (0)
|
||||||
|
#define ACPI_CSTATE_FFH (1)
|
||||||
|
|
||||||
/* Power Management */
|
/* Power Management */
|
||||||
|
|
||||||
struct acpi_processor_cx;
|
struct acpi_processor_cx;
|
||||||
@ -58,6 +61,8 @@ struct acpi_processor_cx {
|
|||||||
u8 valid;
|
u8 valid;
|
||||||
u8 type;
|
u8 type;
|
||||||
u32 address;
|
u32 address;
|
||||||
|
u8 space_id;
|
||||||
|
u8 index;
|
||||||
u32 latency;
|
u32 latency;
|
||||||
u32 latency_ticks;
|
u32 latency_ticks;
|
||||||
u32 power;
|
u32 power;
|
||||||
@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
|
|||||||
#ifdef ARCH_HAS_POWER_INIT
|
#ifdef ARCH_HAS_POWER_INIT
|
||||||
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
|
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
|
||||||
unsigned int cpu);
|
unsigned int cpu);
|
||||||
|
int acpi_processor_ffh_cstate_probe(unsigned int cpu,
|
||||||
|
struct acpi_processor_cx *cx, struct acpi_power_register *reg);
|
||||||
|
void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cstate);
|
||||||
#else
|
#else
|
||||||
static inline void acpi_processor_power_init_bm_check(struct
|
static inline void acpi_processor_power_init_bm_check(struct
|
||||||
acpi_processor_flags
|
acpi_processor_flags
|
||||||
@ -214,6 +222,16 @@ static inline void acpi_processor_power_init_bm_check(struct
|
|||||||
flags->bm_check = 1;
|
flags->bm_check = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
static inline int acpi_processor_ffh_cstate_probe(unsigned int cpu,
|
||||||
|
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static inline void acpi_processor_ffh_cstate_enter(
|
||||||
|
struct acpi_processor_cx *cstate)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* in processor_perflib.c */
|
/* in processor_perflib.c */
|
||||||
|
@ -306,6 +306,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
|
|||||||
: :"a" (eax), "c" (ecx));
|
: :"a" (eax), "c" (ecx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
|
||||||
|
|
||||||
/* from system description table in BIOS. Mostly for MCA use, but
|
/* from system description table in BIOS. Mostly for MCA use, but
|
||||||
others may find it useful. */
|
others may find it useful. */
|
||||||
extern unsigned int machine_id;
|
extern unsigned int machine_id;
|
||||||
|
@ -475,6 +475,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
|
|||||||
: :"a" (eax), "c" (ecx));
|
: :"a" (eax), "c" (ecx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
|
||||||
|
|
||||||
#define stack_current() \
|
#define stack_current() \
|
||||||
({ \
|
({ \
|
||||||
struct thread_info *ti; \
|
struct thread_info *ti; \
|
||||||
|
@ -494,6 +494,9 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
|
|||||||
|
|
||||||
extern int ec_read(u8 addr, u8 *val);
|
extern int ec_read(u8 addr, u8 *val);
|
||||||
extern int ec_write(u8 addr, u8 val);
|
extern int ec_write(u8 addr, u8 val);
|
||||||
|
extern int ec_transaction(u8 command,
|
||||||
|
const u8 *wdata, unsigned wdata_len,
|
||||||
|
u8 *rdata, unsigned rdata_len);
|
||||||
|
|
||||||
#endif /*CONFIG_ACPI_EC*/
|
#endif /*CONFIG_ACPI_EC*/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user