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
Kirill Smelkov
linux
Commits
2984397a
Commit
2984397a
authored
Jan 20, 2010
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'eeepc-laptop' into release
parents
b07f07e0
4194e2f5
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
164 additions
and
135 deletions
+164
-135
drivers/platform/x86/Kconfig
drivers/platform/x86/Kconfig
+1
-0
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-laptop.c
+163
-135
No files found.
drivers/platform/x86/Kconfig
View file @
2984397a
...
...
@@ -364,6 +364,7 @@ config EEEPC_LAPTOP
select HWMON
select LEDS_CLASS
select NEW_LEDS
select INPUT_SPARSEKMAP
---help---
This driver supports the Fn-Fx keys on Eee PC laptops.
...
...
drivers/platform/x86/eeepc-laptop.c
View file @
2984397a
...
...
@@ -31,10 +31,12 @@
#include <acpi/acpi_bus.h>
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/rfkill.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/leds.h>
#include <linux/dmi.h>
#define EEEPC_LAPTOP_VERSION "0.1"
#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
...
...
@@ -48,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper");
MODULE_DESCRIPTION
(
EEEPC_LAPTOP_NAME
);
MODULE_LICENSE
(
"GPL"
);
static
bool
hotplug_disabled
;
module_param
(
hotplug_disabled
,
bool
,
0644
);
MODULE_PARM_DESC
(
hotplug_disabled
,
"Disable hotplug for wireless device. "
"If your laptop need that, please report to "
"acpi4asus-user@lists.sourceforge.net."
);
/*
* Definitions for Asus EeePC
*/
...
...
@@ -120,38 +130,28 @@ static const char *cm_setv[] = {
NULL
,
NULL
,
"PBPS"
,
"TPDS"
};
struct
key_entry
{
char
type
;
u8
code
;
u16
keycode
;
};
enum
{
KE_KEY
,
KE_END
};
static
const
struct
key_entry
eeepc_keymap
[]
=
{
/* Sleep already handled via generic ACPI code */
{
KE_KEY
,
0x10
,
KEY_WLAN
},
{
KE_KEY
,
0x11
,
KEY_WLAN
},
{
KE_KEY
,
0x12
,
KEY_PROG1
},
{
KE_KEY
,
0x13
,
KEY_MUTE
},
{
KE_KEY
,
0x14
,
KEY_VOLUMEDOWN
},
{
KE_KEY
,
0x15
,
KEY_VOLUMEUP
},
{
KE_KEY
,
0x16
,
KEY_DISPLAY_OFF
},
{
KE_KEY
,
0x1a
,
KEY_COFFEE
},
{
KE_KEY
,
0x1b
,
KEY_ZOOM
},
{
KE_KEY
,
0x1c
,
KEY_PROG2
},
{
KE_KEY
,
0x1d
,
KEY_PROG3
},
{
KE_KEY
,
NOTIFY_BRN_MIN
,
KEY_BRIGHTNESSDOWN
},
{
KE_KEY
,
NOTIFY_BRN_MAX
,
KEY_BRIGHTNESSUP
},
{
KE_KEY
,
0x30
,
KEY_SWITCHVIDEOMODE
},
{
KE_KEY
,
0x31
,
KEY_SWITCHVIDEOMODE
},
{
KE_KEY
,
0x32
,
KEY_SWITCHVIDEOMODE
},
{
KE_KEY
,
0x37
,
KEY_F13
},
/* Disable Touchpad */
{
KE_KEY
,
0x38
,
KEY_F14
},
{
KE_END
,
0
},
{
KE_KEY
,
0x10
,
{
KEY_WLAN
}
},
{
KE_KEY
,
0x11
,
{
KEY_WLAN
}
},
{
KE_KEY
,
0x12
,
{
KEY_PROG1
}
},
{
KE_KEY
,
0x13
,
{
KEY_MUTE
}
},
{
KE_KEY
,
0x14
,
{
KEY_VOLUMEDOWN
}
},
{
KE_KEY
,
0x15
,
{
KEY_VOLUMEUP
}
},
{
KE_KEY
,
0x16
,
{
KEY_DISPLAY_OFF
}
},
{
KE_KEY
,
0x1a
,
{
KEY_COFFEE
}
},
{
KE_KEY
,
0x1b
,
{
KEY_ZOOM
}
},
{
KE_KEY
,
0x1c
,
{
KEY_PROG2
}
},
{
KE_KEY
,
0x1d
,
{
KEY_PROG3
}
},
{
KE_KEY
,
NOTIFY_BRN_MIN
,
{
KEY_BRIGHTNESSDOWN
}
},
{
KE_KEY
,
NOTIFY_BRN_MAX
,
{
KEY_BRIGHTNESSUP
}
},
{
KE_KEY
,
0x30
,
{
KEY_SWITCHVIDEOMODE
}
},
{
KE_KEY
,
0x31
,
{
KEY_SWITCHVIDEOMODE
}
},
{
KE_KEY
,
0x32
,
{
KEY_SWITCHVIDEOMODE
}
},
{
KE_KEY
,
0x37
,
{
KEY_F13
}
},
/* Disable Touchpad */
{
KE_KEY
,
0x38
,
{
KEY_F14
}
},
{
KE_END
,
0
},
};
/*
* This is the main structure, we can use it to store useful information
*/
...
...
@@ -159,6 +159,8 @@ struct eeepc_laptop {
acpi_handle
handle
;
/* the handle of the acpi device */
u32
cm_supported
;
/* the control methods supported
by this BIOS */
bool
cpufv_disabled
;
bool
hotplug_disabled
;
u16
event_count
[
128
];
/* count for each event */
struct
platform_device
*
platform_device
;
...
...
@@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev,
struct
eeepc_cpufv
c
;
int
rv
,
value
;
if
(
eeepc
->
cpufv_disabled
)
return
-
EPERM
;
if
(
get_cpufv
(
eeepc
,
&
c
))
return
-
ENODEV
;
rv
=
parse_arg
(
buf
,
count
,
&
value
);
...
...
@@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev,
return
rv
;
}
static
ssize_t
show_cpufv_disabled
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
eeepc_laptop
*
eeepc
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
eeepc
->
cpufv_disabled
);
}
static
ssize_t
store_cpufv_disabled
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
eeepc_laptop
*
eeepc
=
dev_get_drvdata
(
dev
);
int
rv
,
value
;
rv
=
parse_arg
(
buf
,
count
,
&
value
);
if
(
rv
<
0
)
return
rv
;
switch
(
value
)
{
case
0
:
if
(
eeepc
->
cpufv_disabled
)
pr_warning
(
"cpufv enabled (not officially supported "
"on this model)
\n
"
);
eeepc
->
cpufv_disabled
=
false
;
return
rv
;
case
1
:
return
-
EPERM
;
default:
return
-
EINVAL
;
}
}
static
struct
device_attribute
dev_attr_cpufv
=
{
.
attr
=
{
.
name
=
"cpufv"
,
...
...
@@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = {
.
show
=
show_available_cpufv
};
static
struct
device_attribute
dev_attr_cpufv_disabled
=
{
.
attr
=
{
.
name
=
"cpufv_disabled"
,
.
mode
=
0644
},
.
show
=
show_cpufv_disabled
,
.
store
=
store_cpufv_disabled
};
static
struct
attribute
*
platform_attributes
[]
=
{
&
dev_attr_camera
.
attr
,
&
dev_attr_cardr
.
attr
,
&
dev_attr_disp
.
attr
,
&
dev_attr_cpufv
.
attr
,
&
dev_attr_available_cpufv
.
attr
,
&
dev_attr_cpufv_disabled
.
attr
,
NULL
};
...
...
@@ -796,6 +845,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
if
(
result
&&
result
!=
-
ENODEV
)
goto
exit
;
if
(
eeepc
->
hotplug_disabled
)
return
0
;
result
=
eeepc_setup_pci_hotplug
(
eeepc
);
/*
* If we get -EBUSY then something else is handling the PCI hotplug -
...
...
@@ -1090,120 +1142,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
/*
* Input device (i.e. hotkeys)
*/
static
struct
key_entry
*
eeepc_get_entry_by_scancode
(
struct
eeepc_laptop
*
eeepc
,
int
code
)
static
int
eeepc_input_init
(
struct
eeepc_laptop
*
eeepc
)
{
struct
key_entry
*
key
;
for
(
key
=
eeepc
->
keymap
;
key
->
type
!=
KE_END
;
key
++
)
if
(
code
==
key
->
code
)
return
key
;
struct
input_dev
*
input
;
int
error
;
return
NULL
;
}
static
void
eeepc_input_notify
(
struct
eeepc_laptop
*
eeepc
,
int
event
)
{
static
struct
key_entry
*
key
;
key
=
eeepc_get_entry_by_scancode
(
eeepc
,
event
);
if
(
key
)
{
switch
(
key
->
type
)
{
case
KE_KEY
:
input_report_key
(
eeepc
->
inputdev
,
key
->
keycode
,
1
);
input_sync
(
eeepc
->
inputdev
);
input_report_key
(
eeepc
->
inputdev
,
key
->
keycode
,
0
);
input_sync
(
eeepc
->
inputdev
);
break
;
}
input
=
input_allocate_device
();
if
(
!
input
)
{
pr_info
(
"Unable to allocate input device
\n
"
);
return
-
ENOMEM
;
}
}
static
struct
key_entry
*
eeepc_get_entry_by_keycode
(
struct
eeepc_laptop
*
eeepc
,
int
code
)
{
struct
key_entry
*
key
;
for
(
key
=
eeepc
->
keymap
;
key
->
type
!=
KE_END
;
key
++
)
if
(
code
==
key
->
keycode
&&
key
->
type
==
KE_KEY
)
return
key
;
return
NULL
;
}
static
int
eeepc_getkeycode
(
struct
input_dev
*
dev
,
int
scancode
,
int
*
keycode
)
{
struct
eeepc_laptop
*
eeepc
=
input_get_drvdata
(
dev
)
;
struct
key_entry
*
key
=
eeepc_get_entry_by_scancode
(
eeepc
,
scancode
)
;
input
->
name
=
"Asus EeePC extra buttons"
;
input
->
phys
=
EEEPC_LAPTOP_FILE
"/input0"
;
input
->
id
.
bustype
=
BUS_HOST
;
input
->
dev
.
parent
=
&
eeepc
->
platform_device
->
dev
;
if
(
key
&&
key
->
type
==
KE_KEY
)
{
*
keycode
=
key
->
keycode
;
return
0
;
error
=
sparse_keymap_setup
(
input
,
eeepc_keymap
,
NULL
);
if
(
error
)
{
pr_err
(
"Unable to setup input device keymap
\n
"
);
goto
err_free_dev
;
}
return
-
EINVAL
;
}
static
int
eeepc_setkeycode
(
struct
input_dev
*
dev
,
int
scancode
,
int
keycode
)
{
struct
eeepc_laptop
*
eeepc
=
input_get_drvdata
(
dev
);
struct
key_entry
*
key
;
int
old_keycode
;
if
(
keycode
<
0
||
keycode
>
KEY_MAX
)
return
-
EINVAL
;
key
=
eeepc_get_entry_by_scancode
(
eeepc
,
scancode
);
if
(
key
&&
key
->
type
==
KE_KEY
)
{
old_keycode
=
key
->
keycode
;
key
->
keycode
=
keycode
;
set_bit
(
keycode
,
dev
->
keybit
);
if
(
!
eeepc_get_entry_by_keycode
(
eeepc
,
old_keycode
))
clear_bit
(
old_keycode
,
dev
->
keybit
);
return
0
;
error
=
input_register_device
(
input
);
if
(
error
)
{
pr_err
(
"Unable to register input device
\n
"
);
goto
err_free_keymap
;
}
return
-
EINVAL
;
}
static
int
eeepc_input_init
(
struct
eeepc_laptop
*
eeepc
)
{
const
struct
key_entry
*
key
;
int
result
;
eeepc
->
inputdev
=
input_allocate_device
();
if
(
!
eeepc
->
inputdev
)
{
pr_info
(
"Unable to allocate input device
\n
"
);
return
-
ENOMEM
;
}
eeepc
->
inputdev
->
name
=
"Asus EeePC extra buttons"
;
eeepc
->
inputdev
->
dev
.
parent
=
&
eeepc
->
platform_device
->
dev
;
eeepc
->
inputdev
->
phys
=
EEEPC_LAPTOP_FILE
"/input0"
;
eeepc
->
inputdev
->
id
.
bustype
=
BUS_HOST
;
eeepc
->
inputdev
->
getkeycode
=
eeepc_getkeycode
;
eeepc
->
inputdev
->
setkeycode
=
eeepc_setkeycode
;
input_set_drvdata
(
eeepc
->
inputdev
,
eeepc
);
eeepc
->
keymap
=
kmemdup
(
eeepc_keymap
,
sizeof
(
eeepc_keymap
),
GFP_KERNEL
);
for
(
key
=
eeepc_keymap
;
key
->
type
!=
KE_END
;
key
++
)
{
switch
(
key
->
type
)
{
case
KE_KEY
:
set_bit
(
EV_KEY
,
eeepc
->
inputdev
->
evbit
);
set_bit
(
key
->
keycode
,
eeepc
->
inputdev
->
keybit
);
break
;
}
}
result
=
input_register_device
(
eeepc
->
inputdev
);
if
(
result
)
{
pr_info
(
"Unable to register input device
\n
"
);
input_free_device
(
eeepc
->
inputdev
);
return
result
;
}
eeepc
->
inputdev
=
input
;
return
0
;
err_free_keymap:
sparse_keymap_free
(
input
);
err_free_dev:
input_free_device
(
input
);
return
error
;
}
static
void
eeepc_input_exit
(
struct
eeepc_laptop
*
eeepc
)
...
...
@@ -1253,11 +1227,59 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
* event will be desired value (or else ignored)
*/
}
eeepc_input_notify
(
eeepc
,
event
);
sparse_keymap_report_event
(
eeepc
->
inputdev
,
event
,
1
,
true
);
}
}
else
{
/* Everything else is a bona-fide keypress event */
eeepc_input_notify
(
eeepc
,
event
);
sparse_keymap_report_event
(
eeepc
->
inputdev
,
event
,
1
,
true
);
}
}
static
void
eeepc_dmi_check
(
struct
eeepc_laptop
*
eeepc
)
{
const
char
*
model
;
model
=
dmi_get_system_info
(
DMI_PRODUCT_NAME
);
if
(
!
model
)
return
;
/*
* Blacklist for setting cpufv (cpu speed).
*
* EeePC 4G ("701") implements CFVS, but it is not supported
* by the pre-installed OS, and the original option to change it
* in the BIOS setup screen was removed in later versions.
*
* Judging by the lack of "Super Hybrid Engine" on Asus product pages,
* this applies to all "701" models (4G/4G Surf/2G Surf).
*
* So Asus made a deliberate decision not to support it on this model.
* We have several reports that using it can cause the system to hang
*
* The hang has also been reported on a "702" (Model name "8G"?).
*
* We avoid dmi_check_system() / dmi_match(), because they use
* substring matching. We don't want to affect the "701SD"
* and "701SDX" models, because they do support S.H.E.
*/
if
(
strcmp
(
model
,
"701"
)
==
0
||
strcmp
(
model
,
"702"
)
==
0
)
{
eeepc
->
cpufv_disabled
=
true
;
pr_info
(
"model %s does not officially support setting cpu "
"speed
\n
"
,
model
);
pr_info
(
"cpufv disabled to avoid instability
\n
"
);
}
/*
* Blacklist for wlan hotplug
*
* Eeepc 1005HA doesn't work like others models and don't need the
* hotplug code. In fact, current hotplug code seems to unplug another
* device...
*/
if
(
strcmp
(
model
,
"1005HA"
)
==
0
||
strcmp
(
model
,
"1201N"
)
==
0
)
{
eeepc
->
hotplug_disabled
=
true
;
pr_info
(
"wlan hotplug disabled
\n
"
);
}
}
...
...
@@ -1342,6 +1364,10 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
strcpy
(
acpi_device_class
(
device
),
EEEPC_ACPI_CLASS
);
device
->
driver_data
=
eeepc
;
eeepc
->
hotplug_disabled
=
hotplug_disabled
;
eeepc_dmi_check
(
eeepc
);
result
=
eeepc_acpi_init
(
eeepc
,
device
);
if
(
result
)
goto
fail_platform
;
...
...
@@ -1452,10 +1478,12 @@ static int __init eeepc_laptop_init(void)
result
=
acpi_bus_register_driver
(
&
eeepc_acpi_driver
);
if
(
result
<
0
)
goto
fail_acpi_driver
;
if
(
!
eeepc_device_present
)
{
result
=
-
ENODEV
;
goto
fail_no_device
;
}
return
0
;
fail_no_device:
...
...
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