diff --git a/ap_led.c b/ap_led.c index 769dd1c..80d9289 100644 --- a/ap_led.c +++ b/ap_led.c @@ -17,31 +17,90 @@ * along with this program. If not, see . */ +static enum led_brightness ap_led_brightness = 1; + +static bool ap_led_invert = TRUE; + static enum led_brightness ap_led_get(struct led_classdev *led_cdev) { - u8 byte; - - ec_read(0xD9, &byte); - - return byte & 0x40 ? LED_OFF : LED_FULL; + return ap_led_brightness; } static int ap_led_set(struct led_classdev *led_cdev, enum led_brightness value) { u8 byte; ec_read(0xD9, &byte); - ec_write(0xD9, value ? byte & ~0x40 : byte | 0x40); + + if (value > 0) { + ap_led_brightness = 1; + + if (ap_led_invert) { + byte &= ~0x40; + } else { + byte |= 0x40; + } + } else { + ap_led_brightness = 0; + + if (ap_led_invert) { + byte |= 0x40; + } else { + byte &= ~0x40; + } + } + + ec_write(0xD9, byte); return 0; } static struct led_classdev ap_led = { - .name = "system76::airplane", - .brightness_get = ap_led_get, - .brightness_set_blocking = ap_led_set, - .max_brightness = 1, - .default_trigger = "rfkill-any" + .name = "system76::airplane", + .brightness_get = ap_led_get, + .brightness_set_blocking = ap_led_set, + .max_brightness = 1, + .default_trigger = "rfkill-any" }; +static ssize_t ap_led_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { + return sprintf(buf, "%d\n", (int)ap_led_invert); +} + +static ssize_t ap_led_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { + unsigned int val; + int ret; + enum led_brightness brightness; + + ret = kstrtouint(buf, 0, &val); + if (ret) { + return ret; + } + + brightness = ap_led_get(&ap_led); + + if (val) { + ap_led_invert = TRUE; + } else { + ap_led_invert = FALSE; + } + + ap_led_set(&ap_led, brightness); + + return size; +} + +static struct device_attribute ap_led_invert_dev_attr = { + .attr = { + .name = "invert", + .mode = 0644, + }, + .show = ap_led_invert_show, + .store = ap_led_invert_store, +}; + +static void ap_led_resume(void) { + ap_led_set(&ap_led, ap_led_brightness); +} + static int __init ap_led_init(struct device *dev) { int err; @@ -49,11 +108,19 @@ static int __init ap_led_init(struct device *dev) { if (unlikely(err)) { return err; } + + if (device_create_file(ap_led.dev, &ap_led_invert_dev_attr) != 0) { + S76_ERROR("failed to create ap_led_invert\n"); + } + + ap_led_resume(); return 0; } static void __exit ap_led_exit(void) { + device_remove_file(ap_led.dev, &ap_led_invert_dev_attr); + if (!IS_ERR_OR_NULL(ap_led.dev)) { led_classdev_unregister(&ap_led); } diff --git a/ec.c b/ec.c deleted file mode 100644 index bbb2446..0000000 --- a/ec.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ec.c - EC rewrite of WMI functions - * - * Copyright (C) 2017 Jeremy Soller - * - * 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 . - */ - - // EC Registers - - #define FCMD 0xF8 - #define FDAT 0xF9 - #define FBUF 0xFA - #define FBF1 0xFB - #define FBF2 0xFC - #define FBF3 0xFD - -enum EcKbRegion { - EC_KB_LEFT, - EC_KB_CENTER, - EC_KB_RIGHT, - EC_KB_EXTRA, -}; - -static void ec_kb_color_set(enum EcKbRegion region, u32 color) { - u8 region_code; - switch(region) { - case EC_KB_LEFT: - region_code = 0x3; - break; - case EC_KB_CENTER: - region_code = 0x4; - break; - case EC_KB_RIGHT: - region_code = 0x5; - break; - case EC_KB_EXTRA: - region_code = 0x7; - 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) { - return 0; -} - -static void ec_exit(void) { -} diff --git a/kb.c b/kb.c deleted file mode 100644 index c9251a1..0000000 --- a/kb.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * kb.c - * - * Copyright (C) 2017 Jeremy Soller - * Copyright (C) 2014-2016 Arnoud Willemsen - * Copyright (C) 2013-2015 TUXEDO Computers GmbH - * - * 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 . - */ - -#define COLORS { \ - C(white, 0xFFFFFF), \ - C(blue, 0x0000FF), \ - C(red, 0xFF0000), \ - C(magenta, 0xFF00FF), \ - C(green, 0x00FF00), \ - C(cyan, 0x00FFFF), \ - C(yellow, 0xFFFF00), \ -} -#undef C - - -#define C(n, v) KB_COLOR_##n -enum kb_color COLORS; -#undef C - -union kb_rgb_color { - u32 rgb; - struct { u32 b:8, g:8, r:8, : 8; }; -}; - -#define C(n, v) { .name = #n, .value = { .rgb = v, }, } -struct { - const char *const name; - union kb_rgb_color value; -} kb_colors[] = COLORS; -#undef C - -#define KB_COLOR_DEFAULT KB_COLOR_white -#define KB_BRIGHTNESS_MAX 5 -#define KB_BRIGHTNESS_DEFAULT 1 - -static int param_set_kb_color(const char *val, const struct kernel_param *kp) -{ - size_t i; - - if (!val) - return -EINVAL; - - if (!val[0]) { - *((enum kb_color *) kp->arg) = KB_COLOR_DEFAULT; - return 0; - } - - for (i = 0; i < ARRAY_SIZE(kb_colors); i++) { - if (!strcmp(val, kb_colors[i].name)) { - *((enum kb_color *) kp->arg) = i; - return 0; - } - } - - return -EINVAL; -} - -static int param_get_kb_color(char *buffer, const struct kernel_param *kp) -{ - return sprintf(buffer, "%s", - kb_colors[*((enum kb_color *) kp->arg)].name); -} - -static const struct kernel_param_ops param_ops_kb_color = { - .set = param_set_kb_color, - .get = param_get_kb_color, -}; - -static enum kb_color param_kb_color[] = { [0 ... 3] = KB_COLOR_DEFAULT }; -static int param_kb_color_num; -#define param_check_kb_color(name, p) __param_check(name, p, enum kb_color) -module_param_array_named(kb_color, param_kb_color, kb_color, - ¶m_kb_color_num, S_IRUSR); -MODULE_PARM_DESC(kb_color, "Set the color(s) of the keyboard (sections)"); - -static int param_set_kb_brightness(const char *val, - const struct kernel_param *kp) -{ - int ret; - - ret = param_set_byte(val, kp); - - if (!ret && *((unsigned char *) kp->arg) > KB_BRIGHTNESS_MAX) - return -EINVAL; - - return ret; -} - -static const struct kernel_param_ops param_ops_kb_brightness = { - .set = param_set_kb_brightness, - .get = param_get_byte, -}; - -static unsigned char param_kb_brightness = KB_BRIGHTNESS_DEFAULT; -#define param_check_kb_brightness param_check_byte -module_param_named(kb_brightness, param_kb_brightness, kb_brightness, S_IRUSR); -MODULE_PARM_DESC(kb_brightness, "Set the brightness of the keyboard backlight"); - - -static bool param_kb_off = true; -module_param_named(kb_off, param_kb_off, bool, S_IRUSR); -MODULE_PARM_DESC(kb_off, "Switch keyboard backlight off"); - -static bool param_kb_cycle_colors = true; -module_param_named(kb_cycle_colors, param_kb_cycle_colors, bool, S_IRUSR); -MODULE_PARM_DESC(kb_cycle_colors, "Cycle colors rather than modes"); - -static struct { - enum kb_extra { - KB_HAS_EXTRA_TRUE, - KB_HAS_EXTRA_FALSE, - } extra; - - enum kb_state { - KB_STATE_OFF, - KB_STATE_ON, - } state; - - struct { - unsigned left; - unsigned center; - unsigned right; - unsigned extra; - } color; - - unsigned brightness; - - enum kb_mode { - KB_MODE_RANDOM_COLOR, - KB_MODE_CUSTOM, - KB_MODE_BREATHE, - KB_MODE_CYCLE, - KB_MODE_WAVE, - KB_MODE_DANCE, - KB_MODE_TEMPO, - KB_MODE_FLASH, - } mode; - - struct kb_backlight_ops { - void (*set_state)(enum kb_state state); - void (*set_color)(unsigned left, unsigned center, - unsigned right, unsigned extra); - void (*set_brightness)(unsigned brightness); - void (*set_mode)(enum kb_mode); - void (*init)(void); - } *ops; - -} kb_backlight = { .ops = NULL, }; - - -static void kb_dec_brightness(void) -{ - if (kb_backlight.state == KB_STATE_OFF) - return; - if (kb_backlight.brightness == 0) - return; - - S76_DEBUG(); - - kb_backlight.ops->set_brightness(kb_backlight.brightness - 1); -} - -static void kb_inc_brightness(void) -{ - if (kb_backlight.state == KB_STATE_OFF) - return; - - S76_DEBUG(); - - kb_backlight.ops->set_brightness(kb_backlight.brightness + 1); -} - -static void kb_toggle_state(void) -{ - switch (kb_backlight.state) { - case KB_STATE_OFF: - kb_backlight.ops->set_state(KB_STATE_ON); - break; - case KB_STATE_ON: - kb_backlight.ops->set_state(KB_STATE_OFF); - break; - default: - BUG(); - } -} - -static void kb_next_mode(void) -{ - static enum kb_mode modes[] = { - KB_MODE_RANDOM_COLOR, - KB_MODE_DANCE, - KB_MODE_TEMPO, - KB_MODE_FLASH, - KB_MODE_WAVE, - KB_MODE_BREATHE, - KB_MODE_CYCLE, - KB_MODE_CUSTOM, - }; - - size_t i; - - if (kb_backlight.state == KB_STATE_OFF) - return; - - for (i = 0; i < ARRAY_SIZE(modes); i++) { - if (modes[i] == kb_backlight.mode) - break; - } - - BUG_ON(i == ARRAY_SIZE(modes)); - - kb_backlight.ops->set_mode(modes[(i + 1) % ARRAY_SIZE(modes)]); -} - -static void kb_next_color(void) -{ - size_t i; - unsigned int nc; - - if (kb_backlight.state == KB_STATE_OFF) - return; - - for (i = 0; i < ARRAY_SIZE(kb_colors); i++) { - if (i == kb_backlight.color.left) - break; - } - - if (i + 1 >= ARRAY_SIZE(kb_colors)) - nc = 0; - else - nc = i + 1; - - kb_backlight.ops->set_color(nc, nc, nc, nc); -} - -/* full color backlight keyboard */ - -static void kb_full_color__set_color(unsigned left, unsigned center, - unsigned right, unsigned extra) -{ - u32 cmd; - - S76_INFO( - "Left: %s (%X), Center: %s (%X), Right: %s (%X), Extra: %s (%X)\n", - kb_colors[left].name, (unsigned int)kb_colors[left].value.rgb, - kb_colors[center].name, (unsigned int)kb_colors[center].value.rgb, - kb_colors[right].name, (unsigned int)kb_colors[right].value.rgb, - kb_colors[extra].name, (unsigned int)kb_colors[extra].value.rgb - ); - - ec_kb_color_set(EC_KB_LEFT, kb_colors[left].value.rgb); - kb_backlight.color.left = left; - - ec_kb_color_set(EC_KB_CENTER, kb_colors[center].value.rgb); - kb_backlight.color.center = center; - - ec_kb_color_set(EC_KB_RIGHT, kb_colors[right].value.rgb); - kb_backlight.color.right = right; - - if (kb_backlight.extra == KB_HAS_EXTRA_TRUE) { - ec_kb_color_set(EC_KB_EXTRA, kb_colors[extra].value.rgb); - kb_backlight.color.extra = extra; - } - - kb_backlight.mode = KB_MODE_CUSTOM; -} - -static void kb_full_color__set_brightness(unsigned i) -{ - u8 lvl; - u8 lvl_to_raw[] = { 48, 72, 96, 144, 192, 255 }; - - i = clamp_t(unsigned, i, 0, ARRAY_SIZE(lvl_to_raw) - 1); - - lvl = lvl_to_raw[i]; - - kb_led_set(&kb_led, lvl); - led_classdev_notify_brightness_hw_changed(&kb_led, lvl); - kb_backlight.brightness = i; -} - -static void kb_full_color__set_mode(unsigned mode) -{ - static u32 cmds[] = { - [KB_MODE_BREATHE] = 0x1002a000, - [KB_MODE_CUSTOM] = 0, - [KB_MODE_CYCLE] = 0x33010000, - [KB_MODE_DANCE] = 0x80000000, - [KB_MODE_FLASH] = 0xA0000000, - [KB_MODE_RANDOM_COLOR] = 0x70000000, - [KB_MODE_TEMPO] = 0x90000000, - [KB_MODE_WAVE] = 0xB0000000, - }; - - BUG_ON(mode >= ARRAY_SIZE(cmds)); - - s76_wmbb(SET_KB_LED, 0x10000000, NULL); - - if (mode == KB_MODE_CUSTOM) { - kb_full_color__set_color(kb_backlight.color.left, - kb_backlight.color.center, - kb_backlight.color.right, - kb_backlight.color.extra); - kb_full_color__set_brightness(kb_backlight.brightness); - return; - } - - if (!s76_wmbb(SET_KB_LED, cmds[mode], NULL)) - kb_backlight.mode = mode; -} - -static void kb_full_color__set_state(enum kb_state state) -{ - u32 cmd = 0xE0000000; - - S76_DEBUG("State: %d\n", state); - - switch (state) { - case KB_STATE_OFF: - led_classdev_notify_brightness_hw_changed(&kb_led, 0); - - cmd |= 0x003001; - break; - case KB_STATE_ON: - kb_full_color__set_brightness(kb_backlight.brightness); - - cmd |= 0x07F001; - break; - default: - BUG(); - } - - if (!s76_wmbb(SET_KB_LED, cmd, NULL)) - kb_backlight.state = state; -} - -static void kb_full_color__init(void) -{ - S76_DEBUG(); - - kb_backlight.extra = KB_HAS_EXTRA_FALSE; - - kb_full_color__set_state(param_kb_off ? KB_STATE_OFF : KB_STATE_ON); - kb_full_color__set_color(param_kb_color[0], param_kb_color[1], - param_kb_color[2], param_kb_color[3]); - kb_full_color__set_brightness(param_kb_brightness); -} - -static struct kb_backlight_ops kb_full_color_ops = { - .set_state = kb_full_color__set_state, - .set_color = kb_full_color__set_color, - .set_brightness = kb_full_color__set_brightness, - .set_mode = kb_full_color__set_mode, - .init = kb_full_color__init, -}; - -static void kb_full_color__init_extra(void) -{ - S76_DEBUG(); - - kb_backlight.extra = KB_HAS_EXTRA_TRUE; - - kb_full_color__set_state(param_kb_off ? KB_STATE_OFF : KB_STATE_ON); - kb_full_color__set_color(param_kb_color[0], param_kb_color[1], - param_kb_color[2], param_kb_color[3]); - kb_full_color__set_brightness(param_kb_brightness); -} - -static struct kb_backlight_ops kb_full_color_with_extra_ops = { - .set_state = kb_full_color__set_state, - .set_color = kb_full_color__set_color, - .set_brightness = kb_full_color__set_brightness, - .set_mode = kb_full_color__set_mode, - .init = kb_full_color__init_extra, -}; - -static void kb_wmi(u32 event) { - if (!kb_backlight.ops) - return; - - switch (event) { - case 0x81: - kb_dec_brightness(); - break; - case 0x82: - kb_inc_brightness(); - break; - case 0x83: - if (!param_kb_cycle_colors) - kb_next_mode(); - else - kb_next_color(); - break; - case 0x9F: - kb_toggle_state(); - break; - } -} - -/* Sysfs interface */ - -static ssize_t s76_brightness_show(struct device *child, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", kb_backlight.brightness); -} - -static ssize_t s76_brightness_store(struct device *child, - struct device_attribute *attr, const char *buf, size_t size) -{ - unsigned int val; - int ret; - - if (!kb_backlight.ops) - return -EINVAL; - - ret = kstrtouint(buf, 0, &val); - if (ret) - return ret; - - kb_backlight.ops->set_brightness(val); - - return ret ? : size; -} - -static DEVICE_ATTR(kb_brightness, 0644, - s76_brightness_show, s76_brightness_store); - -static ssize_t s76_state_show(struct device *child, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", kb_backlight.state); -} - -static ssize_t s76_state_store(struct device *child, - struct device_attribute *attr, const char *buf, size_t size) -{ - unsigned int val; - int ret; - - if (!kb_backlight.ops) - return -EINVAL; - - ret = kstrtouint(buf, 0, &val); - if (ret) - return ret; - - val = clamp_t(unsigned, val, 0, 1); - kb_backlight.ops->set_state(val); - - return ret ? : size; -} - -static DEVICE_ATTR(kb_state, 0644, - s76_state_show, s76_state_store); - -static ssize_t s76_mode_show(struct device *child, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", kb_backlight.mode); -} - -static ssize_t s76_mode_store(struct device *child, - struct device_attribute *attr, const char *buf, size_t size) -{ - static enum kb_mode modes[] = { - KB_MODE_RANDOM_COLOR, - KB_MODE_CUSTOM, - KB_MODE_BREATHE, - KB_MODE_CYCLE, - KB_MODE_WAVE, - KB_MODE_DANCE, - KB_MODE_TEMPO, - KB_MODE_FLASH, - }; - - unsigned int val; - int ret; - - if (!kb_backlight.ops) - return -EINVAL; - - ret = kstrtouint(buf, 0, &val); - if (ret) - return ret; - - val = clamp_t(unsigned, val, 0, 7); - kb_backlight.ops->set_mode(modes[val]); - - return ret ? : size; -} - -static DEVICE_ATTR(kb_mode, 0644, - s76_mode_show, s76_mode_store); - -static ssize_t s76_color_show(struct device *child, - struct device_attribute *attr, char *buf) -{ - if (kb_backlight.extra == KB_HAS_EXTRA_TRUE) - return sprintf(buf, "%s %s %s %s\n", - kb_colors[kb_backlight.color.left].name, - kb_colors[kb_backlight.color.center].name, - kb_colors[kb_backlight.color.right].name, - kb_colors[kb_backlight.color.extra].name); - else - return sprintf(buf, "%s %s %s\n", - kb_colors[kb_backlight.color.left].name, - kb_colors[kb_backlight.color.center].name, - kb_colors[kb_backlight.color.right].name); -} - -static ssize_t s76_color_store(struct device *child, - struct device_attribute *attr, const char *buf, size_t size) -{ - unsigned int i, j; - unsigned int val[4] = {0}; - char left[8]; - char right[8]; - char center[8]; - char extra[8]; - - if (!kb_backlight.ops) - return -EINVAL; - - i = sscanf(buf, "%7s %7s %7s %7s", left, center, right, extra); - - if (i == 1) { - for (j = 0; j < ARRAY_SIZE(kb_colors); j++) { - if (!strcmp(left, kb_colors[j].name)) - val[0] = j; - } - val[0] = clamp_t(unsigned, val[0], 0, ARRAY_SIZE(kb_colors)); - val[3] = val[2] = val[1] = val[0]; - - } else if (i == 3 || i == 4) { - for (j = 0; j < ARRAY_SIZE(kb_colors); j++) { - if (!strcmp(left, kb_colors[j].name)) - val[0] = j; - if (!strcmp(center, kb_colors[j].name)) - val[1] = j; - if (!strcmp(right, kb_colors[j].name)) - val[2] = j; - if (!strcmp(extra, kb_colors[j].name)) - val[3] = j; - } - val[0] = clamp_t(unsigned, val[0], 0, ARRAY_SIZE(kb_colors)); - val[1] = clamp_t(unsigned, val[1], 0, ARRAY_SIZE(kb_colors)); - val[2] = clamp_t(unsigned, val[2], 0, ARRAY_SIZE(kb_colors)); - val[3] = clamp_t(unsigned, val[3], 0, ARRAY_SIZE(kb_colors)); - - } else - return -EINVAL; - - kb_backlight.ops->set_color(val[0], val[1], val[2], val[3]); - - return size; -} -static DEVICE_ATTR(kb_color, 0644, - s76_color_show, s76_color_store); diff --git a/kb_led.c b/kb_led.c index c3c9a3c..2cedc6d 100644 --- a/kb_led.c +++ b/kb_led.c @@ -19,13 +19,50 @@ #define SET_KB_LED 0x67 -static enum led_brightness kb_led_brightness = LED_OFF; +union kb_led_color { + u32 rgb; + struct { u32 b:8, g:8, r:8, : 8; }; +}; + +enum kb_led_region { + KB_LED_REGION_LEFT, + KB_LED_REGION_CENTER, + KB_LED_REGION_RIGHT, + KB_LED_REGION_EXTRA, +}; + +static enum led_brightness kb_led_brightness = 72; + +static enum led_brightness kb_led_toggle_brightness = 72; + +static enum led_brightness kb_led_levels[] = { 48, 72, 96, 144, 192, 255 }; + +static union kb_led_color kb_led_regions[] = { + { .rgb = 0xFFFFFF }, + { .rgb = 0xFFFFFF }, + { .rgb = 0xFFFFFF }, + { .rgb = 0xFFFFFF } +}; + +static int kb_led_colors_i = 0; + +static union kb_led_color kb_led_colors[] = { + { .rgb = 0xFFFFFF }, + { .rgb = 0x0000FF }, + { .rgb = 0xFF0000 }, + { .rgb = 0xFF00FF }, + { .rgb = 0x00FF00 }, + { .rgb = 0x00FFFF }, + { .rgb = 0xFFFF00 } +}; static enum led_brightness kb_led_get(struct led_classdev *led_cdev) { return kb_led_brightness; } static int kb_led_set(struct led_classdev *led_cdev, enum led_brightness value) { + S76_INFO("kb_led_set %d\n", (int)value); + if (!s76_wmbb(SET_KB_LED, 0xF4000000 | value, NULL)) { kb_led_brightness = value; } @@ -33,14 +70,60 @@ static int kb_led_set(struct led_classdev *led_cdev, enum led_brightness value) return 0; } +static void kb_led_color_set(enum kb_led_region region, union kb_led_color color) { + u32 cmd; + + S76_INFO("kb_led_color_set %d %x\n", (int)region, (int)color.rgb); + + switch (region) { + case KB_LED_REGION_LEFT: + cmd = 0xF0000000; + break; + case KB_LED_REGION_CENTER: + cmd = 0xF1000000; + break; + case KB_LED_REGION_RIGHT: + cmd = 0xF2000000; + break; + case KB_LED_REGION_EXTRA: + cmd = 0xF3000000; + break; + default: + return; + } + + cmd |= color.b << 16; + cmd |= color.r << 8; + cmd |= color.g << 0; + + if (!s76_wmbb(SET_KB_LED, cmd, NULL)) { + kb_led_regions[region] = color; + } +} + static struct led_classdev kb_led = { - .name = "system76::kbd_backlight", + .name = "system76::fun_backlight", .flags = LED_BRIGHT_HW_CHANGED, .brightness_get = kb_led_get, .brightness_set_blocking = kb_led_set, .max_brightness = 255, }; +static void kb_led_resume(void) { + enum kb_led_region region; + + // Enable keyboard backlight + s76_wmbb(SET_KB_LED, 0xE007F001, NULL); + + // Reset current brightness + kb_led_set(&kb_led, kb_led_brightness); + + // Reset current color + for (region = 0; region < sizeof(kb_led_regions)/sizeof(union kb_led_color); region++) { + kb_led_color_set(region, kb_led_regions[region]); + } +} + static int __init kb_led_init(struct device *dev) { int err; @@ -49,6 +132,8 @@ static int __init kb_led_init(struct device *dev) { return err; } + kb_led_resume(); + return 0; } @@ -57,3 +142,62 @@ static void __exit kb_led_exit(void) { led_classdev_unregister(&kb_led); } } + +static void kb_wmi_brightness(enum led_brightness value) { + S76_INFO("kb_wmi_brightness %d\n", (int)value); + + kb_led_set(&kb_led, value); + led_classdev_notify_brightness_hw_changed(&kb_led, value); +} + +static void kb_wmi_toggle(void) { + if (kb_led_brightness > 0) { + kb_led_toggle_brightness = kb_led_brightness; + kb_wmi_brightness(LED_OFF); + } else { + kb_wmi_brightness(kb_led_toggle_brightness); + } +} + +static void kb_wmi_dec(void) { + int i; + + if (kb_led_brightness > 0) { + for (i = sizeof(kb_led_levels)/sizeof(enum led_brightness); i > 0; i--) { + if (kb_led_levels[i - 1] < kb_led_brightness) { + kb_wmi_brightness(kb_led_levels[i - 1]); + break; + } + } + } else { + kb_wmi_toggle(); + } +} + +static void kb_wmi_inc(void) { + int i; + + if (kb_led_brightness > 0) { + for (i = 0; i < sizeof(kb_led_levels)/sizeof(enum led_brightness); i++) { + if (kb_led_levels[i] > kb_led_brightness) { + kb_wmi_brightness(kb_led_levels[i]); + break; + } + } + } else { + kb_wmi_toggle(); + } +} + +static void kb_wmi_color(void) { + enum kb_led_region region; + + kb_led_colors_i += 1; + if (kb_led_colors_i >= sizeof(kb_led_colors)/sizeof(union kb_led_color)) { + kb_led_colors_i = 0; + } + + for (region = 0; region < sizeof(kb_led_regions)/sizeof(union kb_led_color); region++) { + kb_led_color_set(region, kb_led_colors[kb_led_colors_i]); + } +} \ No newline at end of file diff --git a/system76.c b/system76.c index 1c0ede8..496030d 100644 --- a/system76.c +++ b/system76.c @@ -91,11 +91,11 @@ static int s76_wmbb(u32 method_id, u32 arg, u32 *retval) { return 0; } -#include "ec.c" +//#include "ec.c" #include "ap_led.c" #include "input.c" #include "kb_led.c" -#include "kb.c" +//#include "kb.c" #include "hwmon.c" static void s76_debug_wmi(void) { @@ -160,9 +160,21 @@ static void s76_wmi_notify(u32 value, void *context) { S76_INFO("WMI event code (%x)\n", event); switch (event) { + case 0x81: + kb_wmi_dec(); + break; + case 0x82: + kb_wmi_inc(); + break; + case 0x83: + kb_wmi_color(); + break; case 0x95: s76_debug_wmi(); break; + case 0x9F: + kb_wmi_toggle(); + break; case 0xF4: s76_input_airplane_wmi(); break; @@ -173,7 +185,7 @@ static void s76_wmi_notify(u32 value, void *context) { s76_input_touchpad_wmi(true); break; default: - kb_wmi(event); + S76_INFO("Unknown WMI event code (%x)\n", event); break; } } @@ -181,11 +193,6 @@ static void s76_wmi_notify(u32 value, void *context) { static int s76_probe(struct platform_device *dev) { int err; - err = ec_init(); - if (unlikely(err)) { - S76_ERROR("Could not register EC device\n"); - } - err = ap_led_init(&dev->dev); if (unlikely(err)) { S76_ERROR("Could not register LED device\n"); @@ -201,26 +208,6 @@ static int s76_probe(struct platform_device *dev) { S76_ERROR("Could not register input device\n"); } - if (device_create_file(&dev->dev, &dev_attr_kb_brightness) != 0) { - S76_ERROR("Sysfs attribute creation failed for brightness\n"); - } - - if (device_create_file(&dev->dev, &dev_attr_kb_state) != 0) { - S76_ERROR("Sysfs attribute creation failed for state\n"); - } - - if (device_create_file(&dev->dev, &dev_attr_kb_mode) != 0) { - S76_ERROR("Sysfs attribute creation failed for mode\n"); - } - - if (device_create_file(&dev->dev, &dev_attr_kb_color) != 0) { - S76_ERROR("Sysfs attribute creation failed for color\n"); - } - - if (kb_backlight.ops) { - kb_backlight.ops->init(); - } - #ifdef S76_HAS_HWMON s76_hwmon_init(&dev->dev); #endif @@ -249,27 +236,19 @@ static int s76_remove(struct platform_device *dev) { s76_hwmon_fini(&dev->dev); #endif - device_remove_file(&dev->dev, &dev_attr_kb_color); - device_remove_file(&dev->dev, &dev_attr_kb_mode); - device_remove_file(&dev->dev, &dev_attr_kb_state); - device_remove_file(&dev->dev, &dev_attr_kb_brightness); - s76_input_exit(); kb_led_exit(); ap_led_exit(); - ec_exit(); - return 0; } 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) { - kb_backlight.ops->set_mode(kb_backlight.mode); - } + + ap_led_resume(); + kb_led_resume(); return 0; } @@ -285,23 +264,22 @@ static struct platform_driver s76_platform_driver = { static int __init s76_dmi_matched(const struct dmi_system_id *id) { S76_INFO("Model %s found\n", id->ident); - kb_backlight.ops = id->driver_data; return 1; } -#define DMI_TABLE(PRODUCT, DATA) { \ +#define DMI_TABLE(PRODUCT) { \ .ident = "System76 " PRODUCT, \ .matches = { \ DMI_MATCH(DMI_SYS_VENDOR, "System76"), \ DMI_MATCH(DMI_PRODUCT_VERSION, PRODUCT), \ }, \ .callback = s76_dmi_matched, \ - .driver_data = DATA, \ + .driver_data = NULL, \ } static struct dmi_system_id s76_dmi_table[] __initdata = { - DMI_TABLE("oryp3-jeremy", &kb_full_color_ops), + DMI_TABLE("oryp3-jeremy"), {} }; @@ -310,14 +288,6 @@ MODULE_DEVICE_TABLE(dmi, s76_dmi_table); static int __init s76_init(void) { int err; - switch (param_kb_color_num) { - case 1: - param_kb_color[1] = param_kb_color[2] = param_kb_color[0] = param_kb_color[3]; - break; - case 2: - return -EINVAL; - } - dmi_check_system(s76_dmi_table); if (!wmi_has_guid(S76_EVENT_GUID)) {