Add code to rewrite WMI methods using EC
This commit is contained in:
parent
4569e862b4
commit
5f631c3b2f
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* ec.c - EC rewrite of WMI functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Jeremy Soller <jeremy@system76.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// EC Registers
|
||||||
|
|
||||||
|
#define FCMD 0xF8
|
||||||
|
#define FDAT 0xF9
|
||||||
|
#define FBUF 0xFA
|
||||||
|
#define FBF1 0xFB
|
||||||
|
#define FBF2 0xFC
|
||||||
|
#define FBF3 0xFD
|
||||||
|
|
||||||
|
enum KbRegion {
|
||||||
|
KB_LEFT,
|
||||||
|
KB_CENTER,
|
||||||
|
KB_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ec_kb_color_set(enum KbRegion region, u32 color) {
|
||||||
|
u8 region_code;
|
||||||
|
switch(region) {
|
||||||
|
case KB_LEFT:
|
||||||
|
region_code = 0x3;
|
||||||
|
break;
|
||||||
|
case KB_CENTER:
|
||||||
|
region_code = 0x4;
|
||||||
|
break;
|
||||||
|
case KB_RIGHT:
|
||||||
|
region_code = 0x5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ec_write(FDAT, region_code);
|
||||||
|
ec_write(FBUF, (color & 0xFF));
|
||||||
|
ec_write(FBF1, ((color >> 16) & 0xFF));
|
||||||
|
ec_write(FBF2, ((color >> 8) & 0xFF));
|
||||||
|
ec_write(FCMD, 0xCA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ec_init(void) {
|
||||||
|
ec_kb_color_set(KB_LEFT, 0xFF0000);
|
||||||
|
ec_kb_color_set(KB_CENTER, 0xFF00);
|
||||||
|
ec_kb_color_set(KB_RIGHT, 0xFF);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ec_exit(void) {
|
||||||
|
}
|
||||||
26
led.c
26
led.c
|
|
@ -26,8 +26,7 @@ static struct _led_work {
|
||||||
int wk;
|
int wk;
|
||||||
} led_work;
|
} led_work;
|
||||||
|
|
||||||
static void airplane_led_update(struct work_struct *work)
|
static void airplane_led_update(struct work_struct *work) {
|
||||||
{
|
|
||||||
u8 byte;
|
u8 byte;
|
||||||
struct _led_work *w;
|
struct _led_work *w;
|
||||||
|
|
||||||
|
|
@ -40,8 +39,7 @@ static void airplane_led_update(struct work_struct *work)
|
||||||
/* wmbb 0x6C 1 (?) */
|
/* wmbb 0x6C 1 (?) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum led_brightness airplane_led_get(struct led_classdev *led_cdev)
|
static enum led_brightness airplane_led_get(struct led_classdev *led_cdev) {
|
||||||
{
|
|
||||||
u8 byte;
|
u8 byte;
|
||||||
|
|
||||||
ec_read(0xD9, &byte);
|
ec_read(0xD9, &byte);
|
||||||
|
|
@ -50,10 +48,7 @@ static enum led_brightness airplane_led_get(struct led_classdev *led_cdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must not sleep */
|
/* must not sleep */
|
||||||
static void airplane_led_set(struct led_classdev *led_cdev,
|
static void airplane_led_set(struct led_classdev *led_cdev, enum led_brightness value) {
|
||||||
enum led_brightness value)
|
|
||||||
{
|
|
||||||
S76_INFO("Set airplane LED to %X", value);
|
|
||||||
led_work.wk = value;
|
led_work.wk = value;
|
||||||
queue_work(led_workqueue, &led_work.work);
|
queue_work(led_workqueue, &led_work.work);
|
||||||
}
|
}
|
||||||
|
|
@ -66,20 +61,20 @@ static struct led_classdev airplane_led = {
|
||||||
.default_trigger = "rfkill-any"
|
.default_trigger = "rfkill-any"
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init s76_led_init(void)
|
static int __init s76_led_init(void) {
|
||||||
{
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
led_workqueue = create_singlethread_workqueue("led_workqueue");
|
led_workqueue = create_singlethread_workqueue("led_workqueue");
|
||||||
if (unlikely(!led_workqueue))
|
if (unlikely(!led_workqueue)) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
INIT_WORK(&led_work.work, airplane_led_update);
|
INIT_WORK(&led_work.work, airplane_led_update);
|
||||||
|
|
||||||
err = led_classdev_register(&s76_platform_device->dev,
|
err = led_classdev_register(&s76_platform_device->dev, &airplane_led);
|
||||||
&airplane_led);
|
if (unlikely(err)) {
|
||||||
if (unlikely(err))
|
|
||||||
goto err_destroy_workqueue;
|
goto err_destroy_workqueue;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -90,8 +85,7 @@ err_destroy_workqueue:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit s76_led_exit(void)
|
static void __exit s76_led_exit(void) {
|
||||||
{
|
|
||||||
if (!IS_ERR_OR_NULL(airplane_led.dev))
|
if (!IS_ERR_OR_NULL(airplane_led.dev))
|
||||||
led_classdev_unregister(&airplane_led);
|
led_classdev_unregister(&airplane_led);
|
||||||
if (led_workqueue)
|
if (led_workqueue)
|
||||||
|
|
|
||||||
18
system76.c
18
system76.c
|
|
@ -89,6 +89,7 @@ static int s76_wmbb(u32 method_id, u32 arg, u32 *retval) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "ec.c"
|
||||||
#include "led.c"
|
#include "led.c"
|
||||||
#include "input.c"
|
#include "input.c"
|
||||||
#include "kb.c"
|
#include "kb.c"
|
||||||
|
|
@ -124,6 +125,9 @@ static int s76_probe(struct platform_device *dev) {
|
||||||
S76_ERROR("Could not register WMI notify handler (%0#6x)\n", status);
|
S76_ERROR("Could not register WMI notify handler (%0#6x)\n", status);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable hotkey support
|
||||||
|
s76_wmbb(0x46, 0, NULL);
|
||||||
|
|
||||||
if (kb_backlight.ops) {
|
if (kb_backlight.ops) {
|
||||||
kb_backlight.ops->init();
|
kb_backlight.ops->init();
|
||||||
|
|
@ -139,6 +143,9 @@ static int s76_remove(struct platform_device *dev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s76_resume(struct platform_device *dev) {
|
static int s76_resume(struct platform_device *dev) {
|
||||||
|
// Enable hotkey support
|
||||||
|
s76_wmbb(0x46, 0, NULL);
|
||||||
|
|
||||||
if (kb_backlight.ops && kb_backlight.state == KB_STATE_ON) {
|
if (kb_backlight.ops && kb_backlight.state == KB_STATE_ON) {
|
||||||
kb_backlight.ops->set_mode(kb_backlight.mode);
|
kb_backlight.ops->set_mode(kb_backlight.mode);
|
||||||
}
|
}
|
||||||
|
|
@ -173,8 +180,8 @@ static int __init s76_dmi_matched(const struct dmi_system_id *id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dmi_system_id s76_dmi_table[] __initdata = {
|
static struct dmi_system_id s76_dmi_table[] __initdata = {
|
||||||
DMI_TABLE("bonw13", NULL),
|
DMI_TABLE("bonw13", &kb_full_color_with_extra_ops),
|
||||||
DMI_TABLE("oryp3-b", NULL),
|
DMI_TABLE("oryp3-b", &kb_full_color_ops),
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -240,10 +247,17 @@ static int __init s76_init(void) {
|
||||||
s76_hwmon_init(&s76_platform_device->dev);
|
s76_hwmon_init(&s76_platform_device->dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
err = ec_init();
|
||||||
|
if (unlikely(err)) {
|
||||||
|
S76_ERROR("Could not register EC device\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit s76_exit(void) {
|
static void __exit s76_exit(void) {
|
||||||
|
ec_exit();
|
||||||
|
|
||||||
#ifdef S76_HAS_HWMON
|
#ifdef S76_HAS_HWMON
|
||||||
s76_hwmon_fini(&s76_platform_device->dev);
|
s76_hwmon_fini(&s76_platform_device->dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue