Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
7d8c2206
Commit
7d8c2206
authored
Dec 16, 2009
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'msi-wmi' into release
parents
f02f465b
de078e57
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
306 additions
and
0 deletions
+306
-0
drivers/platform/x86/Kconfig
drivers/platform/x86/Kconfig
+12
-0
drivers/platform/x86/Makefile
drivers/platform/x86/Makefile
+1
-0
drivers/platform/x86/msi-wmi.c
drivers/platform/x86/msi-wmi.c
+293
-0
No files found.
drivers/platform/x86/Kconfig
View file @
7d8c2206
...
...
@@ -367,6 +367,18 @@ config ACPI_WMI
It is safe to enable this driver even if your DSDT doesn't define
any ACPI-WMI devices.
config MSI_WMI
tristate "MSI WMI extras"
depends on ACPI_WMI
depends on INPUT
depends on BACKLIGHT_CLASS_DEVICE
select INPUT_SPARSEKMAP
help
Say Y here if you want to support WMI-based hotkeys on MSI laptops.
To compile this driver as a module, choose M here: the module will
be called msi-wmi.
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
depends on ACPI
...
...
drivers/platform/x86/Makefile
View file @
7d8c2206
...
...
@@ -18,6 +18,7 @@ obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_PANASONIC_LAPTOP)
+=
panasonic-laptop.o
obj-$(CONFIG_INTEL_MENLOW)
+=
intel_menlow.o
obj-$(CONFIG_ACPI_WMI)
+=
wmi.o
obj-$(CONFIG_MSI_WMI)
+=
msi-wmi.o
obj-$(CONFIG_ACPI_ASUS)
+=
asus_acpi.o
obj-$(CONFIG_TOPSTAR_LAPTOP)
+=
topstar-laptop.o
obj-$(CONFIG_ACPI_TOSHIBA)
+=
toshiba_acpi.o
drivers/platform/x86/msi-wmi.c
0 → 100644
View file @
7d8c2206
/*
* MSI WMI hotkeys
*
* Copyright (C) 2009 Novell <trenn@suse.de>
*
* Most stuff taken over from hp-wmi
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/acpi.h>
#include <linux/backlight.h>
MODULE_AUTHOR
(
"Thomas Renninger <trenn@suse.de>"
);
MODULE_DESCRIPTION
(
"MSI laptop WMI hotkeys driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
);
MODULE_ALIAS
(
"wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
);
/* Temporary workaround until the WMI sysfs interface goes in
{ "svn", DMI_SYS_VENDOR },
{ "pn", DMI_PRODUCT_NAME },
{ "pvr", DMI_PRODUCT_VERSION },
{ "rvn", DMI_BOARD_VENDOR },
{ "rn", DMI_BOARD_NAME },
*/
MODULE_ALIAS
(
"dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*"
);
#define DRV_NAME "msi-wmi"
#define DRV_PFX DRV_NAME ": "
#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
#define dprintk(msg...) pr_debug(DRV_PFX msg)
#define KEYCODE_BASE 0xD0
#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE
#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2)
#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3)
static
struct
key_entry
msi_wmi_keymap
[]
=
{
{
KE_KEY
,
MSI_WMI_BRIGHTNESSUP
,
{
KEY_BRIGHTNESSUP
}
},
{
KE_KEY
,
MSI_WMI_BRIGHTNESSDOWN
,
{
KEY_BRIGHTNESSDOWN
}
},
{
KE_KEY
,
MSI_WMI_VOLUMEUP
,
{
KEY_VOLUMEUP
}
},
{
KE_KEY
,
MSI_WMI_VOLUMEDOWN
,
{
KEY_VOLUMEDOWN
}
},
{
KE_END
,
0
}
};
static
ktime_t
last_pressed
[
ARRAY_SIZE
(
msi_wmi_keymap
)
-
1
];
struct
backlight_device
*
backlight
;
static
int
backlight_map
[]
=
{
0x00
,
0x33
,
0x66
,
0x99
,
0xCC
,
0xFF
};
static
struct
input_dev
*
msi_wmi_input_dev
;
static
int
msi_wmi_query_block
(
int
instance
,
int
*
ret
)
{
acpi_status
status
;
union
acpi_object
*
obj
;
struct
acpi_buffer
output
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
status
=
wmi_query_block
(
MSIWMI_BIOS_GUID
,
instance
,
&
output
);
obj
=
output
.
pointer
;
if
(
!
obj
||
obj
->
type
!=
ACPI_TYPE_INTEGER
)
{
if
(
obj
)
{
printk
(
KERN_ERR
DRV_PFX
"query block returned object "
"type: %d - buffer length:%d
\n
"
,
obj
->
type
,
obj
->
type
==
ACPI_TYPE_BUFFER
?
obj
->
buffer
.
length
:
0
);
}
kfree
(
obj
);
return
-
EINVAL
;
}
*
ret
=
obj
->
integer
.
value
;
kfree
(
obj
);
return
0
;
}
static
int
msi_wmi_set_block
(
int
instance
,
int
value
)
{
acpi_status
status
;
struct
acpi_buffer
input
=
{
sizeof
(
int
),
&
value
};
dprintk
(
"Going to set block of instance: %d - value: %d
\n
"
,
instance
,
value
);
status
=
wmi_set_block
(
MSIWMI_BIOS_GUID
,
instance
,
&
input
);
return
ACPI_SUCCESS
(
status
)
?
0
:
1
;
}
static
int
bl_get
(
struct
backlight_device
*
bd
)
{
int
level
,
err
,
ret
;
/* Instance 1 is "get backlight", cmp with DSDT */
err
=
msi_wmi_query_block
(
1
,
&
ret
);
if
(
err
)
{
printk
(
KERN_ERR
DRV_PFX
"Could not query backlight: %d
\n
"
,
err
);
return
-
EINVAL
;
}
dprintk
(
"Get: Query block returned: %d
\n
"
,
ret
);
for
(
level
=
0
;
level
<
ARRAY_SIZE
(
backlight_map
);
level
++
)
{
if
(
backlight_map
[
level
]
==
ret
)
{
dprintk
(
"Current backlight level: 0x%X - index: %d
\n
"
,
backlight_map
[
level
],
level
);
break
;
}
}
if
(
level
==
ARRAY_SIZE
(
backlight_map
))
{
printk
(
KERN_ERR
DRV_PFX
"get: Invalid brightness value: 0x%X
\n
"
,
ret
);
return
-
EINVAL
;
}
return
level
;
}
static
int
bl_set_status
(
struct
backlight_device
*
bd
)
{
int
bright
=
bd
->
props
.
brightness
;
if
(
bright
>=
ARRAY_SIZE
(
backlight_map
)
||
bright
<
0
)
return
-
EINVAL
;
/* Instance 0 is "set backlight" */
return
msi_wmi_set_block
(
0
,
backlight_map
[
bright
]);
}
static
struct
backlight_ops
msi_backlight_ops
=
{
.
get_brightness
=
bl_get
,
.
update_status
=
bl_set_status
,
};
static
void
msi_wmi_notify
(
u32
value
,
void
*
context
)
{
struct
acpi_buffer
response
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
static
struct
key_entry
*
key
;
union
acpi_object
*
obj
;
ktime_t
cur
;
wmi_get_event_data
(
value
,
&
response
);
obj
=
(
union
acpi_object
*
)
response
.
pointer
;
if
(
obj
&&
obj
->
type
==
ACPI_TYPE_INTEGER
)
{
int
eventcode
=
obj
->
integer
.
value
;
dprintk
(
"Eventcode: 0x%x
\n
"
,
eventcode
);
key
=
sparse_keymap_entry_from_scancode
(
msi_wmi_input_dev
,
eventcode
);
if
(
key
)
{
ktime_t
diff
;
cur
=
ktime_get_real
();
diff
=
ktime_sub
(
cur
,
last_pressed
[
key
->
code
-
KEYCODE_BASE
]);
/* Ignore event if the same event happened in a 50 ms
timeframe -> Key press may result in 10-20 GPEs */
if
(
ktime_to_us
(
diff
)
<
1000
*
50
)
{
dprintk
(
"Suppressed key event 0x%X - "
"Last press was %lld us ago
\n
"
,
key
->
code
,
ktime_to_us
(
diff
));
return
;
}
last_pressed
[
key
->
code
-
KEYCODE_BASE
]
=
cur
;
if
(
key
->
type
==
KE_KEY
&&
/* Brightness is served via acpi video driver */
(
!
acpi_video_backlight_support
()
||
(
key
->
code
!=
MSI_WMI_BRIGHTNESSUP
&&
key
->
code
!=
MSI_WMI_BRIGHTNESSDOWN
)))
{
dprintk
(
"Send key: 0x%X - "
"Input layer keycode: %d
\n
"
,
key
->
code
,
key
->
keycode
);
sparse_keymap_report_entry
(
msi_wmi_input_dev
,
key
,
1
,
true
);
}
}
else
printk
(
KERN_INFO
"Unknown key pressed - %x
\n
"
,
eventcode
);
}
else
printk
(
KERN_INFO
DRV_PFX
"Unknown event received
\n
"
);
kfree
(
response
.
pointer
);
}
static
int
__init
msi_wmi_input_setup
(
void
)
{
int
err
;
msi_wmi_input_dev
=
input_allocate_device
();
if
(
!
msi_wmi_input_dev
)
return
-
ENOMEM
;
msi_wmi_input_dev
->
name
=
"MSI WMI hotkeys"
;
msi_wmi_input_dev
->
phys
=
"wmi/input0"
;
msi_wmi_input_dev
->
id
.
bustype
=
BUS_HOST
;
err
=
sparse_keymap_setup
(
msi_wmi_input_dev
,
msi_wmi_keymap
,
NULL
);
if
(
err
)
goto
err_free_dev
;
err
=
input_register_device
(
msi_wmi_input_dev
);
if
(
err
)
goto
err_free_keymap
;
memset
(
last_pressed
,
0
,
sizeof
(
last_pressed
));
return
0
;
err_free_keymap:
sparse_keymap_free
(
msi_wmi_input_dev
);
err_free_dev:
input_free_device
(
msi_wmi_input_dev
);
return
err
;
}
static
int
__init
msi_wmi_init
(
void
)
{
int
err
;
if
(
!
wmi_has_guid
(
MSIWMI_EVENT_GUID
))
{
printk
(
KERN_ERR
"This machine doesn't have MSI-hotkeys through WMI
\n
"
);
return
-
ENODEV
;
}
err
=
wmi_install_notify_handler
(
MSIWMI_EVENT_GUID
,
msi_wmi_notify
,
NULL
);
if
(
err
)
return
-
EINVAL
;
err
=
msi_wmi_input_setup
();
if
(
err
)
goto
err_uninstall_notifier
;
if
(
!
acpi_video_backlight_support
())
{
backlight
=
backlight_device_register
(
DRV_NAME
,
NULL
,
NULL
,
&
msi_backlight_ops
);
if
(
IS_ERR
(
backlight
))
goto
err_free_input
;
backlight
->
props
.
max_brightness
=
ARRAY_SIZE
(
backlight_map
)
-
1
;
err
=
bl_get
(
NULL
);
if
(
err
<
0
)
goto
err_free_backlight
;
backlight
->
props
.
brightness
=
err
;
}
dprintk
(
"Event handler installed
\n
"
);
return
0
;
err_free_backlight:
backlight_device_unregister
(
backlight
);
err_free_input:
input_unregister_device
(
msi_wmi_input_dev
);
err_uninstall_notifier:
wmi_remove_notify_handler
(
MSIWMI_EVENT_GUID
);
return
err
;
}
static
void
__exit
msi_wmi_exit
(
void
)
{
if
(
wmi_has_guid
(
MSIWMI_EVENT_GUID
))
{
wmi_remove_notify_handler
(
MSIWMI_EVENT_GUID
);
sparse_keymap_free
(
msi_wmi_input_dev
);
input_unregister_device
(
msi_wmi_input_dev
);
backlight_device_unregister
(
backlight
);
}
}
module_init
(
msi_wmi_init
);
module_exit
(
msi_wmi_exit
);
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