Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
0979ec20
Commit
0979ec20
authored
Feb 05, 2004
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.1
into intel.com:/home/lenb/src/linux-acpi-test-2.6.2
parents
cbd884c9
651f8c98
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
527 additions
and
319 deletions
+527
-319
drivers/acpi/asus_acpi.c
drivers/acpi/asus_acpi.c
+464
-289
drivers/acpi/pci_irq.c
drivers/acpi/pci_irq.c
+7
-5
drivers/acpi/toshiba_acpi.c
drivers/acpi/toshiba_acpi.c
+56
-25
No files found.
drivers/acpi/asus_acpi.c
View file @
0979ec20
...
...
@@ -2,7 +2,7 @@
* asus_acpi.c - Asus Laptop ACPI Extras
*
*
* Copyright (C) 2002, 2003 Julien Lerouge, Karol Kozimor
* Copyright (C) 2002, 2003
, 2004
Julien Lerouge, Karol Kozimor
*
* 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
...
...
@@ -23,16 +23,16 @@
* http://sourceforge.net/projects/acpi4asus/
*
* Credits:
* Pontus Fuchs - Helper functions, cleanup
* Johann Wiesner - Small compile fixes
* John Belmonte - ACPI code for Toshiba laptop was a good starting point.
*
* TODO:
* add Fn key status
* Add mode selection on module loading (parameter) -> still necessary?
* Complete display switching -- may require dirty hacks?
* Complete display switching -- may require dirty hacks
or calling _DOS
?
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
...
...
@@ -41,12 +41,13 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#define ASUS_ACPI_VERSION "0.2
6
"
#define ASUS_ACPI_VERSION "0.2
7
"
#define PROC_ASUS "asus" //the directory
#define PROC_MLED "mled"
#define PROC_WLED "wled"
#define PROC_INFOS "info"
#define PROC_TLED "tled"
#define PROC_INFO "info"
#define PROC_LCD "lcd"
#define PROC_BRN "brn"
#define PROC_DISP "disp"
...
...
@@ -67,6 +68,7 @@
*/
#define MLED_ON 0x01 //is MLED ON ?
#define WLED_ON 0x02
#define TLED_ON 0x04
MODULE_AUTHOR
(
"Julien Lerouge, Karol Kozimor"
);
MODULE_DESCRIPTION
(
ACPI_HOTK_NAME
);
...
...
@@ -81,22 +83,25 @@ MODULE_PARM(asus_gid, "i");
MODULE_PARM_DESC
(
gid
,
"GID for entries in /proc/acpi/asus.
\n
"
);
/* For each model, all features implemented */
/* For each model, all features implemented,
* those marked with R are relative to HOTK, A for absolute */
struct
model_data
{
char
*
name
;
//name of the laptop
char
*
mt_mled
;
//method to handle mled
char
*
mled_status
;
//node to handle mled reading
char
*
mt_wled
;
//method to handle wled
char
*
wled_status
;
//node to handle wled reading
char
*
mt_lcd_switch
;
//method to turn LCD ON/OFF
char
*
lcd_status
;
//node to read LCD panel state
char
*
brightness_up
;
//method to set brightness up
char
*
brightness_down
;
//guess what ?
char
*
brightness_set
;
//method to set absolute brightness
char
*
brightness_get
;
//method to get absolute brightness
char
*
brightness_status
;
//node to get brightness
char
*
display_set
;
//method to set video output
char
*
display_get
;
//method to get video output
char
*
name
;
//name of the laptop________________A
char
*
mt_mled
;
//method to handle mled_____________R
char
*
mled_status
;
//node to handle mled reading_______A
char
*
mt_wled
;
//method to handle wled_____________R
char
*
wled_status
;
//node to handle wled reading_______A
char
*
mt_tled
;
//method to handle tled_____________R
char
*
tled_status
;
//node to handle tled reading_______A
char
*
mt_lcd_switch
;
//method to turn LCD ON/OFF_________A
char
*
lcd_status
;
//node to read LCD panel state______A
char
*
brightness_up
;
//method to set brightness up_______A
char
*
brightness_down
;
//guess what ?______________________A
char
*
brightness_set
;
//method to set absolute brightness_R
char
*
brightness_get
;
//method to get absolute brightness_R
char
*
brightness_status
;
//node to get brightness____________A
char
*
display_set
;
//method to set video output________R
char
*
display_get
;
//method to get video output________R
};
/*
...
...
@@ -108,87 +113,235 @@ struct asus_hotk {
acpi_handle
handle
;
//the handle of the hotk device
char
status
;
//status of the hotk, for LEDs, ...
struct
model_data
*
methods
;
//methods available on the laptop
u8
brightness
;
//brigh
ness level
u8
brightness
;
//bright
ness level
enum
{
A1X
=
0
,
//A1340D, A1300F
A2X
,
//A2500H
D1X
,
//D1
L1X
,
//L1400B
L2X
,
//L2000D -> TODO check Q11 (Fn+F8)
// Calling this method simply hangs the
// computer, ISMI method hangs the laptop.
A1x
=
0
,
//A1340D, A1300F
A2x
,
//A2500H
D1x
,
//D1
L2D
,
//L2000D
L3C
,
//L3800C
L3D
,
//L3400D
L3
X
,
//L3C
L5
X
,
//L5C TODO this model seems to have one more
// LED, add support
M
2X
,
//M2400E
M
3N
,
//M3700N, but also S1300N -> TODO WLED
S1
X
,
//S1300A -> TODO special keys do not work ?
S2
X
,
//S200 (J1 reported), Victor MP-XP7210
L3
H
,
//L3H, but also L2000E
L5
x
,
//L5800C
L8L
,
//L8400L
M
1A
,
//M1300A
M
2E
,
//M2400E
S1
x
,
//S1300A, but also L1400B and M2400A (L84F)
S2
x
,
//S200 (J1 reported), Victor MP-XP7210
//TODO A1370D does not seem to have an ATK device
// L8400 model doesn't have ATK
xxN
,
//M2400N, M3700N, S1300N (Centrino)
END_MODEL
}
model
;
//Models currently supported
u16
event_count
[
128
];
//count for each event TODO make this better
};
/* Here we go */
#define
L3X_PREFIX "\\_SB.PCI0.PX40.ECD
0."
#define
S1X_PREFIX "\\_SB.PCI0.PX4
0."
#define
L1X_PREFIX S1X_PREFIX
#define
A1X_PREFIX "\\_SB.PCI0.ISA.EC
0."
#define S2
X_PREFIX A1X
_PREFIX
#define
M3
N_PREFIX "\\_SB.PCI0.SBRG.EC0."
#define
A1x_PREFIX "\\_SB.PCI0.ISA.EC
0."
#define
L3C_PREFIX "\\_SB.PCI0.PX40.ECD
0."
#define
M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
#define
S1x_PREFIX "\\_SB.PCI0.PX4
0."
#define S2
x_PREFIX A1x
_PREFIX
#define
xx
N_PREFIX "\\_SB.PCI0.SBRG.EC0."
static
struct
model_data
model_conf
[
END_MODEL
]
=
{
/*
* name| mled |mled read| wled |wled read| lcd sw |lcd read |
* br up|br down | br set | br read | br status|set disp | get disp
*
* br set and read shall be in hotk device !
* same for set disp
* Those pathnames are relative to the HOTK / ATKD device :
* - mt_mled
* - mt_wled
* - brightness_set
* - brightness_get
* - display_set
* - display_get
*
* TODO I have seen a SWBX and AIBX method on some models, like L1400B,
* it seems to be a kind of switch, but what for ?
*
*/
{
"A1X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
A1X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
A1X_PREFIX
"_Q0E"
,
A1X_PREFIX
"_Q0F"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
},
{
"A2X"
,
"MLED"
,
NULL
,
"WLED"
,
"
\\
SG66"
,
"
\\
Q10"
,
"
\\
BAOF"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
"
\\
CMOD"
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"A1x"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
MAIL"
,
.
mt_lcd_switch
=
A1x_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
BKLI"
,
.
brightness_up
=
A1x_PREFIX
"_Q0E"
,
.
brightness_down
=
A1x_PREFIX
"_Q0F"
,
},
{
"D1X"
,
"MLED"
,
NULL
,
NULL
,
NULL
,
"
\\
Q0D"
,
"
\\
GP11"
,
"
\\
Q0C"
,
"
\\
Q0B"
,
NULL
,
NULL
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"A2x"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
wled_status
=
"
\\
SG66"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
BAOF"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
CMOD"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"L1X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
L1X_PREFIX
"Q0F"
,
L1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
.
name
=
"D1x"
,
.
mt_mled
=
"MLED"
,
.
mt_lcd_switch
=
"
\\
Q0D"
,
.
lcd_status
=
"
\\
GP11"
,
.
brightness_up
=
"
\\
Q0C"
,
.
brightness_down
=
"
\\
Q0B"
,
.
brightness_status
=
"
\\
BLVL"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"L2X"
,
"MLED"
,
"
\\
SGP6"
,
"WLED"
,
"
\\
RCP3"
,
"
\\
Q10"
,
"
\\
SGP0"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
NULL
,
NULL
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"L2D"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
SGP6"
,
.
mt_wled
=
"WLED"
,
.
wled_status
=
"
\\
RCP3"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
SGP0"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"L3D"
,
"MLED"
,
"
\\
MALD"
,
"WLED"
,
NULL
,
"
\\
Q10"
,
"
\\
BKLG"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"L3C"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
L3C_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
GL32"
,
.
brightness_up
=
L3C_PREFIX
"_Q0F"
,
.
brightness_down
=
L3C_PREFIX
"_Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BLVL"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
},
{
"L3X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L3X_PREFIX
"_Q10"
,
"
\\
GL32"
,
L3X_PREFIX
"_Q0F"
,
L3X_PREFIX
"_Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
},
{
.
name
=
"L3D"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
MALD"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
BKLG"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BLVL"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"L5X"
,
"MLED"
,
NULL
,
"WLED"
,
"WRED"
,
"
\\
Q0D"
,
"
\\
BAOF"
,
"
\\
Q0C"
,
"
\\
Q0B"
,
"SPLV"
,
"GPLV"
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"L3H"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"EHK"
,
.
lcd_status
=
"
\\
_SB.PCI0.PM.PBC"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"L5x"
,
.
mt_mled
=
"MLED"
,
// .mt_wled = "WLED",
// .wled_status = "\\WRED",
/* Present, but not controlled by ACPI */
.
mt_tled
=
"TLED"
,
.
mt_lcd_switch
=
"
\\
Q0D"
,
.
lcd_status
=
"
\\
BAOF"
,
.
brightness_up
=
"
\\
Q0C"
,
.
brightness_down
=
"
\\
Q0B"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"M2X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
"
\\
Q10"
,
"
\\
GP06"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
.
name
=
"L8L"
/* No features, but at least support the hotkeys */
},
{
"M3N"
,
"MLED"
,
NULL
,
"WLED"
,
"
\\
PO33"
,
M3N_PREFIX
"_Q10"
,
"
\\
BKLT"
,
M3N_PREFIX
"_Q0F"
,
M3N_PREFIX
"_Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
LBTN"
,
"SDSP"
,
"
\\
ADVG"
},
{
.
name
=
"M1A"
,
.
mt_mled
=
"MLED"
,
.
mt_lcd_switch
=
M1A_PREFIX
"Q10"
,
.
lcd_status
=
"
\\
PNOF"
,
.
brightness_up
=
M1A_PREFIX
"Q0E"
,
.
brightness_down
=
M1A_PREFIX
"Q0F"
,
.
brightness_status
=
"
\\
BRIT"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"S1X"
,
"MLED"
,
"
\\
EMLE"
,
"WLED"
,
NULL
,
S1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
S1X_PREFIX
"Q0F"
,
S1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
.
name
=
"M2E"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
GP06"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
"S2X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
S2X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
S2X_PREFIX
"_Q0B"
,
S2X_PREFIX
"_Q0A"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
}
{
.
name
=
"S1x"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
EMLE"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
S1x_PREFIX
"Q10"
,
.
lcd_status
=
"
\\
PNOF"
,
.
brightness_up
=
S1x_PREFIX
"Q0F"
,
.
brightness_down
=
S1x_PREFIX
"Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BRIT"
,
},
{
.
name
=
"S2x"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
MAIL"
,
.
mt_lcd_switch
=
S2x_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
BKLI"
,
.
brightness_up
=
S2x_PREFIX
"_Q0B"
,
.
brightness_down
=
S2x_PREFIX
"_Q0A"
,
},
{
.
name
=
"xxN"
,
.
mt_mled
=
"MLED"
,
// .mt_wled = "WLED",
// .wled_status = "\\PO33",
/* Present, but not controlled by ACPI */
.
mt_lcd_switch
=
xxN_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
BKLT"
,
.
brightness_up
=
xxN_PREFIX
"_Q0F"
,
.
brightness_down
=
xxN_PREFIX
"_Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
LBTN"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
ADVG"
}
};
/* procdir we use */
...
...
@@ -264,7 +417,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
void
*
data
)
{
int
len
=
0
;
int
sfun
;
int
temp
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
char
buf
[
16
];
//enough for all info
/*
...
...
@@ -275,8 +428,23 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
len
+=
sprintf
(
page
,
ACPI_HOTK_NAME
" "
ASUS_ACPI_VERSION
"
\n
"
);
len
+=
sprintf
(
page
+
len
,
"Model reference : %s
\n
"
,
hotk
->
methods
->
name
);
if
(
read_acpi_int
(
hotk
->
handle
,
"SFUN"
,
&
sfun
))
len
+=
sprintf
(
page
+
len
,
"SFUN value : 0x%04x
\n
"
,
sfun
);
/*
* The SFUN method probably allows the original driver to get the list
* of features supported by a given model. For now, 0x0100 or 0x0800
* bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
* 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
);
/*
* Another value for userspace: the ASYM method returns 0x02 for
* battery low and 0x04 for battery critical, it's readings tend to be
* more accurate than those provided by _BST.
* Note: since not all the laptops provide this method, errors are
* silently ignored.
*/
if
(
read_acpi_int
(
hotk
->
handle
,
"ASYM"
,
&
temp
))
len
+=
sprintf
(
page
+
len
,
"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
);
...
...
@@ -301,127 +469,178 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
/*
* proc file handlers
* /proc handlers
* 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
*/
/* Generic LED functions */
static
int
proc_read_mled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
read_led
(
struct
asus_hotk
*
hotk
,
const
char
*
ledname
,
int
ledmask
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
=
0
;
/*
* We use the easy way, we don't care of off and count, so we don't set eof
* to 1
*/
if
(
hotk
->
methods
->
mled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
mled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
if
(
ledname
)
{
int
led_status
;
if
(
read_acpi_int
(
NULL
,
ledname
,
&
led_status
))
return
led_status
;
else
printk
(
KERN_WARNING
"Asus ACPI: Error reading
M
LED "
printk
(
KERN_WARNING
"Asus ACPI: Error reading LED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
MLED_ON
)
?
1
:
0
);
}
return
len
;
return
(
hotk
->
status
&
ledmask
)
?
1
:
0
;
}
/* FIXME: kill extraneous args so it can be called independently */
static
int
proc_write_mled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
write_led
(
const
char
*
buffer
,
unsigned
long
count
,
struct
asus_hotk
*
hotk
,
char
*
ledname
,
int
ledmask
,
int
invert
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
~
value
&
1
;
led_out
=
value
?
1
:
0
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
MLED_ON
)
:
(
hotk
->
status
&
~
MLED_ON
);
/* We don't have to check mt_mled exists if we are here :) */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
mt_mled
,
led_out
,
NULL
))
printk
(
KERN_WARNING
"Asus ACPI: MLED write failed
\n
"
);
(
led_out
)
?
(
hotk
->
status
|
ledmask
)
:
(
hotk
->
status
&
~
ledmask
);
if
(
invert
)
/* invert target value */
led_out
=
!
led_out
&
0x1
;
if
(
!
write_acpi_int
(
hotk
->
handle
,
ledname
,
led_out
,
NULL
))
printk
(
KERN_WARNING
"Asus ACPI: LED (%s) write failed
\n
"
,
ledname
);
return
count
;
}
/*
* 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
* Proc handlers for MLED
*/
static
int
proc_read_
w
led
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
proc_read_
m
led
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
mled_status
,
MLED_ON
));
}
if
(
hotk
->
methods
->
wled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
wled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
else
printk
(
KERN_WARNING
"Asus ACPI: Error reading WLED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
WLED_ON
)
?
1
:
0
);
}
return
len
;
static
int
proc_write_mled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_mled
,
MLED_ON
,
1
);
}
/*
* Proc handlers for WLED
*/
static
int
proc_read_wled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
wled_status
,
WLED_ON
));
}
static
int
proc_write_wled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_wled
,
WLED_ON
,
0
);
}
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
value
&
1
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
WLED_ON
)
:
(
hotk
->
status
&
~
WLED_ON
);
/* We don't have to check if mt_wled exists if we are here :) */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
mt_wled
,
led_out
,
NULL
))
printk
(
KERN_WARNING
"Asus ACPI: WLED write failed
\n
"
);
/*
* Proc handlers for TLED
*/
static
int
proc_read_tled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
tled_status
,
TLED_ON
));
}
return
count
;
static
int
proc_write_tled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_tled
,
TLED_ON
,
0
);
}
static
int
get_lcd_state
(
struct
asus_hotk
*
hotk
)
{
int
lcd
=
0
;
/* We don't have to check anything, if we are here */
if
(
hotk
->
model
!=
L3H
)
{
/* We don't have to check anything if we are here */
if
(
!
read_acpi_int
(
NULL
,
hotk
->
methods
->
lcd_status
,
&
lcd
))
printk
(
KERN_WARNING
"Asus ACPI: Error reading LCD status
\n
"
);
if
(
hotk
->
model
==
L2X
)
if
(
hotk
->
model
==
L2D
)
lcd
=
~
lcd
;
}
else
{
/* L3H and the like have to be handled differently */
acpi_status
status
=
0
;
struct
acpi_object_list
input
;
union
acpi_object
mt_params
[
2
];
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
input
.
count
=
2
;
input
.
pointer
=
mt_params
;
/* Note: the following values are partly guessed up, but
otherwise they seem to work */
mt_params
[
0
].
type
=
ACPI_TYPE_INTEGER
;
mt_params
[
0
].
integer
.
value
=
0x02
;
mt_params
[
1
].
type
=
ACPI_TYPE_INTEGER
;
mt_params
[
1
].
integer
.
value
=
0x02
;
output
.
length
=
sizeof
(
out_obj
);
output
.
pointer
=
&
out_obj
;
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
lcd_status
,
&
input
,
&
output
);
if
(
status
!=
AE_OK
)
return
-
1
;
if
(
out_obj
.
type
==
ACPI_TYPE_INTEGER
)
/* That's what the AML code does */
lcd
=
out_obj
.
integer
.
value
>>
8
;
}
return
(
lcd
&
1
);
}
static
int
set_lcd_state
(
struct
asus_hotk
*
hotk
,
int
value
)
{
int
lcd
=
0
;
acpi_status
status
=
0
;
lcd
=
value
?
1
:
0
;
if
(
lcd
!=
get_lcd_state
(
hotk
))
{
/* switch */
if
(
hotk
->
model
!=
L3H
)
{
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
mt_lcd_switch
,
NULL
,
NULL
);
}
else
{
/* L3H and the like have to be handled differently */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
mt_lcd_switch
,
0x07
,
NULL
))
status
=
AE_ERROR
;
/* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
the exact behaviour is simulated here */
}
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_WARNING
"Asus ACPI: Error switching LCD
\n
"
);
}
return
0
;
}
static
int
proc_read_lcd
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
...
...
@@ -436,26 +655,10 @@ proc_write_lcd(struct file *file, const char *buffer,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
lcd
=
0
;
acpi_status
status
=
0
;
int
lcd_status
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
lcd
=
value
&
1
;
lcd_status
=
get_lcd_state
(
hotk
);
if
(
lcd_status
!=
lcd
)
{
/* switch */
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
mt_lcd_switch
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_WARNING
"Asus ACPI: Error switching LCD
\n
"
);
}
set_lcd_state
(
hotk
,
value
);
return
count
;
}
...
...
@@ -521,7 +724,6 @@ proc_write_brn(struct file *file, const char *buffer,
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
{
value
=
(
0
<
value
)
?
((
15
<
value
)
?
15
:
value
)
:
0
;
/* 0 <= value <= 15 */
...
...
@@ -546,7 +748,6 @@ static void set_display(int value, struct asus_hotk *hotk)
* 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
)
...
...
@@ -560,12 +761,11 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
}
/*
* Experimental support for display switching. As of now:
0x0
1 should activate
* the LCD output,
0x02 should do for CRT, and 0x0
4 for TV-Out. Any combination
* Experimental support for display switching. As of now: 1 should activate
* the LCD output,
2 should do for CRT, and
4 for TV-Out. Any combination
* (bitwise) of these will suffice. I never actually tested 3 displays hooked up
* simultaneously, so be warned.
* simultaneously, so be warned.
See the acpi4asus README for more info.
*/
static
int
proc_write_disp
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
...
...
@@ -573,7 +773,6 @@ proc_write_disp(struct file *file, const char *buffer,
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
set_display
(
value
,
hotk
);
else
{
...
...
@@ -583,6 +782,31 @@ proc_write_disp(struct file *file, const char *buffer,
return
count
;
}
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
*
buffer
,
unsigned
long
count
,
void
*
data
);
static
int
__init
asus_proc_add
(
char
*
name
,
proc_writefunc
*
writefunc
,
proc_readfunc
*
readfunc
,
mode_t
mode
,
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
proc
=
create_proc_entry
(
name
,
mode
,
acpi_device_dir
(
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
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;
return
0
;
}
static
int
__init
asus_hotk_add_fs
(
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
proc
;
...
...
@@ -605,46 +829,28 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
if
(
!
acpi_device_dir
(
device
))
return
(
-
ENODEV
);
proc
=
create_proc_entry
(
PROC_INFO
S
,
mode
,
acpi_device_dir
(
device
));
proc
=
create_proc_entry
(
PROC_INFO
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
read_proc
=
proc_read_info
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;
;
proc
->
gid
=
asus_gid
;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_INFO
S
printk
(
KERN_WARNING
" Unable to create "
PROC_INFO
" fs entry
\n
"
);
}
if
(
hotk
->
methods
->
mt_wled
)
{
proc
=
create_proc_entry
(
PROC_WLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_wled
;
proc
->
read_proc
=
proc_read_wled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_WLED
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_WLED
,
&
proc_write_wled
,
&
proc_read_wled
,
mode
,
device
);
}
if
(
hotk
->
methods
->
mt_mled
)
{
proc
=
create_proc_entry
(
PROC_MLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_mled
;
proc
->
read_proc
=
proc_read_mled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_MLED
" fs entry
\n
"
);
asus_proc_add
(
PROC_MLED
,
&
proc_write_mled
,
&
proc_read_mled
,
mode
,
device
);
}
if
(
hotk
->
methods
->
mt_tled
)
{
asus_proc_add
(
PROC_TLED
,
&
proc_write_tled
,
&
proc_read_tled
,
mode
,
device
);
}
/*
...
...
@@ -652,49 +858,17 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
* from keyboard
*/
if
(
hotk
->
methods
->
mt_lcd_switch
&&
hotk
->
methods
->
lcd_status
)
{
proc
=
create_proc_entry
(
PROC_LCD
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_lcd
;
proc
->
read_proc
=
proc_read_lcd
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_LCD
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_LCD
,
&
proc_write_lcd
,
&
proc_read_lcd
,
mode
,
device
);
}
if
((
hotk
->
methods
->
brightness_up
&&
hotk
->
methods
->
brightness_down
)
||
(
hotk
->
methods
->
brightness_get
&&
hotk
->
methods
->
brightness_get
))
{
proc
=
create_proc_entry
(
PROC_BRN
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_brn
;
proc
->
read_proc
=
proc_read_brn
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_BRN
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_BRN
,
&
proc_write_brn
,
&
proc_read_brn
,
mode
,
device
);
}
if
(
hotk
->
methods
->
display_set
)
{
proc
=
create_proc_entry
(
PROC_DISP
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_disp
;
proc
->
read_proc
=
proc_read_disp
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_DISP
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_DISP
,
&
proc_write_disp
,
&
proc_read_disp
,
mode
,
device
);
}
return
0
;
...
...
@@ -761,11 +935,6 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
else
if
(
bsts_result
)
printk
(
KERN_NOTICE
" BSTS called, 0x%02x returned
\n
"
,
bsts_result
);
/*
* Here, we also use asus_info to make decision. For example, on INIT
* method, S1X and L1X models both reports to be L84F, but they don't
* have the same methods (L1X has WLED, S1X don't)
*/
model
=
(
union
acpi_object
*
)
buffer
.
pointer
;
if
(
model
->
type
==
ACPI_TYPE_STRING
)
{
printk
(
KERN_NOTICE
" %s model detected, "
,
model
->
string
.
pointer
);
...
...
@@ -774,52 +943,63 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
hotk
->
model
=
END_MODEL
;
if
(
strncmp
(
model
->
string
.
pointer
,
"L3D"
,
3
)
==
0
)
hotk
->
model
=
L3D
;
/*
* L2B has same settings that L3X, except for GL32, but as
* there is no node to get the LCD status, and as GL32 is never
* used anywhere else, I assume it's safe, even if lcd get is
* broken for this model (TODO fix it ?)
*/
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L3H"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"L2E"
,
3
)
==
0
)
hotk
->
model
=
L3H
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L3"
,
2
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"L2B"
,
3
)
==
0
)
hotk
->
model
=
L3X
;
hotk
->
model
=
L3C
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8L"
,
3
)
==
0
)
hotk
->
model
=
L8L
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M2N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"M3N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S1N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S5N"
,
3
)
==
0
)
hotk
->
model
=
xxN
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M1"
,
2
)
==
0
)
hotk
->
model
=
M1A
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M2"
,
2
)
==
0
)
hotk
->
model
=
M2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M3N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S1N"
,
3
)
==
0
)
hotk
->
model
=
M3N
;
/* S1300N is similar enough */
hotk
->
model
=
M2E
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L2"
,
2
)
==
0
)
hotk
->
model
=
L2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8"
,
2
)
==
0
)
{
/* S1300A reports L84F, but L1400B too */
if
(
asus_info
)
{
if
(
strncmp
(
asus_info
->
oem_table_id
,
"L1"
,
2
)
==
0
)
hotk
->
model
=
L1X
;
}
else
hotk
->
model
=
S1X
;
}
hotk
->
model
=
L2D
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8"
,
2
)
==
0
)
hotk
->
model
=
S1x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"D1"
,
2
)
==
0
)
hotk
->
model
=
D1
X
;
hotk
->
model
=
D1
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"A1"
,
2
)
==
0
)
hotk
->
model
=
A1
X
;
hotk
->
model
=
A1
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"A2"
,
2
)
==
0
)
hotk
->
model
=
A2
X
;
hotk
->
model
=
A2
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"J1"
,
2
)
==
0
)
hotk
->
model
=
S2
X
;
hotk
->
model
=
S2
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L5"
,
2
)
==
0
)
hotk
->
model
=
L5
X
;
hotk
->
model
=
L5
x
;
if
(
hotk
->
model
==
END_MODEL
)
{
/* By default use the same values, as I don't know others */
printk
(
"unsupported, trying default values, supply the "
"developers with your DSDT
\n
"
);
hotk
->
model
=
L2X
;
hotk
->
model
=
M2E
;
}
else
{
printk
(
"supported
\n
"
);
}
hotk
->
methods
=
&
model_conf
[
hotk
->
model
];
/* Sort of per-model blacklist */
if
(
strncmp
(
model
->
string
.
pointer
,
"L2B"
,
3
)
==
0
)
hotk
->
methods
->
lcd_status
=
NULL
;
/* L2B is similar enough to L3C to use its settings, with this only
exception */
else
if
(
strncmp
(
model
->
string
.
pointer
,
"S5N"
,
3
)
==
0
)
hotk
->
methods
->
mt_mled
=
NULL
;
/* S5N has no MLED */
else
if
(
asus_info
)
{
if
(
strncmp
(
asus_info
->
oem_table_id
,
"L1"
,
2
)
==
0
)
hotk
->
methods
->
mled_status
=
NULL
;
/* S1300A reports L84F, but L1400B too, account for that */
}
acpi_os_free
(
model
);
return
AE_OK
;
...
...
@@ -917,8 +1097,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
}
static
int
asus_hotk_remove
(
struct
acpi_device
*
device
,
int
type
)
{
acpi_status
status
=
0
;
...
...
@@ -940,15 +1118,13 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
}
static
int
__init
asus_acpi_init
(
void
)
{
int
result
;
asus_proc_dir
=
proc_mkdir
(
PROC_ASUS
,
acpi_root_dir
);
if
(
!
asus_proc_dir
)
{
printk
(
KERN_ERR
"Asus ACPI: Unable to create /proc entry"
);
printk
(
KERN_ERR
"Asus ACPI: Unable to create /proc entry
\n
"
);
return
(
-
ENODEV
);
}
asus_proc_dir
->
owner
=
THIS_MODULE
;
...
...
@@ -963,7 +1139,6 @@ static int __init asus_acpi_init(void)
}
static
void
__exit
asus_acpi_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
asus_hotk_driver
);
...
...
drivers/acpi/pci_irq.c
View file @
0979ec20
...
...
@@ -315,7 +315,6 @@ acpi_pci_irq_enable (
{
int
irq
=
0
;
u8
pin
=
0
;
static
u16
irq_mask
=
0
;
ACPI_FUNCTION_TRACE
(
"acpi_pci_irq_enable"
);
...
...
@@ -372,11 +371,14 @@ acpi_pci_irq_enable (
* Make sure all (legacy) PCI IRQs are set as level-triggered.
*/
#ifdef CONFIG_X86
{
static
u16
irq_mask
;
if
((
dev
->
irq
<
16
)
&&
!
((
1
<<
dev
->
irq
)
&
irq_mask
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Setting IRQ %d as level-triggered
\n
"
,
dev
->
irq
));
irq_mask
|=
(
1
<<
dev
->
irq
);
eisa_set_level_irq
(
dev
->
irq
);
}
}
#endif
#ifdef CONFIG_IOSAPIC
if
(
acpi_irq_model
==
ACPI_IRQ_MODEL_IOSAPIC
)
...
...
drivers/acpi/toshiba_acpi.c
View file @
0979ec20
...
...
@@ -2,7 +2,7 @@
* toshiba_acpi.c - Toshiba Laptop ACPI Extras
*
*
* Copyright (C) 2002-200
3
John Belmonte
* Copyright (C) 2002-200
4
John Belmonte
*
* 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
...
...
@@ -33,7 +33,7 @@
*
*/
#define TOSHIBA_ACPI_VERSION "0.1
6
"
#define TOSHIBA_ACPI_VERSION "0.1
7
"
#define PROC_INTERFACE_VERSION 1
#include <linux/kernel.h>
...
...
@@ -48,9 +48,15 @@ MODULE_AUTHOR("John Belmonte");
MODULE_DESCRIPTION
(
"Toshiba Laptop ACPI Extras Driver"
);
MODULE_LICENSE
(
"GPL"
);
#define MY_LOGPREFIX "toshiba_acpi: "
#define MY_ERR KERN_ERR MY_LOGPREFIX
#define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
#define MY_INFO KERN_INFO MY_LOGPREFIX
/* Toshiba ACPI method paths */
#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
#define METHOD_HCI "\\_SB_.VALD.GHCI"
#define METHOD_HCI_1 "\\_SB_.VALD.GHCI"
#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI"
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
/* Toshiba HCI interface definitions
...
...
@@ -120,6 +126,16 @@ snscanf(const char* str, int n, const char* format, ...)
/* acpi interface wrappers
*/
static
int
is_valid_acpi_path
(
const
char
*
methodName
)
{
acpi_handle
handle
;
acpi_status
status
;
status
=
acpi_get_handle
(
0
,
(
char
*
)
methodName
,
&
handle
);
return
!
ACPI_FAILURE
(
status
);
}
static
int
write_acpi_int
(
const
char
*
methodName
,
int
val
)
{
...
...
@@ -154,6 +170,8 @@ read_acpi_int(const char* methodName, int* pVal)
}
#endif
static
const
char
*
method_hci
/*= 0*/
;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
...
...
@@ -177,7 +195,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results
.
length
=
sizeof
(
out_objs
);
results
.
pointer
=
out_objs
;
status
=
acpi_evaluate_object
(
0
,
METHOD_HCI
,
&
params
,
status
=
acpi_evaluate_object
(
0
,
(
char
*
)
method_hci
,
&
params
,
&
results
);
if
((
status
==
AE_OK
)
&&
(
out_objs
->
package
.
count
<=
HCI_WORDS
))
{
for
(
i
=
0
;
i
<
out_objs
->
package
.
count
;
++
i
)
{
...
...
@@ -215,7 +233,7 @@ hci_read1(u32 reg, u32* out1, u32* result)
return
status
;
}
static
struct
proc_dir_entry
*
toshiba_proc_dir
;
static
struct
proc_dir_entry
*
toshiba_proc_dir
/*= 0*/
;
static
int
force_fan
;
static
int
last_key_event
;
static
int
key_event_valid
;
...
...
@@ -270,7 +288,7 @@ read_lcd(char* p)
p
+=
sprintf
(
p
,
"brightness_levels: %d
\n
"
,
HCI_LCD_BRIGHTNESS_LEVELS
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading LCD brightness
\n
"
);
}
return
p
;
...
...
@@ -310,7 +328,7 @@ read_video(char* p)
p
+=
sprintf
(
p
,
"crt_out: %d
\n
"
,
is_crt
);
p
+=
sprintf
(
p
,
"tv_out: %d
\n
"
,
is_tv
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading video out status
\n
"
);
}
return
p
;
...
...
@@ -320,25 +338,31 @@ static unsigned long
write_video
(
const
char
*
buffer
,
unsigned
long
count
)
{
int
value
;
const
char
*
buffer_end
=
buffer
+
count
;
int
remain
=
count
;
int
lcd_out
=
-
1
;
int
crt_out
=
-
1
;
int
tv_out
=
-
1
;
u32
hci_result
;
int
video_out
;
/* scan expression. Multiple expressions may be delimited with ; */
do
{
if
(
snscanf
(
buffer
,
count
,
" lcd_out : %i"
,
&
value
)
==
1
)
/* scan expression. Multiple expressions may be delimited with ;
*
* NOTE: to keep scanning simple, invalid fields are ignored
*/
while
(
remain
)
{
if
(
snscanf
(
buffer
,
remain
,
" lcd_out : %i"
,
&
value
)
==
1
)
lcd_out
=
value
&
1
;
else
if
(
snscanf
(
buffer
,
count
,
" crt_out : %i"
,
&
value
)
==
1
)
else
if
(
snscanf
(
buffer
,
remain
,
" crt_out : %i"
,
&
value
)
==
1
)
crt_out
=
value
&
1
;
else
if
(
snscanf
(
buffer
,
count
,
" tv_out : %i"
,
&
value
)
==
1
)
else
if
(
snscanf
(
buffer
,
remain
,
" tv_out : %i"
,
&
value
)
==
1
)
tv_out
=
value
&
1
;
/* advance to one character past the next ; */
do
++
buffer
;
while
((
buffer
<
buffer_end
)
&&
(
*
(
buffer
-
1
)
!=
';'
));
}
while
(
buffer
<
buffer_end
);
do
{
++
buffer
;
--
remain
;
}
while
(
remain
&&
*
(
buffer
-
1
)
!=
';'
);
}
hci_read1
(
HCI_VIDEO_OUT
,
&
video_out
,
&
hci_result
);
if
(
hci_result
==
HCI_SUCCESS
)
{
...
...
@@ -353,6 +377,8 @@ write_video(const char* buffer, unsigned long count)
* video setting if something changed. */
if
(
new_video_out
!=
video_out
)
write_acpi_int
(
METHOD_VIDEO_OUT
,
new_video_out
);
}
else
{
return
-
EFAULT
;
}
return
count
;
...
...
@@ -369,7 +395,7 @@ read_fan(char* p)
p
+=
sprintf
(
p
,
"running: %d
\n
"
,
(
value
>
0
));
p
+=
sprintf
(
p
,
"force_on: %d
\n
"
,
force_fan
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading fan status
\n
"
);
}
return
p
;
...
...
@@ -413,8 +439,9 @@ read_keys(char* p)
* some machines where system events sporadically
* become disabled. */
hci_write1
(
HCI_SYSTEM_EVENT
,
1
,
&
hci_result
);
printk
(
MY_NOTICE
"Re-enabled hotkeys
\n
"
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading hotkey status
\n
"
);
goto
end
;
}
}
...
...
@@ -465,7 +492,7 @@ ProcItem proc_items[] =
{
0
,
0
,
0
},
};
static
acpi_status
static
acpi_status
__init
add_device
(
void
)
{
struct
proc_dir_entry
*
proc
;
...
...
@@ -483,7 +510,7 @@ add_device(void)
return
(
AE_OK
);
}
static
acpi_status
static
acpi_status
__exit
remove_device
(
void
)
{
ProcItem
*
item
;
...
...
@@ -497,15 +524,19 @@ static int __init
toshiba_acpi_init
(
void
)
{
acpi_status
status
=
AE_OK
;
int
value
;
u32
hci_result
;
/* simple device detection: try reading an HCI register */
hci_read1
(
HCI_LCD_BRIGHTNESS
,
&
value
,
&
hci_result
);
if
(
hci_result
!=
HCI_SUCCESS
)
/* simple device detection: look for HCI method */
if
(
is_valid_acpi_path
(
METHOD_HCI_1
))
method_hci
=
METHOD_HCI_1
;
else
if
(
is_valid_acpi_path
(
METHOD_HCI_2
))
method_hci
=
METHOD_HCI_2
;
else
return
-
ENODEV
;
printk
(
"Toshiba Laptop ACPI Extras version %s
\n
"
,
TOSHIBA_ACPI_VERSION
);
printk
(
MY_INFO
"Toshiba Laptop ACPI Extras version %s
\n
"
,
TOSHIBA_ACPI_VERSION
);
printk
(
MY_INFO
" HCI method: %s
\n
"
,
method_hci
);
force_fan
=
0
;
key_event_valid
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment