From 6cf70084abb866dac6ba340ad587ebbebcb792cc Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 15 Jul 2022 14:45:51 +0200 Subject: [PATCH 01/59] Add header guard --- src/clevo_keyboard.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 278e937..b0224ce 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with this software. If not, see . */ +#ifndef CLEVO_KEYBOARD_H +#define CLEVO_KEYBOARD_H + #include "tuxedo_keyboard_common.h" #include "clevo_interfaces.h" @@ -827,3 +830,5 @@ struct tuxedo_keyboard_driver clevo_keyboard_driver = { .probe = clevo_keyboard_probe, .key_map = clevo_keymap, }; + +#endif // CLEVO_KEYBOARD_H From 42f8a677cf3bd6105190ac2f45b7f9d3b44ccff7 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 15 Jul 2022 14:46:25 +0200 Subject: [PATCH 02/59] Add basic leds interface backlight control --- src/clevo_keyboard.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index b0224ce..8f52d22 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -22,6 +22,8 @@ #include "tuxedo_keyboard_common.h" #include "clevo_interfaces.h" +#include + #define BRIGHTNESS_MIN 0 #define BRIGHTNESS_MAX 255 #define BRIGHTNESS_DEFAULT BRIGHTNESS_MAX @@ -644,6 +646,23 @@ static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); +int ledcdev_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { + set_brightness(brightness); + return 0; +} + +enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { + return kbd_led_state.brightness; +} + +struct led_classdev cdev_brightness = { + .name = KBUILD_MODNAME "::kbd_backlight", + .max_brightness = BRIGHTNESS_MAX, + .brightness_set_blocking = &ledcdev_set_blocking, + .brightness_get = &ledcdev_get, + .brightness = BRIGHTNESS_DEFAULT, +}; + static void clevo_keyboard_init_device_interface(struct platform_device *dev) { // Setup sysfs @@ -701,6 +720,7 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) ("Sysfs attribute file creation failed for brightness\n"); } + led_classdev_register(&dev->dev, &cdev_brightness); } void clevo_keyboard_write_state(void) From 45a240f5f2c96ecba15b12e0386ff742a14dbfa0 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 16 Jul 2022 17:08:15 +0200 Subject: [PATCH 03/59] Add debug on wmi call 13 output for testing Fix wrong pointer dereferentiation Add debug output for clevo_acpi Create more flexible clevo_evaluate_method2() --- src/clevo_acpi.c | 30 ++++++++++++++++------------- src/clevo_interfaces.h | 4 +++- src/clevo_keyboard.h | 26 ++++++++++++++++++++++++- src/clevo_wmi.c | 43 +++++++++++++++++++++++------------------- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index 9b246eb..eb734b0 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -31,7 +31,7 @@ struct clevo_acpi_driver_data_t { static struct clevo_acpi_driver_data_t *active_driver_data = NULL; -static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 *result) +static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, union acpi_object **result) { u32 status; acpi_handle handle; @@ -68,23 +68,17 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 if (!out_obj) { pr_err("failed to evaluate _DSM\n"); status = -1; - } else { - if (out_obj->type == ACPI_TYPE_INTEGER) { - if (!IS_ERR_OR_NULL(result)) - *result = (u32) out_obj->integer.value; - // pr_debug("evaluate _DSM cmd: %0#4x arg: %0#10x\n", cmd, arg); - } else { - pr_err("unknown output from _DSM\n"); - status = -ENODATA; + } + else { + if (!IS_ERR_OR_NULL(result)) { + *result = out_obj; } } - ACPI_FREE(out_obj); - return status; } -u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value) { u32 status = 0; @@ -139,9 +133,19 @@ static int clevo_acpi_remove(struct acpi_device *device) void clevo_acpi_notify(struct acpi_device *device, u32 event) { u32 event_value; + union acpi_object *out_obj; + u32 status; // struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; - clevo_acpi_evaluate(device, 0x01, 0, &event_value); + status = clevo_acpi_evaluate(device, 0x01, 0, &out_obj); + if (!status) { + if (out_obj->type == ACPI_TYPE_INTEGER) { + event_value = (u32)out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + } + ACPI_FREE(out_obj); + } pr_debug("clevo_acpi event: %0#6x, clevo event value: %0#6x\n", event, event_value); // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index e8f2bd5..c3226cd 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -20,6 +20,7 @@ #define CLEVO_INTERFACES_H #include +#include #define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" #define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" @@ -51,12 +52,13 @@ struct clevo_interface_t { char *string_id; void (*event_callb)(u32); - u32 (*method_call)(u8, u32, u32*); + u32 (*method_call)(u8, u32, union acpi_object **); }; u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface); u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result); +u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result); u32 clevo_get_active_interface_id(char **id_str); #define MODULE_ALIAS_CLEVO_WMI() \ diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 8f52d22..d7712ee 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -307,7 +307,7 @@ static ssize_t show_hasextra_fs(struct device *child, return sprintf(buffer, "%d\n", kbd_led_state.has_extra); } -u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result) { if (IS_ERR_OR_NULL(active_clevo_interface)) { pr_err("clevo_keyboard: no active interface while attempting cmd %02x arg %08x\n", cmd, arg); @@ -315,6 +315,30 @@ u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) } return active_clevo_interface->method_call(cmd, arg, result); } +EXPORT_SYMBOL(clevo_evaluate_method2); + +u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +{ + u32 status = 0; + union acpi_object *out_obj; + + status = clevo_evaluate_method2(cmd, arg, &out_obj); + if (status) { + return status; + } + else { + if (out_obj->type == ACPI_TYPE_INTEGER) { + if (!IS_ERR_OR_NULL(result)) + *result = (u32) out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + status = -ENODATA; + } + ACPI_FREE(out_obj); + } + + return status; +} EXPORT_SYMBOL(clevo_evaluate_method); u32 clevo_get_active_interface_id(char **id_str) diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 14320f4..22623a6 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -23,7 +23,7 @@ #include #include "clevo_interfaces.h" -static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) +static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, union acpi_object **result) { struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg), &wmi_arg }; @@ -45,26 +45,17 @@ static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) if (!acpi_result) { pr_err("failed to evaluate WMI method\n"); return_status = -1; - } else { - if (acpi_result->type == ACPI_TYPE_INTEGER) { - if (!IS_ERR_OR_NULL(result)) { - *result = (u32)acpi_result->integer.value; - /*pr_debug( - "evaluate wmi cmd: %0#4x arg: %0#10x\n", - wmi_method_id, wmi_arg);*/ - } - } else { - pr_err("unknown output from wmi method\n"); - return_status = -EIO; + } + else { + if (!IS_ERR_OR_NULL(result)) { + *result = acpi_result; } } - kfree(acpi_result); - return return_status; } -u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value) { return clevo_wmi_evaluate(cmd, arg, result_value); } @@ -80,7 +71,8 @@ static int clevo_wmi_probe(struct wmi_device *wdev) static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) #endif { - u32 status, ret; + u32 status; + union acpi_object *out_obj; pr_debug("clevo_wmi driver probe\n"); @@ -96,16 +88,18 @@ static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) // Since the WMI GUIDs aren't unique let's (at least) // check the return of some "known existing general" method - status = clevo_wmi_evaluate(0x52, 0, &ret); + status = clevo_wmi_evaluate(0x52, 0, &out_obj); if (status < 0) { pr_debug("probe: Clevo GUIDs present but method call failed\n"); return -ENODEV; } - if (ret == 0xffffffff) { + if (out_obj->type != ACPI_TYPE_INTEGER || (out_obj->type == ACPI_TYPE_INTEGER && (u32)out_obj->integer.value == 0xffffffff)) { pr_debug( "probe: Clevo GUIDs present but method returned unexpected value\n"); + ACPI_FREE(out_obj); return -ENODEV; } + ACPI_FREE(out_obj); // Add this interface clevo_keyboard_add_interface(&clevo_wmi_interface); @@ -131,7 +125,18 @@ static void clevo_wmi_remove(struct wmi_device *wdev) static void clevo_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) { u32 event_value; - clevo_wmi_evaluate(0x01, 0, &event_value); + union acpi_object *out_obj; + u32 status; + + status = clevo_wmi_evaluate(0x01, 0, &out_obj); + if (!status) { + if (out_obj->type == ACPI_TYPE_INTEGER) { + event_value = (u32)out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + } + ACPI_FREE(out_obj); + } pr_debug("clevo_wmi notify\n"); if (!IS_ERR_OR_NULL(clevo_wmi_interface.event_callb)) { // Execute registered callback From e77d9748eeb31cf01fae199b1a7a91e292ec773f Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 22 Jul 2022 15:40:44 +0200 Subject: [PATCH 04/59] Add debug output --- src/clevo_keyboard.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index d7712ee..bb7f772 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -815,9 +815,20 @@ int clevo_keyboard_init(void) static int clevo_keyboard_probe(struct platform_device *dev) { + u32 status; + union acpi_object *result; + clevo_keyboard_init_device_interface(dev); clevo_keyboard_init(); + status = clevo_evaluate_method2(0x0D, 0, &result); + if (!status) { + if (result->type == ACPI_TYPE_BUFFER) { + printk(KERN_EMERG "Keyboard Backlight Type: 0x%02x", result->buffer.pointer[0x0f]); + } + ACPI_FREE(result); + } + return 0; } From 95b0b95599f5f942693937c65b6d20f1ecc2e13a Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 18 Aug 2022 13:52:55 +0200 Subject: [PATCH 05/59] Use clevo keyboard backlight type information to only create relevant sysfs entries --- src/clevo_keyboard.h | 148 +++++++++++++++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 33 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index bb7f772..353abc2 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -43,6 +43,7 @@ #define CLEVO_METHOD_ID_GET_AP 0x46 #define CLEVO_METHOD_ID_SET_KB_LEDS 0x67 /* used to set color, brightness, blinking pattern, etc. */ +#define CLEVO_METHOD_ID_GET_SPECS 0x0D // only works with clevo_evaluate_method2 // Clevo event codes @@ -66,6 +67,14 @@ static struct clevo_interfaces_t { struct clevo_interface_t *acpi; } clevo_interfaces; +enum clevo_kb_backlight_type { + CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, + CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR = 0x01, + CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB = 0x02, + CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB = 0x06, + CLEVO_KB_BACKLIGHT_TYPE_PER_KEY_RGB = 0xf3 +}; + struct clevo_interface_t *active_clevo_interface; void clevo_keyboard_write_state(void); @@ -173,7 +182,12 @@ static struct key_entry clevo_keymap[] = { // Keyboard struct struct kbd_led_state_t { + u8 has_left; + u8 has_center; + u8 has_right; u8 has_extra; + u8 has_mode; + u8 has_brightness; u8 enabled; struct { @@ -228,7 +242,12 @@ MODULE_PARM_DESC(state, "Set the State of the Keyboard TRUE = ON | FALSE = OFF"); static struct kbd_led_state_t kbd_led_state = { + .has_left = 0, + .has_center = 0, + .has_right = 0, .has_extra = 0, + .has_mode = 0, + .has_brightness = 0, .enabled = 1, .color = { .left = KB_COLOR_DEFAULT, .center = KB_COLOR_DEFAULT, @@ -689,30 +708,69 @@ struct led_classdev cdev_brightness = { static void clevo_keyboard_init_device_interface(struct platform_device *dev) { + u32 status; + union acpi_object *result; + // The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To + // not break these, we set this as default for the time being, better having an extra sysfs entry without function than + // a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. + enum clevo_kb_backlight_type kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; + + status = clevo_evaluate_method2(CLEVO_METHOD_ID_GET_SPECS, 0, &result); + if (!status) { + if (result->type == ACPI_TYPE_BUFFER) { + pr_debug("CLEVO_METHOD_ID_GET_SPECS successful"); + kb_backlight_type = result->buffer.pointer[0x0f]; + } + else { + pr_debug("CLEVO_METHOD_ID_GET_SPECS return value has wrong type"); + } + ACPI_FREE(result); + } + else { + pr_debug("CLEVO_METHOD_ID_GET_SPECS failed"); + } + pr_debug("Keyboard Backlight Type: 0x%02x", kb_backlight_type); + // Setup sysfs if (device_create_file(&dev->dev, &dev_attr_state) != 0) { TUXEDO_ERROR("Sysfs attribute file creation failed for state\n"); } - if (device_create_file - (&dev->dev, &dev_attr_color_left) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color left\n"); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB || + kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file + (&dev->dev, &dev_attr_color_left) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color left\n"); + } + else { + kbd_led_state.has_left = 1; + } } - if (device_create_file - (&dev->dev, &dev_attr_color_center) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color center\n"); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file + (&dev->dev, &dev_attr_color_center) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color center\n"); + } + else { + kbd_led_state.has_center = 1; + } } - if (device_create_file - (&dev->dev, &dev_attr_color_right) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color right\n"); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file + (&dev->dev, &dev_attr_color_right) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for color right\n"); + } + else { + kbd_led_state.has_right = 1; + } } - if (set_color(REGION_EXTRA, KB_COLOR_DEFAULT) != 0) { + /*if (set_color(REGION_EXTRA, KB_COLOR_DEFAULT) != 0) { TUXEDO_DEBUG("Keyboard does not support EXTRA Color"); kbd_led_state.has_extra = 0; } else { @@ -725,7 +783,8 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) } set_color(REGION_EXTRA, param_color_extra); - } + }*/ + kbd_led_state.has_extra = 0; // No known Clevo device using this region, set color check doesn't work. if (device_create_file(&dev->dev, &dev_attr_extra) != 0) { @@ -733,9 +792,27 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) ("Sysfs attribute file creation failed for extra information flag\n"); } - if (device_create_file(&dev->dev, &dev_attr_mode) != - 0) { - TUXEDO_ERROR("Sysfs attribute file creation failed for blinking pattern\n"); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file(&dev->dev, &dev_attr_mode) != + 0) { + TUXEDO_ERROR("Sysfs attribute file creation failed for blinking pattern\n"); + } + else { + kbd_led_state.has_mode = 1; + } + } + + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR || + kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB || + kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file + (&dev->dev, &dev_attr_brightness) != 0) { + TUXEDO_ERROR + ("Sysfs attribute file creation failed for brightness\n"); + } + else { + kbd_led_state.has_brightness = 1; + } } if (device_create_file @@ -815,32 +892,37 @@ int clevo_keyboard_init(void) static int clevo_keyboard_probe(struct platform_device *dev) { - u32 status; - union acpi_object *result; - clevo_keyboard_init_device_interface(dev); clevo_keyboard_init(); - status = clevo_evaluate_method2(0x0D, 0, &result); - if (!status) { - if (result->type == ACPI_TYPE_BUFFER) { - printk(KERN_EMERG "Keyboard Backlight Type: 0x%02x", result->buffer.pointer[0x0f]); - } - ACPI_FREE(result); - } - return 0; } static void clevo_keyboard_remove_device_interface(struct platform_device *dev) { device_remove_file(&dev->dev, &dev_attr_state); - device_remove_file(&dev->dev, &dev_attr_color_left); - device_remove_file(&dev->dev, &dev_attr_color_center); - device_remove_file(&dev->dev, &dev_attr_color_right); + + if (kbd_led_state.has_left == 1) { + device_remove_file(&dev->dev, &dev_attr_color_left); + } + + if (kbd_led_state.has_center == 1) { + device_remove_file(&dev->dev, &dev_attr_color_center); + } + + if (kbd_led_state.has_right == 1) { + device_remove_file(&dev->dev, &dev_attr_color_right); + } + device_remove_file(&dev->dev, &dev_attr_extra); - device_remove_file(&dev->dev, &dev_attr_mode); - device_remove_file(&dev->dev, &dev_attr_brightness); + + if (kbd_led_state.has_mode == 1) { + device_remove_file(&dev->dev, &dev_attr_mode); + } + + if (kbd_led_state.has_brightness == 1) { + device_remove_file(&dev->dev, &dev_attr_brightness); + } if (kbd_led_state.has_extra == 1) { device_remove_file(&dev->dev, &dev_attr_color_extra); From f50eeaac07128013758bb3a8ef3aa83115b2c192 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 18 Aug 2022 14:04:25 +0200 Subject: [PATCH 06/59] Add dummy leds interface for 3 zone keyboard --- src/clevo_keyboard.h | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 353abc2..683db6e 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -698,7 +698,23 @@ enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { return kbd_led_state.brightness; } -struct led_classdev cdev_brightness = { +struct led_classdev cdev_kb_1 = { + .name = KBUILD_MODNAME "::kbd_backlight", + .max_brightness = BRIGHTNESS_MAX, + .brightness_set_blocking = &ledcdev_set_blocking, + .brightness_get = &ledcdev_get, + .brightness = BRIGHTNESS_DEFAULT, +}; + +struct led_classdev cdev_kb_2 = { + .name = KBUILD_MODNAME "::kbd_backlight", + .max_brightness = BRIGHTNESS_MAX, + .brightness_set_blocking = &ledcdev_set_blocking, + .brightness_get = &ledcdev_get, + .brightness = BRIGHTNESS_DEFAULT, +}; + +struct led_classdev cdev_kb_3 = { .name = KBUILD_MODNAME "::kbd_backlight", .max_brightness = BRIGHTNESS_MAX, .brightness_set_blocking = &ledcdev_set_blocking, @@ -815,13 +831,19 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) } } - if (device_create_file - (&dev->dev, &dev_attr_brightness) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for brightness\n"); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + led_classdev_register(&dev->dev, &cdev_kb_1); } - led_classdev_register(&dev->dev, &cdev_brightness); + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + led_classdev_register(&dev->dev, &cdev_kb_1); + } + + if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + led_classdev_register(&dev->dev, &cdev_kb_1); + led_classdev_register(&dev->dev, &cdev_kb_2); + led_classdev_register(&dev->dev, &cdev_kb_3); + } } void clevo_keyboard_write_state(void) From affc59e3e2784a3a838c4495fb8365e1759fcd67 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 18 Aug 2022 18:32:45 +0200 Subject: [PATCH 07/59] Implement multi color leds for Clevo 1 and 3 zone rgb keyboard backlights --- src/clevo_keyboard.h | 147 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 127 insertions(+), 20 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 683db6e..2c3ba81 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -23,6 +23,7 @@ #include "clevo_interfaces.h" #include +#include #define BRIGHTNESS_MIN 0 #define BRIGHTNESS_MAX 255 @@ -694,11 +695,63 @@ int ledcdev_set_blocking(struct led_classdev *led_cdev, enum led_brightness brig return 0; } +int ledcdev_set_blocking_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + u32 region, colorcode; + struct led_classdev_mc *led_cdev_mc = lcdev_to_mccdev(led_cdev); + + pr_debug("ledcdev_set_blocking_mc() brightness 0x%02x", brightness); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].intensity 0x%02x", led_cdev_mc->subled_info[0].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].intensity 0x%02x", led_cdev_mc->subled_info[1].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].intensity 0x%02x", led_cdev_mc->subled_info[2].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].channel 0x%02x", led_cdev_mc->subled_info[0].channel); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].channel 0x%02x", led_cdev_mc->subled_info[1].channel); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].channel 0x%02x", led_cdev_mc->subled_info[2].channel); + + if (led_cdev_mc->subled_info[0].channel == 0) { + region = REGION_LEFT; + } + else if (led_cdev_mc->subled_info[0].channel == 1) { + region = REGION_CENTER; + } + else if (led_cdev_mc->subled_info[0].channel == 2) { + region = REGION_RIGHT; + } + else { + region = REGION_EXTRA; + } + + colorcode = (led_cdev_mc->subled_info[0].intensity << 16) + + (led_cdev_mc->subled_info[1].intensity << 8) + + led_cdev_mc->subled_info[2].intensity; + + if (!set_color(region, colorcode)) { + // after succesfully setting color, update our state struct + // depending on which region was changed + switch (region) { + case REGION_LEFT: + kbd_led_state.color.left = colorcode; + break; + case REGION_CENTER: + kbd_led_state.color.center = colorcode; + break; + case REGION_RIGHT: + kbd_led_state.color.right = colorcode; + break; + case REGION_EXTRA: + kbd_led_state.color.extra = colorcode; + break; + } + } + + set_brightness(brightness); + return 0; +} + enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { return kbd_led_state.brightness; } -struct led_classdev cdev_kb_1 = { +struct led_classdev cdev_kb = { .name = KBUILD_MODNAME "::kbd_backlight", .max_brightness = BRIGHTNESS_MAX, .brightness_set_blocking = &ledcdev_set_blocking, @@ -706,21 +759,9 @@ struct led_classdev cdev_kb_1 = { .brightness = BRIGHTNESS_DEFAULT, }; -struct led_classdev cdev_kb_2 = { - .name = KBUILD_MODNAME "::kbd_backlight", - .max_brightness = BRIGHTNESS_MAX, - .brightness_set_blocking = &ledcdev_set_blocking, - .brightness_get = &ledcdev_get, - .brightness = BRIGHTNESS_DEFAULT, -}; +struct led_classdev_mc cdev_kb_mc[3]; -struct led_classdev cdev_kb_3 = { - .name = KBUILD_MODNAME "::kbd_backlight", - .max_brightness = BRIGHTNESS_MAX, - .brightness_set_blocking = &ledcdev_set_blocking, - .brightness_get = &ledcdev_get, - .brightness = BRIGHTNESS_DEFAULT, -}; +struct mc_subled cdev_kb_mc_subled[3][3]; static void clevo_keyboard_init_device_interface(struct platform_device *dev) { @@ -832,17 +873,83 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) } if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - led_classdev_register(&dev->dev, &cdev_kb_1); + led_classdev_register(&dev->dev, &cdev_kb); } if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - led_classdev_register(&dev->dev, &cdev_kb_1); + cdev_kb_mc[0].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; + cdev_kb_mc[0].led_cdev.max_brightness = BRIGHTNESS_MAX; + cdev_kb_mc[0].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; + cdev_kb_mc[0].led_cdev.brightness_get = &ledcdev_get; + cdev_kb_mc[0].led_cdev.brightness = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].num_colors = 3; + cdev_kb_mc[0].subled_info = cdev_kb_mc_subled[0]; + cdev_kb_mc[0].subled_info[0].color_index = LED_COLOR_ID_RED; + cdev_kb_mc[0].subled_info[0].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[0].channel = 0; + cdev_kb_mc[0].subled_info[1].color_index = LED_COLOR_ID_GREEN; + cdev_kb_mc[0].subled_info[1].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[1].channel = 0; + cdev_kb_mc[0].subled_info[2].color_index = LED_COLOR_ID_BLUE; + cdev_kb_mc[0].subled_info[2].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[2].channel = 0; + devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[0]); } if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - led_classdev_register(&dev->dev, &cdev_kb_1); - led_classdev_register(&dev->dev, &cdev_kb_2); - led_classdev_register(&dev->dev, &cdev_kb_3); + cdev_kb_mc[0].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; + cdev_kb_mc[0].led_cdev.max_brightness = BRIGHTNESS_MAX; + cdev_kb_mc[0].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; + cdev_kb_mc[0].led_cdev.brightness_get = &ledcdev_get; + cdev_kb_mc[0].led_cdev.brightness = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].num_colors = 3; + cdev_kb_mc[0].subled_info = cdev_kb_mc_subled[0]; + cdev_kb_mc[0].subled_info[0].color_index = LED_COLOR_ID_RED; + cdev_kb_mc[0].subled_info[0].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[0].channel = 0; + cdev_kb_mc[0].subled_info[1].color_index = LED_COLOR_ID_GREEN; + cdev_kb_mc[0].subled_info[1].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[1].channel = 0; + cdev_kb_mc[0].subled_info[2].color_index = LED_COLOR_ID_BLUE; + cdev_kb_mc[0].subled_info[2].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[0].subled_info[2].channel = 0; + devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[0]); + + cdev_kb_mc[1].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; + cdev_kb_mc[1].led_cdev.max_brightness = BRIGHTNESS_MAX; + cdev_kb_mc[1].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; + cdev_kb_mc[1].led_cdev.brightness_get = &ledcdev_get; + cdev_kb_mc[1].led_cdev.brightness = BRIGHTNESS_DEFAULT; + cdev_kb_mc[1].num_colors = 3; + cdev_kb_mc[1].subled_info = cdev_kb_mc_subled[1]; + cdev_kb_mc[1].subled_info[0].color_index = LED_COLOR_ID_RED; + cdev_kb_mc[1].subled_info[0].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[1].subled_info[0].channel = 1; + cdev_kb_mc[1].subled_info[1].color_index = LED_COLOR_ID_GREEN; + cdev_kb_mc[1].subled_info[1].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[1].subled_info[1].channel = 1; + cdev_kb_mc[1].subled_info[2].color_index = LED_COLOR_ID_BLUE; + cdev_kb_mc[1].subled_info[2].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[1].subled_info[2].channel = 1; + devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[1]); + + cdev_kb_mc[2].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; + cdev_kb_mc[2].led_cdev.max_brightness = BRIGHTNESS_MAX; + cdev_kb_mc[2].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; + cdev_kb_mc[2].led_cdev.brightness_get = &ledcdev_get; + cdev_kb_mc[2].led_cdev.brightness = BRIGHTNESS_DEFAULT; + cdev_kb_mc[2].num_colors = 3; + cdev_kb_mc[2].subled_info = cdev_kb_mc_subled[2]; + cdev_kb_mc[2].subled_info[0].color_index = LED_COLOR_ID_RED; + cdev_kb_mc[2].subled_info[0].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[2].subled_info[0].channel = 2; + cdev_kb_mc[2].subled_info[1].color_index = LED_COLOR_ID_GREEN; + cdev_kb_mc[2].subled_info[1].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[2].subled_info[1].channel = 2; + cdev_kb_mc[2].subled_info[2].color_index = LED_COLOR_ID_BLUE; + cdev_kb_mc[2].subled_info[2].intensity = BRIGHTNESS_DEFAULT; + cdev_kb_mc[2].subled_info[2].channel = 2; + devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[2]); } } From 5c410c27c99c233e950188476af864a44119c34b Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 18 Aug 2022 18:46:50 +0200 Subject: [PATCH 08/59] Change default to max brightness --- tuxedo_keyboard.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuxedo_keyboard.conf b/tuxedo_keyboard.conf index 6bc2838..b257600 100644 --- a/tuxedo_keyboard.conf +++ b/tuxedo_keyboard.conf @@ -1 +1 @@ -options tuxedo-keyboard mode=0 brightness=75 color_left=0xFFFFFF color_center=0xFFFFFF color_right=0xFFFFFF +options tuxedo-keyboard mode=0 brightness=255 color_left=0xFFFFFF color_center=0xFFFFFF color_right=0xFFFFFF From 9d0dd45147ff49aeec6529054267e5150c7a8549 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 18 Aug 2022 18:47:46 +0200 Subject: [PATCH 09/59] Change stepsize to something better suited for 0 - 255 --- src/clevo_keyboard.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 2c3ba81..d6d3395 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -179,7 +179,7 @@ static struct key_entry clevo_keymap[] = { { KE_END, 0 } }; -#define BRIGHTNESS_STEP 25 +#define BRIGHTNESS_STEP 32 // Keyboard struct struct kbd_led_state_t { @@ -635,20 +635,20 @@ void clevo_keyboard_event_callb(u32 event) switch (key_event) { case CLEVO_EVENT_DECREASE_BACKLIGHT: if (kbd_led_state.brightness == BRIGHTNESS_MIN - || (kbd_led_state.brightness - 25) < BRIGHTNESS_MIN) { + || (kbd_led_state.brightness - BRIGHTNESS_STEP) < BRIGHTNESS_MIN) { set_brightness(BRIGHTNESS_MIN); } else { - set_brightness(kbd_led_state.brightness - 25); + set_brightness(kbd_led_state.brightness - BRIGHTNESS_STEP); } break; case CLEVO_EVENT_INCREASE_BACKLIGHT: if (kbd_led_state.brightness == BRIGHTNESS_MAX - || (kbd_led_state.brightness + 25) > BRIGHTNESS_MAX) { + || (kbd_led_state.brightness + BRIGHTNESS_STEP) > BRIGHTNESS_MAX) { set_brightness(BRIGHTNESS_MAX); } else { - set_brightness(kbd_led_state.brightness + 25); + set_brightness(kbd_led_state.brightness + BRIGHTNESS_STEP); } break; From 3fc795aa0c5a119ede43741b5b5c88a6c8f15a2b Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 19 Aug 2022 12:33:54 +0200 Subject: [PATCH 10/59] Fix coding style issues --- src/clevo_keyboard.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index d6d3395..09631b8 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -690,22 +690,22 @@ static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); -int ledcdev_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { +static int ledcdev_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { set_brightness(brightness); return 0; } -int ledcdev_set_blocking_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { +static int ledcdev_set_blocking_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { u32 region, colorcode; struct led_classdev_mc *led_cdev_mc = lcdev_to_mccdev(led_cdev); - pr_debug("ledcdev_set_blocking_mc() brightness 0x%02x", brightness); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].intensity 0x%02x", led_cdev_mc->subled_info[0].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].intensity 0x%02x", led_cdev_mc->subled_info[1].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].intensity 0x%02x", led_cdev_mc->subled_info[2].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].channel 0x%02x", led_cdev_mc->subled_info[0].channel); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].channel 0x%02x", led_cdev_mc->subled_info[1].channel); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].channel 0x%02x", led_cdev_mc->subled_info[2].channel); + pr_debug("ledcdev_set_blocking_mc() brightness 0x%02x\n", brightness); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].intensity 0x%02x\n", led_cdev_mc->subled_info[0].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].intensity 0x%02x\n", led_cdev_mc->subled_info[1].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].intensity 0x%02x\n", led_cdev_mc->subled_info[2].intensity); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].channel 0x%02x\n", led_cdev_mc->subled_info[0].channel); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].channel 0x%02x\n", led_cdev_mc->subled_info[1].channel); + pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].channel 0x%02x\n", led_cdev_mc->subled_info[2].channel); if (led_cdev_mc->subled_info[0].channel == 0) { region = REGION_LEFT; @@ -747,11 +747,11 @@ int ledcdev_set_blocking_mc(struct led_classdev *led_cdev, enum led_brightness b return 0; } -enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { +static enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { return kbd_led_state.brightness; } -struct led_classdev cdev_kb = { +static struct led_classdev cdev_kb = { .name = KBUILD_MODNAME "::kbd_backlight", .max_brightness = BRIGHTNESS_MAX, .brightness_set_blocking = &ledcdev_set_blocking, @@ -759,9 +759,9 @@ struct led_classdev cdev_kb = { .brightness = BRIGHTNESS_DEFAULT, }; -struct led_classdev_mc cdev_kb_mc[3]; +static struct led_classdev_mc cdev_kb_mc[3]; -struct mc_subled cdev_kb_mc_subled[3][3]; +static struct mc_subled cdev_kb_mc_subled[3][3]; static void clevo_keyboard_init_device_interface(struct platform_device *dev) { @@ -775,18 +775,18 @@ static void clevo_keyboard_init_device_interface(struct platform_device *dev) status = clevo_evaluate_method2(CLEVO_METHOD_ID_GET_SPECS, 0, &result); if (!status) { if (result->type == ACPI_TYPE_BUFFER) { - pr_debug("CLEVO_METHOD_ID_GET_SPECS successful"); + pr_debug("CLEVO_METHOD_ID_GET_SPECS successful\n"); kb_backlight_type = result->buffer.pointer[0x0f]; } else { - pr_debug("CLEVO_METHOD_ID_GET_SPECS return value has wrong type"); + pr_debug("CLEVO_METHOD_ID_GET_SPECS return value has wrong type\n"); } ACPI_FREE(result); } else { - pr_debug("CLEVO_METHOD_ID_GET_SPECS failed"); + pr_debug("CLEVO_METHOD_ID_GET_SPECS failed\n"); } - pr_debug("Keyboard Backlight Type: 0x%02x", kb_backlight_type); + pr_debug("Keyboard Backlight Type: 0x%02x\n", kb_backlight_type); // Setup sysfs if (device_create_file(&dev->dev, &dev_attr_state) != 0) { From ca72360c7dc1698ff5eeeec6a3155cc42e5b2043 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 19 Aug 2022 12:34:26 +0200 Subject: [PATCH 11/59] Add multi color interface for Uniwill single zone rgb keyboards --- src/uniwill_keyboard.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 41f7b8d..46de633 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with this software. If not, see . */ +#ifndef UNIWILL_KEYBOARD_H +#define UNIWILL_KEYBOARD_H + #include "tuxedo_keyboard_common.h" #include #include @@ -366,6 +369,10 @@ static ssize_t uw_brightness_show(struct device *child, return sprintf(buffer, "%d\n", kbd_led_state_uw.brightness); } +static enum led_brightness ledcdev_get_uw(struct led_classdev *led_cdev) { + return kbd_led_state_uw.brightness; +} + static ssize_t uw_brightness_store(struct device *child, struct device_attribute *attr, const char *buffer, size_t size) @@ -379,6 +386,22 @@ static ssize_t uw_brightness_store(struct device *child, return size; } +static int ledcdev_set_blocking_uw_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + struct led_classdev_mc *led_cdev_mc = lcdev_to_mccdev(led_cdev); + + led_mc_calc_color_components(led_cdev_mc, brightness); + uniwill_write_kbd_bl_rgb(led_cdev_mc->subled_info[0].brightness, + led_cdev_mc->subled_info[1].brightness, + led_cdev_mc->subled_info[2].brightness); + + kbd_led_state_uw.color = ((led_cdev_mc->subled_info[0].intensity * 255 / 200) << 16) + + ((led_cdev_mc->subled_info[1].intensity * 255 / 200) << 8) + + (led_cdev_mc->subled_info[2].intensity * 255 / 200); + kbd_led_state_uw.brightness = brightness; + + return 0; +} + static ssize_t uw_color_string_show(struct device *child, struct device_attribute *attr, char *buffer) { @@ -496,6 +519,28 @@ static void uw_kbd_bl_init_ready_check(struct timer_list *t) schedule_work(&uw_kbd_bl_init_ready_check_work); } +static struct mc_subled cdev_kb_uw_mc_subled[3] = { + { .color_index = LED_COLOR_ID_RED, + .brightness = UNIWILL_BRIGHTNESS_DEFAULT, + .intensity = UNIWILL_BRIGHTNESS_MAX }, + { .color_index = LED_COLOR_ID_GREEN, + .brightness = UNIWILL_BRIGHTNESS_DEFAULT, + .intensity = UNIWILL_BRIGHTNESS_MAX }, + { .color_index = LED_COLOR_ID_BLUE, + .brightness = UNIWILL_BRIGHTNESS_DEFAULT, + .intensity = UNIWILL_BRIGHTNESS_MAX } +}; + +static struct led_classdev_mc cdev_kb_uw_mc = { + .led_cdev.name = KBUILD_MODNAME "::kbd_backlight", + .led_cdev.max_brightness = UNIWILL_BRIGHTNESS_MAX, + .led_cdev.brightness_set_blocking = &ledcdev_set_blocking_uw_mc, + .led_cdev.brightness_get = &ledcdev_get_uw, + .led_cdev.brightness = UNIWILL_BRIGHTNESS_DEFAULT, + .num_colors = 3, + .subled_info = cdev_kb_uw_mc_subled +}; + static int uw_kbd_bl_init(struct platform_device *dev) { int status = 0; @@ -547,6 +592,9 @@ static int uw_kbd_bl_init(struct platform_device *dev) // Start periodic checking of animation, set and enable bl when done timer_setup(&uw_kbd_bl_init_timer, uw_kbd_bl_init_ready_check, 0); mod_timer(&uw_kbd_bl_init_timer, jiffies + msecs_to_jiffies(uw_kbd_bl_init_check_interval_ms)); + + // Register leds sysfs interface + devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_uw_mc); } else { // For non-RGB versions // Enable keyboard backlight immediately (should it be disabled) @@ -828,3 +876,5 @@ struct tuxedo_keyboard_driver uniwill_keyboard_driver = { .probe = uniwill_keyboard_probe, .key_map = uniwill_wmi_keymap, }; + +#endif // UNIWILL_KEYBOARD_H From dbd467bcd48a5be2cab7ac67976dc59e5c9fa03a Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 10:57:20 +0200 Subject: [PATCH 12/59] Rework to switch from old platform sysfs interface to standardised leds sysfs interface --- Makefile | 4 +- src/clevo_interfaces.h | 14 + src/clevo_keyboard.h | 800 ++++------------------------------- src/clevo_leds.c | 285 +++++++++++++ src/clevo_leds.h | 39 ++ src/tuxedo_keyboard_common.h | 3 +- src/uniwill_keyboard.h | 1 + 7 files changed, 431 insertions(+), 715 deletions(-) create mode 100644 src/clevo_leds.c create mode 100644 src/clevo_leds.h diff --git a/Makefile b/Makefile index c60cf4d..75dc1a1 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,14 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := ./src/tuxedo_keyboard.o \ +obj-m := tuxedo_keyboard.o \ ./src/clevo_wmi.o \ ./src/clevo_acpi.o \ ./src/tuxedo_io/tuxedo_io.o \ ./src/uniwill_wmi.o +tuxedo_keyboard-y := ./src/tuxedo_keyboard.o ./src/clevo_leds.o + PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index c3226cd..a624258 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -38,6 +38,10 @@ #define CLEVO_CMD_GET_FLIGHTMODE_SW 0x07 #define CLEVO_CMD_GET_TOUCHPAD_SW 0x09 +#define CLEVO_CMD_GET_EVENT 0x01 + +#define CLEVO_CMD_GET_SPECS 0x0D // Returns buffer -> only works with clevo_evaluate_method2 + // The clevo set commands expect a parameter #define CLEVO_CMD_SET_FANSPEED_VALUE 0x68 #define CLEVO_CMD_SET_FANSPEED_AUTO 0x69 @@ -46,6 +50,16 @@ #define CLEVO_CMD_SET_FLIGHTMODE_SW 0x20 #define CLEVO_CMD_SET_TOUCHPAD_SW 0x2a +#define CLEVO_CMD_SET_KB_LEDS 0x67 // used to set color, brightness, blinking pattern, etc. + +#define CLEVO_CMD_SET_EVENTS_ENABLED 0x46 + +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 0xF0000000 // 1-zone RGB and 3-zone RGB left +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 0xF1000000 // 3-zone RGB center +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 0xF2000000 // 3-Zone RGB right +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_3 0xF3000000 // Unused on all known Clevo devices +#define CLEVO_CMD_SET_KB_LEDS_SUB_BRIGHTNESS 0xF4000000 + #define CLEVO_CMD_OPT 0x79 #define CLEVO_OPT_SUBCMD_SET_PERF_PROF 0x19 diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 09631b8..80701f4 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -21,45 +21,23 @@ #include "tuxedo_keyboard_common.h" #include "clevo_interfaces.h" - -#include -#include - -#define BRIGHTNESS_MIN 0 -#define BRIGHTNESS_MAX 255 -#define BRIGHTNESS_DEFAULT BRIGHTNESS_MAX - -#define REGION_LEFT 0xF0000000 -#define REGION_CENTER 0xF1000000 -#define REGION_RIGHT 0xF2000000 -#define REGION_EXTRA 0xF3000000 - -#define KEYBOARD_BRIGHTNESS 0xF4000000 - -#define KB_COLOR_DEFAULT 0xFFFFFF // White -#define DEFAULT_BLINKING_PATTERN 0 - -// Submethod IDs for the CLEVO_GET interface method -#define CLEVO_METHOD_ID_GET_EVENT 0x01 -#define CLEVO_METHOD_ID_GET_AP 0x46 -#define CLEVO_METHOD_ID_SET_KB_LEDS 0x67 /* used to set color, brightness, - blinking pattern, etc. */ -#define CLEVO_METHOD_ID_GET_SPECS 0x0D // only works with clevo_evaluate_method2 - +#include "clevo_leds.h" // Clevo event codes -#define CLEVO_EVENT_DECREASE_BACKLIGHT 0x81 -#define CLEVO_EVENT_INCREASE_BACKLIGHT 0x82 -#define CLEVO_EVENT_NEXT_BLINKING_PATTERN 0x83 -#define CLEVO_EVENT_TOGGLE_STATE 0x9F +#define CLEVO_EVENT_KB_LEDS_DECREASE 0x81 +#define CLEVO_EVENT_KB_LEDS_INCREASE 0x82 +#define CLEVO_EVENT_KB_LEDS_CYCLE_MODE 0x83 +#define CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS 0x8A +#define CLEVO_EVENT_KB_LEDS_TOGGLE 0x9F -#define CLEVO_EVENT_CYCLE_BRIGHTNESS 0x8A -#define CLEVO_EVENT_TOUCHPAD_TOGGLE 0x5D -#define CLEVO_EVENT_TOUCHPAD_OFF 0xFC -#define CLEVO_EVENT_TOUCHPAD_ON 0xFD +#define CLEVO_EVENT_TOUCHPAD_TOGGLE 0x5D +#define CLEVO_EVENT_TOUCHPAD_OFF 0xFC +#define CLEVO_EVENT_TOUCHPAD_ON 0xFD -#define CLEVO_EVENT_RFKILL1 0x85 -#define CLEVO_EVENT_RFKILL2 0x86 +#define CLEVO_EVENT_RFKILL1 0x85 +#define CLEVO_EVENT_RFKILL2 0x86 + +#define CLEVO_KB_MODE_DEFAULT 0 // "CUSTOM"/Static Color struct tuxedo_keyboard_driver clevo_keyboard_driver; @@ -68,18 +46,9 @@ static struct clevo_interfaces_t { struct clevo_interface_t *acpi; } clevo_interfaces; -enum clevo_kb_backlight_type { - CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, - CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR = 0x01, - CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB = 0x02, - CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB = 0x06, - CLEVO_KB_BACKLIGHT_TYPE_PER_KEY_RGB = 0xf3 -}; - struct clevo_interface_t *active_clevo_interface; -void clevo_keyboard_write_state(void); -void clevo_keyboard_event_callb(u32 event); +void clevo_keyboard_event_callb(u32 event); // TODO Reorder to not require forward declaration? static DEFINE_MUTEX(clevo_keyboard_interface_modification_lock); @@ -94,7 +63,7 @@ u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) // Only use wmi if there is no other current interface if (ZERO_OR_NULL_PTR(active_clevo_interface)) { pr_debug("enable wmi events\n"); - clevo_interfaces.wmi->method_call(0x46, 0, NULL); + clevo_interfaces.wmi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); active_clevo_interface = clevo_interfaces.wmi; } @@ -104,7 +73,7 @@ u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) clevo_interfaces.acpi->event_callb = clevo_keyboard_event_callb; pr_debug("enable acpi events (takes priority)\n"); - clevo_interfaces.acpi->method_call(0x46, 0, NULL); + clevo_interfaces.acpi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); active_clevo_interface = clevo_interfaces.acpi; } else { // Not recognized interface @@ -149,12 +118,12 @@ EXPORT_SYMBOL(clevo_keyboard_remove_interface); static struct key_entry clevo_keymap[] = { // Keyboard backlight (RGB versions) - { KE_KEY, CLEVO_EVENT_DECREASE_BACKLIGHT, { KEY_KBDILLUMDOWN } }, - { KE_KEY, CLEVO_EVENT_INCREASE_BACKLIGHT, { KEY_KBDILLUMUP } }, - { KE_KEY, CLEVO_EVENT_TOGGLE_STATE, { KEY_KBDILLUMTOGGLE } }, - { KE_KEY, CLEVO_EVENT_NEXT_BLINKING_PATTERN, { KEY_LIGHTS_TOGGLE } }, + { KE_KEY, CLEVO_EVENT_KB_LEDS_DECREASE, { KEY_KBDILLUMDOWN } }, + { KE_KEY, CLEVO_EVENT_KB_LEDS_INCREASE, { KEY_KBDILLUMUP } }, + { KE_KEY, CLEVO_EVENT_KB_LEDS_TOGGLE, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_MODE, { KEY_LIGHTS_TOGGLE } }, // Single cycle key (white only versions) - { KE_KEY, CLEVO_EVENT_CYCLE_BRIGHTNESS, { KEY_KBDILLUMUP } }, + { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS, { KEY_KBDILLUMTOGGLE } }, //FIXME Cycle in driver or toggle in desktop environment? // Touchpad // The weirdly named touchpad toggle key that is implemented as KEY_F21 "everywhere" @@ -183,23 +152,8 @@ static struct key_entry clevo_keymap[] = { // Keyboard struct struct kbd_led_state_t { - u8 has_left; - u8 has_center; - u8 has_right; - u8 has_extra; u8 has_mode; - u8 has_brightness; - u8 enabled; - - struct { - u32 left; - u32 center; - u32 right; - u32 extra; - } color; - - u8 brightness; - u8 blinking_pattern; + u8 mode; u8 whole_kbd_color; }; @@ -209,122 +163,28 @@ struct blinking_pattern_t { const char *const name; }; - -static int blinking_pattern_id_validator(const char *value, - const struct kernel_param *blinking_pattern_param); -static const struct kernel_param_ops param_ops_mode_ops = { - .set = blinking_pattern_id_validator, - .get = param_get_int, +static struct blinking_pattern_t kbd_backlight_modes[] = { + { .key = 0, .value = 0x00000000, .name = "CUSTOM"}, + { .key = 1, .value = 0x1002a000, .name = "BREATHE"}, + { .key = 2, .value = 0x33010000, .name = "CYCLE"}, + { .key = 3, .value = 0x80000000, .name = "DANCE"}, + { .key = 4, .value = 0xA0000000, .name = "FLASH"}, + { .key = 5, .value = 0x70000000, .name = "RANDOM_COLOR"}, + { .key = 6, .value = 0x90000000, .name = "TEMPO"}, + { .key = 7, .value = 0xB0000000, .name = "WAVE"} }; -static uint param_color_left = KB_COLOR_DEFAULT; -module_param_named(color_left, param_color_left, uint, S_IRUSR); -MODULE_PARM_DESC(color_left, "Color for the Left Region"); - -static uint param_color_center = KB_COLOR_DEFAULT; -module_param_named(color_center, param_color_center, uint, S_IRUSR); -MODULE_PARM_DESC(color_center, "Color for the Center Region"); - -static uint param_color_right = KB_COLOR_DEFAULT; -module_param_named(color_right, param_color_right, uint, S_IRUSR); -MODULE_PARM_DESC(color_right, "Color for the Right Region"); - -static uint param_color_extra = KB_COLOR_DEFAULT; -module_param_named(color_extra, param_color_extra, uint, S_IRUSR); -MODULE_PARM_DESC(color_extra, "Color for the Extra Region"); - -static ushort param_blinking_pattern = DEFAULT_BLINKING_PATTERN; -module_param_cb(mode, ¶m_ops_mode_ops, ¶m_blinking_pattern, S_IRUSR); -MODULE_PARM_DESC(mode, "Set the keyboard backlight blinking pattern"); - -static bool param_state = true; -module_param_named(state, param_state, bool, S_IRUSR); -MODULE_PARM_DESC(state, - "Set the State of the Keyboard TRUE = ON | FALSE = OFF"); - static struct kbd_led_state_t kbd_led_state = { - .has_left = 0, - .has_center = 0, - .has_right = 0, - .has_extra = 0, - .has_mode = 0, - .has_brightness = 0, - .enabled = 1, - .color = { - .left = KB_COLOR_DEFAULT, .center = KB_COLOR_DEFAULT, - .right = KB_COLOR_DEFAULT, .extra = KB_COLOR_DEFAULT - }, - .brightness = BRIGHTNESS_DEFAULT, - .blinking_pattern = DEFAULT_BLINKING_PATTERN, - .whole_kbd_color = 7 + .has_mode = 1, + .mode = CLEVO_KB_MODE_DEFAULT, + .whole_kbd_color = 7, }; -static struct blinking_pattern_t blinking_patterns[] = { - { .key = 0,.value = 0,.name = "CUSTOM"}, - { .key = 1,.value = 0x1002a000,.name = "BREATHE"}, - { .key = 2,.value = 0x33010000,.name = "CYCLE"}, - { .key = 3,.value = 0x80000000,.name = "DANCE"}, - { .key = 4,.value = 0xA0000000,.name = "FLASH"}, - { .key = 5,.value = 0x70000000,.name = "RANDOM_COLOR"}, - { .key = 6,.value = 0x90000000,.name = "TEMPO"}, - { .key = 7,.value = 0xB0000000,.name = "WAVE"} -}; - -// Sysfs Interface Methods -// Sysfs Interface for the keyboard state (ON / OFF) -static ssize_t show_state_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%d\n", kbd_led_state.enabled); -} - -// Sysfs Interface for the color of the left side (Color as hexvalue) -static ssize_t show_color_left_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%06x\n", kbd_led_state.color.left); -} - -// Sysfs Interface for the color of the center (Color as hexvalue) -static ssize_t show_color_center_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%06x\n", kbd_led_state.color.center); -} - -// Sysfs Interface for the color of the right side (Color as hexvalue) -static ssize_t show_color_right_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%06x\n", kbd_led_state.color.right); -} - -// Sysfs Interface for the color of the extra region (Color as hexvalue) -static ssize_t show_color_extra_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%06x\n", kbd_led_state.color.extra); -} - -// Sysfs Interface for the keyboard brightness (unsigned int) -static ssize_t show_brightness_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%d\n", kbd_led_state.brightness); -} - // Sysfs Interface for the backlight blinking pattern -static ssize_t show_blinking_patterns_fs(struct device *child, struct device_attribute *attr, +static ssize_t show_kbd_backlight_modes_fs(struct device *child, struct device_attribute *attr, char *buffer) { - return sprintf(buffer, "%d\n", kbd_led_state.blinking_pattern); -} - -// Sysfs Interface for if the keyboard has extra region -static ssize_t show_hasextra_fs(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%d\n", kbd_led_state.has_extra); + return sprintf(buffer, "%d\n", kbd_led_state.mode); } u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result) @@ -373,33 +233,6 @@ u32 clevo_get_active_interface_id(char **id_str) } EXPORT_SYMBOL(clevo_get_active_interface_id); -static void set_brightness(u8 brightness) -{ - TUXEDO_INFO("Set brightness on %d", brightness); - if (!clevo_evaluate_method - (CLEVO_METHOD_ID_SET_KB_LEDS, 0xF4000000 | brightness, NULL)) { - kbd_led_state.brightness = brightness; - } -} - -static ssize_t set_brightness_fs(struct device *child, - struct device_attribute *attr, - const char *buffer, size_t size) -{ - unsigned int val; - // hier unsigned? - - int err = kstrtouint(buffer, 0, &val); - if (err) { - return err; - } - - val = clamp_t(u8, val, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - set_brightness(val); - - return size; -} - static int set_enabled_cmd(u8 state) { u32 cmd = 0xE0000000; @@ -411,126 +244,7 @@ static int set_enabled_cmd(u8 state) cmd |= 0x07F001; } - return clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, cmd, NULL); -} - -static void set_enabled(u8 state) -{ - if (!set_enabled_cmd(state)) { - kbd_led_state.enabled = state; - } -} - -static ssize_t set_state_fs(struct device *child, struct device_attribute *attr, - const char *buffer, size_t size) -{ - unsigned int state; - - int err = kstrtouint(buffer, 0, &state); - if (err) { - return err; - } - - state = clamp_t(u8, state, 0, 1); - - set_enabled(state); - - return size; -} - -static int set_color(u32 region, u32 color) -{ - u32 cset = - ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | - ((color & 0x00FF00) >> 8); - u32 clevo_submethod_arg = region | cset; - - TUXEDO_DEBUG("Set Color '%08x' for region '%08x'", color, region); - - return clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, clevo_submethod_arg, NULL); -} -static int set_color_code_region(u32 region, u32 colorcode) -{ - int err; - if (0 == (err = set_color(region, colorcode))) { - // after succesfully setting color, update our state struct - // depending on which region was changed - switch (region) { - case REGION_LEFT: - kbd_led_state.color.left = colorcode; - break; - case REGION_CENTER: - kbd_led_state.color.center = colorcode; - break; - case REGION_RIGHT: - kbd_led_state.color.right = colorcode; - break; - case REGION_EXTRA: - kbd_led_state.color.extra = colorcode; - break; - } - } - - return err; -} - -static int set_color_string_region(const char *color_string, size_t size, u32 region) -{ - u32 colorcode; - int err = kstrtouint(color_string, 0, &colorcode); - - if (err) { - return err; - } - - if (!set_color(region, colorcode)) { - // after succesfully setting color, update our state struct - // depending on which region was changed - switch (region) { - case REGION_LEFT: - kbd_led_state.color.left = colorcode; - break; - case REGION_CENTER: - kbd_led_state.color.center = colorcode; - break; - case REGION_RIGHT: - kbd_led_state.color.right = colorcode; - break; - case REGION_EXTRA: - kbd_led_state.color.extra = colorcode; - break; - } - } - - return size; -} - -static ssize_t set_color_left_fs(struct device *child, - struct device_attribute *attr, - const char *color_string, size_t size) -{ - return set_color_string_region(color_string, size, REGION_LEFT); -} - -static ssize_t set_color_center_fs(struct device *child, - struct device_attribute *attr, - const char *color_string, size_t size) -{ - return set_color_string_region(color_string, size, REGION_CENTER); -} - -static ssize_t set_color_right_fs(struct device *child, - struct device_attribute *attr, - const char *color_string, size_t size) -{ - return set_color_string_region(color_string, size, REGION_RIGHT); -} - -static ssize_t set_color_extra_fs(struct device *child, - struct device_attribute *attr, - const char *color_string, size_t size) -{ - return set_color_string_region(color_string, size, REGION_EXTRA); + return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, cmd, NULL); } static int set_next_color_whole_kb(void) @@ -549,77 +263,71 @@ static int set_next_color_whole_kb(void) new_color_id, new_color_code); /* Set color on all four regions*/ - set_color_code_region(REGION_LEFT, new_color_code); - set_color_code_region(REGION_CENTER, new_color_code); - set_color_code_region(REGION_RIGHT, new_color_code); - set_color_code_region(REGION_EXTRA, new_color_code); - + clevo_leds_set_color_extern(new_color_code); kbd_led_state.whole_kbd_color = new_color_id; return 0; } -static void set_blinking_pattern(u8 blinkling_pattern) +static void set_kbd_backlight_mode(u8 kbd_backlight_mode) { - TUXEDO_INFO("set_mode on %s", blinking_patterns[blinkling_pattern].name); + TUXEDO_INFO("Set keyboard backlight mode on %s", kbd_backlight_modes[kbd_backlight_mode].name); - if (!clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, blinking_patterns[blinkling_pattern].value, NULL)) { + if (!clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, kbd_backlight_modes[kbd_backlight_mode].value, NULL)) { // method was succesfull so update ur internal state struct - kbd_led_state.blinking_pattern = blinkling_pattern; - } - - if (blinkling_pattern == 0) { // 0 is the "custom" blinking pattern - - // so just set all regions to the stored colors - set_color(REGION_LEFT, kbd_led_state.color.left); - set_color(REGION_CENTER, kbd_led_state.color.center); - set_color(REGION_RIGHT, kbd_led_state.color.right); - - if (kbd_led_state.has_extra == 1) { - set_color(REGION_EXTRA, kbd_led_state.color.extra); - } + kbd_led_state.mode = kbd_backlight_mode; } } -static ssize_t set_blinking_pattern_fs(struct device *child, +static ssize_t set_kbd_backlight_mode_fs(struct device *child, struct device_attribute *attr, const char *buffer, size_t size) { - unsigned int blinking_pattern; + unsigned int kbd_backlight_mode; - int err = kstrtouint(buffer, 0, &blinking_pattern); + int err = kstrtouint(buffer, 0, &kbd_backlight_mode); if (err) { return err; } - blinking_pattern = clamp_t(u8, blinking_pattern, 0, ARRAY_SIZE(blinking_patterns) - 1); - set_blinking_pattern(blinking_pattern); + kbd_backlight_mode = clamp_t(u8, kbd_backlight_mode, 0, ARRAY_SIZE(kbd_backlight_modes) - 1); + set_kbd_backlight_mode(kbd_backlight_mode); return size; } -static int blinking_pattern_id_validator(const char *value, - const struct kernel_param *blinking_pattern_param) +static int kbd_backlight_mode_id_validator(const char *value, + const struct kernel_param *kbd_backlight_mode_param) { - int blinking_pattern = 0; + int kbd_backlight_mode = 0; - if (kstrtoint(value, 10, &blinking_pattern) != 0 - || blinking_pattern < 0 - || blinking_pattern > (ARRAY_SIZE(blinking_patterns) - 1)) { + if (kstrtoint(value, 10, &kbd_backlight_mode) != 0 + || kbd_backlight_mode < 0 + || kbd_backlight_mode > (ARRAY_SIZE(kbd_backlight_modes) - 1)) { return -EINVAL; } - return param_set_int(value, blinking_pattern_param); + return param_set_int(value, kbd_backlight_mode_param); } +static const struct kernel_param_ops param_ops_mode_ops = { + .set = kbd_backlight_mode_id_validator, + .get = param_get_int, +}; + +static u8 param_kbd_backlight_mode = CLEVO_KB_MODE_DEFAULT; +module_param_cb(kbd_backlight_mode, ¶m_ops_mode_ops, ¶m_kbd_backlight_mode, S_IRUSR); +MODULE_PARM_DESC(kbd_backlight_mode, "Set the keyboard backlight blinking pattern"); + +// TODO remove static int brightness_validator(const char *value, const struct kernel_param *brightness_param) { int brightness = 0; if (kstrtoint(value, 10, &brightness) != 0 - || brightness < BRIGHTNESS_MIN - || brightness > BRIGHTNESS_MAX) { + || brightness < 0 + || brightness > 255) { return -EINVAL; } @@ -630,338 +338,37 @@ void clevo_keyboard_event_callb(u32 event) { u32 key_event = event; - // TUXEDO_DEBUG("clevo event: %0#6x\n", event); + TUXEDO_DEBUG("Clevo event: %0#6x\n", event); switch (key_event) { - case CLEVO_EVENT_DECREASE_BACKLIGHT: - if (kbd_led_state.brightness == BRIGHTNESS_MIN - || (kbd_led_state.brightness - BRIGHTNESS_STEP) < BRIGHTNESS_MIN) { - set_brightness(BRIGHTNESS_MIN); - } else { - set_brightness(kbd_led_state.brightness - BRIGHTNESS_STEP); - } - - break; - - case CLEVO_EVENT_INCREASE_BACKLIGHT: - if (kbd_led_state.brightness == BRIGHTNESS_MAX - || (kbd_led_state.brightness + BRIGHTNESS_STEP) > BRIGHTNESS_MAX) { - set_brightness(BRIGHTNESS_MAX); - } else { - set_brightness(kbd_led_state.brightness + BRIGHTNESS_STEP); - } - - break; - -// case CLEVO_EVENT_NEXT_BLINKING_PATTERN: -// set_blinking_pattern((kbd_led_state.blinking_pattern + 1) > -// (ARRAY_SIZE(blinking_patterns) - 1) ? 0 : (kbd_led_state.blinking_pattern + 1)); -// break; - - case CLEVO_EVENT_NEXT_BLINKING_PATTERN: - set_next_color_whole_kb(); - break; - - case CLEVO_EVENT_TOGGLE_STATE: - set_enabled(kbd_led_state.enabled == 0 ? 1 : 0); - break; - - default: - break; + case CLEVO_EVENT_KB_LEDS_CYCLE_MODE: + set_next_color_whole_kb(); + break; + default: + break; } if (current_driver != NULL && current_driver->input_device != NULL) { - if (!sparse_keymap_report_known_event( - current_driver->input_device, key_event, 1, true)) { - TUXEDO_DEBUG("Unknown key - %d (%0#6x)\n", key_event, - key_event); + if (!sparse_keymap_report_known_event(current_driver->input_device, key_event, 1, true)) { + TUXEDO_DEBUG("Unknown key - %d (%0#6x)\n", key_event, key_event); } } } // Sysfs attribute file permissions and method linking -static DEVICE_ATTR(state, 0644, show_state_fs, set_state_fs); -static DEVICE_ATTR(color_left, 0644, show_color_left_fs, set_color_left_fs); -static DEVICE_ATTR(color_center, 0644, show_color_center_fs, - set_color_center_fs); -static DEVICE_ATTR(color_right, 0644, show_color_right_fs, set_color_right_fs); -static DEVICE_ATTR(color_extra, 0644, show_color_extra_fs, set_color_extra_fs); -static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); -static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); -static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); - -static int ledcdev_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { - set_brightness(brightness); - return 0; -} - -static int ledcdev_set_blocking_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { - u32 region, colorcode; - struct led_classdev_mc *led_cdev_mc = lcdev_to_mccdev(led_cdev); - - pr_debug("ledcdev_set_blocking_mc() brightness 0x%02x\n", brightness); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].intensity 0x%02x\n", led_cdev_mc->subled_info[0].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].intensity 0x%02x\n", led_cdev_mc->subled_info[1].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].intensity 0x%02x\n", led_cdev_mc->subled_info[2].intensity); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[0].channel 0x%02x\n", led_cdev_mc->subled_info[0].channel); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[1].channel 0x%02x\n", led_cdev_mc->subled_info[1].channel); - pr_debug("ledcdev_set_blocking_mc() led_cdev_mc->subled_info[2].channel 0x%02x\n", led_cdev_mc->subled_info[2].channel); - - if (led_cdev_mc->subled_info[0].channel == 0) { - region = REGION_LEFT; - } - else if (led_cdev_mc->subled_info[0].channel == 1) { - region = REGION_CENTER; - } - else if (led_cdev_mc->subled_info[0].channel == 2) { - region = REGION_RIGHT; - } - else { - region = REGION_EXTRA; - } - - colorcode = (led_cdev_mc->subled_info[0].intensity << 16) + - (led_cdev_mc->subled_info[1].intensity << 8) + - led_cdev_mc->subled_info[2].intensity; - - if (!set_color(region, colorcode)) { - // after succesfully setting color, update our state struct - // depending on which region was changed - switch (region) { - case REGION_LEFT: - kbd_led_state.color.left = colorcode; - break; - case REGION_CENTER: - kbd_led_state.color.center = colorcode; - break; - case REGION_RIGHT: - kbd_led_state.color.right = colorcode; - break; - case REGION_EXTRA: - kbd_led_state.color.extra = colorcode; - break; - } - } - - set_brightness(brightness); - return 0; -} - -static enum led_brightness ledcdev_get(struct led_classdev *led_cdev) { - return kbd_led_state.brightness; -} - -static struct led_classdev cdev_kb = { - .name = KBUILD_MODNAME "::kbd_backlight", - .max_brightness = BRIGHTNESS_MAX, - .brightness_set_blocking = &ledcdev_set_blocking, - .brightness_get = &ledcdev_get, - .brightness = BRIGHTNESS_DEFAULT, -}; - -static struct led_classdev_mc cdev_kb_mc[3]; - -static struct mc_subled cdev_kb_mc_subled[3][3]; +static DEVICE_ATTR(kbd_backlight_mode, 0644, show_kbd_backlight_modes_fs, set_kbd_backlight_mode_fs); static void clevo_keyboard_init_device_interface(struct platform_device *dev) { - u32 status; - union acpi_object *result; - // The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To - // not break these, we set this as default for the time being, better having an extra sysfs entry without function than - // a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. - enum clevo_kb_backlight_type kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; - - status = clevo_evaluate_method2(CLEVO_METHOD_ID_GET_SPECS, 0, &result); - if (!status) { - if (result->type == ACPI_TYPE_BUFFER) { - pr_debug("CLEVO_METHOD_ID_GET_SPECS successful\n"); - kb_backlight_type = result->buffer.pointer[0x0f]; - } - else { - pr_debug("CLEVO_METHOD_ID_GET_SPECS return value has wrong type\n"); - } - ACPI_FREE(result); - } - else { - pr_debug("CLEVO_METHOD_ID_GET_SPECS failed\n"); - } - pr_debug("Keyboard Backlight Type: 0x%02x\n", kb_backlight_type); - // Setup sysfs - if (device_create_file(&dev->dev, &dev_attr_state) != 0) { - TUXEDO_ERROR("Sysfs attribute file creation failed for state\n"); - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB || - kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - if (device_create_file - (&dev->dev, &dev_attr_color_left) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color left\n"); - } - else { - kbd_led_state.has_left = 1; - } - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - if (device_create_file - (&dev->dev, &dev_attr_color_center) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color center\n"); - } - else { - kbd_led_state.has_center = 1; - } - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - if (device_create_file - (&dev->dev, &dev_attr_color_right) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color right\n"); - } - else { - kbd_led_state.has_right = 1; - } - } - - /*if (set_color(REGION_EXTRA, KB_COLOR_DEFAULT) != 0) { - TUXEDO_DEBUG("Keyboard does not support EXTRA Color"); - kbd_led_state.has_extra = 0; - } else { - kbd_led_state.has_extra = 1; - if (device_create_file - (&dev->dev, - &dev_attr_color_extra) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for color extra\n"); - } - - set_color(REGION_EXTRA, param_color_extra); - }*/ - kbd_led_state.has_extra = 0; // No known Clevo device using this region, set color check doesn't work. - - if (device_create_file(&dev->dev, &dev_attr_extra) != - 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for extra information flag\n"); - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - if (device_create_file(&dev->dev, &dev_attr_mode) != - 0) { + if (clevo_leds_get_backlight_type() == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + if (device_create_file(&dev->dev, &dev_attr_kbd_backlight_mode) != 0) { TUXEDO_ERROR("Sysfs attribute file creation failed for blinking pattern\n"); } else { kbd_led_state.has_mode = 1; } } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR || - kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB || - kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - if (device_create_file - (&dev->dev, &dev_attr_brightness) != 0) { - TUXEDO_ERROR - ("Sysfs attribute file creation failed for brightness\n"); - } - else { - kbd_led_state.has_brightness = 1; - } - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - led_classdev_register(&dev->dev, &cdev_kb); - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - cdev_kb_mc[0].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; - cdev_kb_mc[0].led_cdev.max_brightness = BRIGHTNESS_MAX; - cdev_kb_mc[0].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; - cdev_kb_mc[0].led_cdev.brightness_get = &ledcdev_get; - cdev_kb_mc[0].led_cdev.brightness = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].num_colors = 3; - cdev_kb_mc[0].subled_info = cdev_kb_mc_subled[0]; - cdev_kb_mc[0].subled_info[0].color_index = LED_COLOR_ID_RED; - cdev_kb_mc[0].subled_info[0].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[0].channel = 0; - cdev_kb_mc[0].subled_info[1].color_index = LED_COLOR_ID_GREEN; - cdev_kb_mc[0].subled_info[1].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[1].channel = 0; - cdev_kb_mc[0].subled_info[2].color_index = LED_COLOR_ID_BLUE; - cdev_kb_mc[0].subled_info[2].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[2].channel = 0; - devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[0]); - } - - if (kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - cdev_kb_mc[0].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; - cdev_kb_mc[0].led_cdev.max_brightness = BRIGHTNESS_MAX; - cdev_kb_mc[0].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; - cdev_kb_mc[0].led_cdev.brightness_get = &ledcdev_get; - cdev_kb_mc[0].led_cdev.brightness = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].num_colors = 3; - cdev_kb_mc[0].subled_info = cdev_kb_mc_subled[0]; - cdev_kb_mc[0].subled_info[0].color_index = LED_COLOR_ID_RED; - cdev_kb_mc[0].subled_info[0].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[0].channel = 0; - cdev_kb_mc[0].subled_info[1].color_index = LED_COLOR_ID_GREEN; - cdev_kb_mc[0].subled_info[1].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[1].channel = 0; - cdev_kb_mc[0].subled_info[2].color_index = LED_COLOR_ID_BLUE; - cdev_kb_mc[0].subled_info[2].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[0].subled_info[2].channel = 0; - devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[0]); - - cdev_kb_mc[1].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; - cdev_kb_mc[1].led_cdev.max_brightness = BRIGHTNESS_MAX; - cdev_kb_mc[1].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; - cdev_kb_mc[1].led_cdev.brightness_get = &ledcdev_get; - cdev_kb_mc[1].led_cdev.brightness = BRIGHTNESS_DEFAULT; - cdev_kb_mc[1].num_colors = 3; - cdev_kb_mc[1].subled_info = cdev_kb_mc_subled[1]; - cdev_kb_mc[1].subled_info[0].color_index = LED_COLOR_ID_RED; - cdev_kb_mc[1].subled_info[0].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[1].subled_info[0].channel = 1; - cdev_kb_mc[1].subled_info[1].color_index = LED_COLOR_ID_GREEN; - cdev_kb_mc[1].subled_info[1].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[1].subled_info[1].channel = 1; - cdev_kb_mc[1].subled_info[2].color_index = LED_COLOR_ID_BLUE; - cdev_kb_mc[1].subled_info[2].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[1].subled_info[2].channel = 1; - devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[1]); - - cdev_kb_mc[2].led_cdev.name = KBUILD_MODNAME "::kbd_backlight"; - cdev_kb_mc[2].led_cdev.max_brightness = BRIGHTNESS_MAX; - cdev_kb_mc[2].led_cdev.brightness_set_blocking = &ledcdev_set_blocking_mc; - cdev_kb_mc[2].led_cdev.brightness_get = &ledcdev_get; - cdev_kb_mc[2].led_cdev.brightness = BRIGHTNESS_DEFAULT; - cdev_kb_mc[2].num_colors = 3; - cdev_kb_mc[2].subled_info = cdev_kb_mc_subled[2]; - cdev_kb_mc[2].subled_info[0].color_index = LED_COLOR_ID_RED; - cdev_kb_mc[2].subled_info[0].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[2].subled_info[0].channel = 2; - cdev_kb_mc[2].subled_info[1].color_index = LED_COLOR_ID_GREEN; - cdev_kb_mc[2].subled_info[1].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[2].subled_info[1].channel = 2; - cdev_kb_mc[2].subled_info[2].color_index = LED_COLOR_ID_BLUE; - cdev_kb_mc[2].subled_info[2].intensity = BRIGHTNESS_DEFAULT; - cdev_kb_mc[2].subled_info[2].channel = 2; - devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_mc[2]); - } -} - -void clevo_keyboard_write_state(void) -{ - // Note: - // - set_blinking_pattern also writes colors - // - set_brightness, set_enabled, set_blinking_pattern - // still also update state - set_blinking_pattern(kbd_led_state.blinking_pattern); - set_brightness(kbd_led_state.brightness); - set_enabled(kbd_led_state.enabled); } /** @@ -981,20 +388,11 @@ int clevo_keyboard_init(void) { bool performance_profile_set_workaround; - // Init state from params - kbd_led_state.color.left = param_color_left; - kbd_led_state.color.center = param_color_center; - kbd_led_state.color.right = param_color_right; - kbd_led_state.color.extra = param_color_extra; + kbd_led_state.mode = param_kbd_backlight_mode; + set_kbd_backlight_mode(kbd_led_state.mode); - kbd_led_state.blinking_pattern = param_blinking_pattern; - - if (param_brightness > BRIGHTNESS_MAX) param_brightness = BRIGHTNESS_DEFAULT; - kbd_led_state.brightness = param_brightness; - - kbd_led_state.enabled = param_state; - - clevo_keyboard_write_state(); + clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); + set_enabled_cmd(1); // Workaround for firmware issue not setting selected performance profile. // Explicitly set "performance" perf. profile on init regardless of what is chosen @@ -1013,7 +411,7 @@ int clevo_keyboard_init(void) ; if (performance_profile_set_workaround) { TUXEDO_INFO("Performance profile 'performance' set workaround applied\n"); - clevo_evaluate_method(0x79, 0x19000002, NULL); + clevo_evaluate_method(CLEVO_CMD_OPT, 0x19000002, NULL); } return 0; @@ -1022,6 +420,7 @@ int clevo_keyboard_init(void) static int clevo_keyboard_probe(struct platform_device *dev) { clevo_keyboard_init_device_interface(dev); + clevo_leds_init(dev); clevo_keyboard_init(); return 0; @@ -1029,38 +428,15 @@ static int clevo_keyboard_probe(struct platform_device *dev) static void clevo_keyboard_remove_device_interface(struct platform_device *dev) { - device_remove_file(&dev->dev, &dev_attr_state); - - if (kbd_led_state.has_left == 1) { - device_remove_file(&dev->dev, &dev_attr_color_left); - } - - if (kbd_led_state.has_center == 1) { - device_remove_file(&dev->dev, &dev_attr_color_center); - } - - if (kbd_led_state.has_right == 1) { - device_remove_file(&dev->dev, &dev_attr_color_right); - } - - device_remove_file(&dev->dev, &dev_attr_extra); - if (kbd_led_state.has_mode == 1) { - device_remove_file(&dev->dev, &dev_attr_mode); - } - - if (kbd_led_state.has_brightness == 1) { - device_remove_file(&dev->dev, &dev_attr_brightness); - } - - if (kbd_led_state.has_extra == 1) { - device_remove_file(&dev->dev, &dev_attr_color_extra); + device_remove_file(&dev->dev, &dev_attr_kbd_backlight_mode); } } static int clevo_keyboard_remove(struct platform_device *dev) { clevo_keyboard_remove_device_interface(dev); + clevo_leds_remove(dev); return 0; } @@ -1073,10 +449,8 @@ static int clevo_keyboard_suspend(struct platform_device *dev, pm_message_t stat static int clevo_keyboard_resume(struct platform_device *dev) { - clevo_evaluate_method(CLEVO_METHOD_ID_GET_AP, 0, NULL); - - clevo_keyboard_write_state(); - + clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); + set_enabled_cmd(1); return 0; } diff --git a/src/clevo_leds.c b/src/clevo_leds.c new file mode 100644 index 0000000..7cbd3bf --- /dev/null +++ b/src/clevo_leds.c @@ -0,0 +1,285 @@ +/*! + * Copyright (c) 2018-2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-keyboard. + * + * tuxedo-keyboard 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 3 of the License, or + * (at your option) any later version. + * + * This software 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 software. If not, see . + */ + +#include "clevo_leds.h" + +#include "clevo_interfaces.h" + +#include +#include + +#define CLEVO_KBD_BRIGHTNESS_MIN 0 +#define CLEVO_KBD_BRIGHTNESS_MAX 255 +#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) + +#define CLEVO_KB_COLOR_DEFAULT_RED 0xFF +#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xFF +#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xFF +#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) + +// The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To +// not break these, we set this as default for the time being, better having an extra sysfs entry without function than +// a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. +static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; + +static int clevo_evaluate_set_brightness(u8 brightness) +{ + pr_debug("Set brightness on %d", brightness); + + return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, 0xF4000000 | brightness, NULL); +} + +static int clevo_evaluate_set_color(u32 zone, u32 color) +{ + u32 cset = ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | ((color & 0x00FF00) >> 8); + u32 clevo_submethod_arg = zone | cset; + + pr_debug("Set Color '%08x' for region '%08x'", color, zone); + + return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, clevo_submethod_arg, NULL); +} + +static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { + int ret = clevo_evaluate_set_brightness(brightness); + if (ret) { + pr_debug("clevo_leds_set_brightness(): clevo_evaluate_set_brightness() failed"); + return; + } + led_cdev->brightness = brightness; +} + +static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + int ret; + u32 zone, color; + struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); + + ret = clevo_evaluate_set_brightness(CLEVO_KBD_BRIGHTNESS_MAX); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed"); + return; + } + + zone = mcled_cdev->subled_info[0].channel; + + led_mc_calc_color_components(mcled_cdev, brightness); + color = (mcled_cdev->subled_info[0].brightness << 16) + + (mcled_cdev->subled_info[1].brightness << 8) + + mcled_cdev->subled_info[2].brightness; + + ret = clevo_evaluate_set_color(zone, color); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed"); + return; + } + led_cdev->brightness = brightness; +} + +static struct led_classdev clevo_led_cdev = { + .name = "rgb:kbd_backlight", + .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness_set = &clevo_leds_set_brightness, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT +}; + +static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + } + }, + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + } + }, + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + } + } +}; + +static struct led_classdev_mc clevo_mcled_cdevs[3] = { + { + .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .subled_info = clevo_mcled_cdevs_subleds[0] + }, + { + .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .subled_info = clevo_mcled_cdevs_subleds[1] + }, + { + .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .subled_info = clevo_mcled_cdevs_subleds[2] + } +}; + +int clevo_leds_init(struct platform_device *dev) +{ + u32 status; + union acpi_object *result; + + status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); + if (!status) { + if (result->type == ACPI_TYPE_BUFFER) { + pr_debug("CLEVO_CMD_GET_SPECS successful\n"); + clevo_kb_backlight_type = result->buffer.pointer[0x0f]; + } + else { + pr_debug("CLEVO_CMD_GET_SPECS return value has wrong type\n"); + } + ACPI_FREE(result); + } + else { + pr_debug("CLEVO_CMD_GET_SPECS failed\n"); + } + pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); + + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + led_classdev_register(&dev->dev, &clevo_led_cdev); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); + devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[1]); + devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[2]); + } + + return 0; +} +EXPORT_SYMBOL(clevo_leds_init); + +int clevo_leds_remove(struct platform_device *dev) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + led_classdev_unregister(&clevo_led_cdev); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[1]); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[2]); + } + + return 0; +} +EXPORT_SYMBOL(clevo_leds_remove); + +enum clevo_kb_backlight_types clevo_leds_get_backlight_type() { + return clevo_kb_backlight_type; +} +EXPORT_SYMBOL(clevo_leds_get_backlight_type); + +void clevo_leds_set_brightness_extern(u32 brightness) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + clevo_led_cdev.brightness_set(&clevo_led_cdev, brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); + clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, brightness); + clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, brightness); + } +} +EXPORT_SYMBOL(clevo_leds_set_brightness_extern); + +void clevo_leds_set_color_extern(u32 color) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[1].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[1].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[1].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[2].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[2].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[2].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + } +} +EXPORT_SYMBOL(clevo_leds_set_color_extern); + +MODULE_LICENSE("GPL"); diff --git a/src/clevo_leds.h b/src/clevo_leds.h new file mode 100644 index 0000000..e6bf721 --- /dev/null +++ b/src/clevo_leds.h @@ -0,0 +1,39 @@ +/*! + * Copyright (c) 2018-2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-keyboard. + * + * tuxedo-keyboard 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 3 of the License, or + * (at your option) any later version. + * + * This software 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 software. If not, see . + */ + +#ifndef CLEVO_LEDS_H +#define CLEVO_LEDS_H + +#include + +enum clevo_kb_backlight_types { + CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, + CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR = 0x01, + CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB = 0x02, + CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB = 0x06, + CLEVO_KB_BACKLIGHT_TYPE_PER_KEY_RGB = 0xf3 +}; + +int clevo_leds_init(struct platform_device *dev); +int clevo_leds_remove(struct platform_device *dev); +enum clevo_kb_backlight_types clevo_leds_get_backlight_type(void); +void clevo_leds_set_brightness_extern(u32 brightness); +void clevo_leds_set_color_extern(u32 color); + +#endif // CLEVO_LEDS_H diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 84f6059..60e62d8 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -129,6 +129,7 @@ static const struct kernel_param_ops param_ops_brightness_ops = { .get = param_get_int, }; +// TODO remove static ushort param_brightness = 0xffff; // Default unset value (higher than max) module_param_cb(brightness, ¶m_ops_brightness_ops, ¶m_brightness, S_IRUSR); @@ -139,4 +140,4 @@ static char param_color[COLOR_STRING_LEN]; module_param_string(color, param_color, COLOR_STRING_LEN, S_IRUSR); MODULE_PARM_DESC(color, "Preset color for the keyboard backlight as string"); -#endif \ No newline at end of file +#endif diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 46de633..0e03e61 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "uniwill_interfaces.h" From 47337549d7888aa1ad713743a93ca0abe15fa58d Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 11:47:10 +0200 Subject: [PATCH 13/59] Fix Makefile --- Makefile | 8 +------- src/Kbuild | 8 ++++++++ 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 src/Kbuild diff --git a/Makefile b/Makefile index 75dc1a1..5e908f8 100644 --- a/Makefile +++ b/Makefile @@ -16,13 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := tuxedo_keyboard.o \ - ./src/clevo_wmi.o \ - ./src/clevo_acpi.o \ - ./src/tuxedo_io/tuxedo_io.o \ - ./src/uniwill_wmi.o - -tuxedo_keyboard-y := ./src/tuxedo_keyboard.o ./src/clevo_leds.o +obj-m := src/ PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/src/Kbuild b/src/Kbuild new file mode 100644 index 0000000..d8e05ef --- /dev/null +++ b/src/Kbuild @@ -0,0 +1,8 @@ +obj-m := tuxedo_keyboard.o \ + clevo_wmi.o \ + clevo_acpi.o \ + tuxedo_io/tuxedo_io.o \ + uniwill_wmi.o + +clevo_wmi-y := clevo_wmi.o clevo_leds.o +clevo_acpi-y := clevo_acpi.o clevo_leds.o From 1f2fad72deb5b4518694619a0c92771468b12106 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 11:55:12 +0200 Subject: [PATCH 14/59] Fix Makefile --- src/Kbuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kbuild b/src/Kbuild index d8e05ef..bcf4ac3 100644 --- a/src/Kbuild +++ b/src/Kbuild @@ -4,5 +4,5 @@ obj-m := tuxedo_keyboard.o \ tuxedo_io/tuxedo_io.o \ uniwill_wmi.o -clevo_wmi-y := clevo_wmi.o clevo_leds.o -clevo_acpi-y := clevo_acpi.o clevo_leds.o +clevo_wmi-y := clevo_leds.o +clevo_acpi-y := clevo_leds.o From d3be79612af0d3f5a706dab594dbeac68a627964 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 17:59:37 +0200 Subject: [PATCH 15/59] Fix crash --- src/Kbuild | 4 +- src/clevo_keyboard.h | 4 +- src/clevo_leds.c | 267 ------------------------------------- src/clevo_leds.h | 304 +++++++++++++++++++++++++++++++++++++++++++ tuxedo_keyboard.conf | 2 +- 5 files changed, 310 insertions(+), 271 deletions(-) diff --git a/src/Kbuild b/src/Kbuild index bcf4ac3..0d77606 100644 --- a/src/Kbuild +++ b/src/Kbuild @@ -4,5 +4,5 @@ obj-m := tuxedo_keyboard.o \ tuxedo_io/tuxedo_io.o \ uniwill_wmi.o -clevo_wmi-y := clevo_leds.o -clevo_acpi-y := clevo_leds.o +#clevo_wmi-y := clevo_leds.o +#clevo_acpi-y := clevo_leds.o diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 80701f4..9dee864 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -419,8 +419,10 @@ int clevo_keyboard_init(void) static int clevo_keyboard_probe(struct platform_device *dev) { - clevo_keyboard_init_device_interface(dev); clevo_leds_init(dev); + // clevo_keyboard_init_device_interface() must come after clevo_leds_init() + // to know keyboard backlight type + clevo_keyboard_init_device_interface(dev); clevo_keyboard_init(); return 0; diff --git a/src/clevo_leds.c b/src/clevo_leds.c index 7cbd3bf..9310504 100644 --- a/src/clevo_leds.c +++ b/src/clevo_leds.c @@ -16,270 +16,3 @@ * You should have received a copy of the GNU General Public License * along with this software. If not, see . */ - -#include "clevo_leds.h" - -#include "clevo_interfaces.h" - -#include -#include - -#define CLEVO_KBD_BRIGHTNESS_MIN 0 -#define CLEVO_KBD_BRIGHTNESS_MAX 255 -#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) - -#define CLEVO_KB_COLOR_DEFAULT_RED 0xFF -#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xFF -#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xFF -#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) - -// The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To -// not break these, we set this as default for the time being, better having an extra sysfs entry without function than -// a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. -static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; - -static int clevo_evaluate_set_brightness(u8 brightness) -{ - pr_debug("Set brightness on %d", brightness); - - return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, 0xF4000000 | brightness, NULL); -} - -static int clevo_evaluate_set_color(u32 zone, u32 color) -{ - u32 cset = ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | ((color & 0x00FF00) >> 8); - u32 clevo_submethod_arg = zone | cset; - - pr_debug("Set Color '%08x' for region '%08x'", color, zone); - - return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, clevo_submethod_arg, NULL); -} - -static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { - int ret = clevo_evaluate_set_brightness(brightness); - if (ret) { - pr_debug("clevo_leds_set_brightness(): clevo_evaluate_set_brightness() failed"); - return; - } - led_cdev->brightness = brightness; -} - -static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { - int ret; - u32 zone, color; - struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); - - ret = clevo_evaluate_set_brightness(CLEVO_KBD_BRIGHTNESS_MAX); - if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed"); - return; - } - - zone = mcled_cdev->subled_info[0].channel; - - led_mc_calc_color_components(mcled_cdev, brightness); - color = (mcled_cdev->subled_info[0].brightness << 16) + - (mcled_cdev->subled_info[1].brightness << 8) + - mcled_cdev->subled_info[2].brightness; - - ret = clevo_evaluate_set_color(zone, color); - if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed"); - return; - } - led_cdev->brightness = brightness; -} - -static struct led_classdev clevo_led_cdev = { - .name = "rgb:kbd_backlight", - .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .brightness_set = &clevo_leds_set_brightness, - .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT -}; - -static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { - { - { - .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_RED, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 - }, - { - .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 - }, - { - .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 - } - }, - { - { - .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_RED, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 - }, - { - .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 - }, - { - .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 - } - }, - { - { - .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_RED, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 - }, - { - .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 - }, - { - .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, - .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 - } - } -}; - -static struct led_classdev_mc clevo_mcled_cdevs[3] = { - { - .led_cdev.name = "rgb:kbd_backlight", - .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, - .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, - .subled_info = clevo_mcled_cdevs_subleds[0] - }, - { - .led_cdev.name = "rgb:kbd_backlight", - .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, - .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, - .subled_info = clevo_mcled_cdevs_subleds[1] - }, - { - .led_cdev.name = "rgb:kbd_backlight", - .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, - .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, - .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, - .subled_info = clevo_mcled_cdevs_subleds[2] - } -}; - -int clevo_leds_init(struct platform_device *dev) -{ - u32 status; - union acpi_object *result; - - status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); - if (!status) { - if (result->type == ACPI_TYPE_BUFFER) { - pr_debug("CLEVO_CMD_GET_SPECS successful\n"); - clevo_kb_backlight_type = result->buffer.pointer[0x0f]; - } - else { - pr_debug("CLEVO_CMD_GET_SPECS return value has wrong type\n"); - } - ACPI_FREE(result); - } - else { - pr_debug("CLEVO_CMD_GET_SPECS failed\n"); - } - pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); - - if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - led_classdev_register(&dev->dev, &clevo_led_cdev); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); - devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[1]); - devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[2]); - } - - return 0; -} -EXPORT_SYMBOL(clevo_leds_init); - -int clevo_leds_remove(struct platform_device *dev) { - if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - led_classdev_unregister(&clevo_led_cdev); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); - devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[1]); - devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[2]); - } - - return 0; -} -EXPORT_SYMBOL(clevo_leds_remove); - -enum clevo_kb_backlight_types clevo_leds_get_backlight_type() { - return clevo_kb_backlight_type; -} -EXPORT_SYMBOL(clevo_leds_get_backlight_type); - -void clevo_leds_set_brightness_extern(u32 brightness) { - if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - clevo_led_cdev.brightness_set(&clevo_led_cdev, brightness); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); - clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, brightness); - clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, brightness); - } -} -EXPORT_SYMBOL(clevo_leds_set_brightness_extern); - -void clevo_leds_set_color_extern(u32 color) { - if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; - clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; - clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); - } - else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { - clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; - clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; - clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); - clevo_mcled_cdevs[1].subled_info[0].intensity = (color >> 16) & 0xff; - clevo_mcled_cdevs[1].subled_info[1].intensity = (color >> 8) & 0xff; - clevo_mcled_cdevs[1].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); - clevo_mcled_cdevs[2].subled_info[0].intensity = (color >> 16) & 0xff; - clevo_mcled_cdevs[2].subled_info[1].intensity = (color >> 8) & 0xff; - clevo_mcled_cdevs[2].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); - } -} -EXPORT_SYMBOL(clevo_leds_set_color_extern); - -MODULE_LICENSE("GPL"); diff --git a/src/clevo_leds.h b/src/clevo_leds.h index e6bf721..d56056f 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -21,6 +21,7 @@ #define CLEVO_LEDS_H #include +#include enum clevo_kb_backlight_types { CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, @@ -36,4 +37,307 @@ enum clevo_kb_backlight_types clevo_leds_get_backlight_type(void); void clevo_leds_set_brightness_extern(u32 brightness); void clevo_leds_set_color_extern(u32 color); +// TODO The following should go into a seperate .c file, but for this to work more reworking is required in the tuxedo_keyboard structure. + +#include "clevo_leds.h" + +#include "clevo_interfaces.h" + +#include +#include + +#define CLEVO_KBD_BRIGHTNESS_MIN 0 +#define CLEVO_KBD_BRIGHTNESS_MAX 255 +#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) + +#define CLEVO_KB_COLOR_DEFAULT_RED 0xFF +#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xFF +#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xFF +#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) + +// The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To +// not break these, we set this as default for the time being, better having an extra sysfs entry without function than +// a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. +static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; +static bool leds_initiaized; + +static int clevo_evaluate_set_brightness(u8 brightness) +{ + pr_debug("Set brightness on %d\n", brightness); + + return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, 0xF4000000 | brightness, NULL); +} + +static int clevo_evaluate_set_color(u32 zone, u32 color) +{ + u32 cset = ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | ((color & 0x00FF00) >> 8); + u32 clevo_submethod_arg = zone | cset; + + pr_debug("Set Color 0x%08x for region 0x%08x\n", color, zone); + + return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, clevo_submethod_arg, NULL); +} + +static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { + int ret = clevo_evaluate_set_brightness(brightness); + if (ret) { + pr_debug("clevo_leds_set_brightness(): clevo_evaluate_set_brightness() failed\n"); + return; + } + led_cdev->brightness = brightness; +} + +static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + int ret; + u32 zone, color; + struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); + + ret = clevo_evaluate_set_brightness(CLEVO_KBD_BRIGHTNESS_MAX); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed\n"); + return; + } + + zone = mcled_cdev->subled_info[0].channel; + + led_mc_calc_color_components(mcled_cdev, brightness); + color = (mcled_cdev->subled_info[0].brightness << 16) + + (mcled_cdev->subled_info[1].brightness << 8) + + mcled_cdev->subled_info[2].brightness; + + ret = clevo_evaluate_set_color(zone, color); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed\n"); + return; + } + led_cdev->brightness = brightness; +} + +static struct led_classdev clevo_led_cdev = { + .name = DRIVER_NAME ":white:kbd_backlight", + .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness_set = &clevo_leds_set_brightness, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT +}; + +static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 + } + }, + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 + } + }, + { + { + .color_index = LED_COLOR_ID_RED, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_RED, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, + .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 + } + } +}; + +static struct led_classdev_mc clevo_mcled_cdevs[3] = { + { + .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .num_colors = 3, + .subled_info = clevo_mcled_cdevs_subleds[0] + }, + { + .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .num_colors = 3, + .subled_info = clevo_mcled_cdevs_subleds[1] + }, + { + .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, + .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, + .num_colors = 3, + .subled_info = clevo_mcled_cdevs_subleds[2] + } +}; + +int clevo_leds_init(struct platform_device *dev) +{ + int ret; + u32 status; + union acpi_object *result; + + status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); + if (!status) { + if (result->type == ACPI_TYPE_BUFFER) { + pr_debug("CLEVO_CMD_GET_SPECS successful\n"); + clevo_kb_backlight_type = result->buffer.pointer[0x0f]; + } + else { + pr_err("CLEVO_CMD_GET_SPECS return value has wrong type\n"); + } + ACPI_FREE(result); + } + else { + pr_err("CLEVO_CMD_GET_SPECS failed\n"); + } + pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); + + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + pr_debug("Registering fixed color leds interface\n"); + ret = led_classdev_register(&dev->dev, &clevo_led_cdev); + if(ret) { + pr_err("Registering fixed color leds interface failed\n"); + return ret; + } + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + pr_debug("Registering single zone rgb leds interface\n"); + ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); + if(ret) { + pr_err("Registering single zone rgb leds interface failed\n"); + return ret; + } + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + pr_debug("Registering three zone rgb leds interface\n"); + ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); + if(ret) { + pr_err("Registering three zone rgb zone 0 leds interface failed\n"); + return ret; + } + ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[1]); + if(ret) { + pr_err("Registering three zone rgb zone 1 leds interface failed\n"); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + return ret; + } + ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[2]); + if(ret) { + pr_err("Registering three zone rgb zone 2 leds interface failed\n"); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[1]); + return ret; + } + } + + leds_initiaized = true; + return 0; +} +EXPORT_SYMBOL(clevo_leds_init); + +int clevo_leds_remove(struct platform_device *dev) { + if (leds_initiaized) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + led_classdev_unregister(&clevo_led_cdev); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[1]); + devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[2]); + } + } + + return 0; +} +EXPORT_SYMBOL(clevo_leds_remove); + +enum clevo_kb_backlight_types clevo_leds_get_backlight_type() { + return clevo_kb_backlight_type; +} +EXPORT_SYMBOL(clevo_leds_get_backlight_type); + +void clevo_leds_set_brightness_extern(u32 brightness) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + clevo_led_cdev.brightness_set(&clevo_led_cdev, brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, brightness); + clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, brightness); + clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, brightness); + } +} +EXPORT_SYMBOL(clevo_leds_set_brightness_extern); + +void clevo_leds_set_color_extern(u32 color) { + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + } + else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { + clevo_mcled_cdevs[0].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[0].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[0].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[0].led_cdev.brightness_set(&clevo_mcled_cdevs[0].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[1].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[1].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[1].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[2].subled_info[0].intensity = (color >> 16) & 0xff; + clevo_mcled_cdevs[2].subled_info[1].intensity = (color >> 8) & 0xff; + clevo_mcled_cdevs[2].subled_info[2].intensity = color & 0xff; + clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + } +} +EXPORT_SYMBOL(clevo_leds_set_color_extern); + +MODULE_LICENSE("GPL"); + #endif // CLEVO_LEDS_H diff --git a/tuxedo_keyboard.conf b/tuxedo_keyboard.conf index b257600..57d0ea6 100644 --- a/tuxedo_keyboard.conf +++ b/tuxedo_keyboard.conf @@ -1 +1 @@ -options tuxedo-keyboard mode=0 brightness=255 color_left=0xFFFFFF color_center=0xFFFFFF color_right=0xFFFFFF +options tuxedo-keyboard kbd_backlight_mode=0 brightness=255 From 2766237dd0a681fc6a0d0e673b2e473db5cc542a Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 18:23:53 +0200 Subject: [PATCH 16/59] Cleanup --- src/clevo_leds.c | 18 ------------------ src/clevo_leds.h | 8 +++++--- 2 files changed, 5 insertions(+), 21 deletions(-) delete mode 100644 src/clevo_leds.c diff --git a/src/clevo_leds.c b/src/clevo_leds.c deleted file mode 100644 index 9310504..0000000 --- a/src/clevo_leds.c +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Copyright (c) 2018-2020 TUXEDO Computers GmbH - * - * This file is part of tuxedo-keyboard. - * - * tuxedo-keyboard 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 3 of the License, or - * (at your option) any later version. - * - * This software 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 software. If not, see . - */ diff --git a/src/clevo_leds.h b/src/clevo_leds.h index d56056f..7642568 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -21,7 +21,6 @@ #define CLEVO_LEDS_H #include -#include enum clevo_kb_backlight_types { CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, @@ -232,6 +231,9 @@ int clevo_leds_init(struct platform_device *dev) } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); + clevo_leds_set_brightness_extern(CLEVO_KBD_BRIGHTNESS_DEFAULT); + clevo_leds_set_color_extern(CLEVO_KB_COLOR_DEFAULT); + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { pr_debug("Registering fixed color leds interface\n"); ret = led_classdev_register(&dev->dev, &clevo_led_cdev); @@ -329,11 +331,11 @@ void clevo_leds_set_color_extern(u32 color) { clevo_mcled_cdevs[1].subled_info[0].intensity = (color >> 16) & 0xff; clevo_mcled_cdevs[1].subled_info[1].intensity = (color >> 8) & 0xff; clevo_mcled_cdevs[1].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[1].led_cdev.brightness_set(&clevo_mcled_cdevs[1].led_cdev, clevo_mcled_cdevs[1].led_cdev.brightness); clevo_mcled_cdevs[2].subled_info[0].intensity = (color >> 16) & 0xff; clevo_mcled_cdevs[2].subled_info[1].intensity = (color >> 8) & 0xff; clevo_mcled_cdevs[2].subled_info[2].intensity = color & 0xff; - clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, clevo_mcled_cdevs[0].led_cdev.brightness); + clevo_mcled_cdevs[2].led_cdev.brightness_set(&clevo_mcled_cdevs[2].led_cdev, clevo_mcled_cdevs[2].led_cdev.brightness); } } EXPORT_SYMBOL(clevo_leds_set_color_extern); From 6f9ee3fd6f4dd2feeadf8890d76dacf4a54353b2 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 18:42:53 +0200 Subject: [PATCH 17/59] Cleanup --- src/clevo_keyboard.h | 159 ++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 85 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 9dee864..80c5dee 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -39,83 +39,15 @@ #define CLEVO_KB_MODE_DEFAULT 0 // "CUSTOM"/Static Color -struct tuxedo_keyboard_driver clevo_keyboard_driver; - static struct clevo_interfaces_t { struct clevo_interface_t *wmi; struct clevo_interface_t *acpi; } clevo_interfaces; -struct clevo_interface_t *active_clevo_interface; - -void clevo_keyboard_event_callb(u32 event); // TODO Reorder to not require forward declaration? +static struct clevo_interface_t *active_clevo_interface; static DEFINE_MUTEX(clevo_keyboard_interface_modification_lock); -u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) -{ - mutex_lock(&clevo_keyboard_interface_modification_lock); - - if (strcmp(new_interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { - clevo_interfaces.wmi = new_interface; - clevo_interfaces.wmi->event_callb = clevo_keyboard_event_callb; - - // Only use wmi if there is no other current interface - if (ZERO_OR_NULL_PTR(active_clevo_interface)) { - pr_debug("enable wmi events\n"); - clevo_interfaces.wmi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); - - active_clevo_interface = clevo_interfaces.wmi; - } - - } else if (strcmp(new_interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { - clevo_interfaces.acpi = new_interface; - clevo_interfaces.acpi->event_callb = clevo_keyboard_event_callb; - - pr_debug("enable acpi events (takes priority)\n"); - clevo_interfaces.acpi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); - active_clevo_interface = clevo_interfaces.acpi; - } else { - // Not recognized interface - pr_err("unrecognized interface\n"); - mutex_unlock(&clevo_keyboard_interface_modification_lock); - return -EINVAL; - } - - mutex_unlock(&clevo_keyboard_interface_modification_lock); - - if (active_clevo_interface != NULL) - tuxedo_keyboard_init_driver(&clevo_keyboard_driver); - - return 0; -} -EXPORT_SYMBOL(clevo_keyboard_add_interface); - -u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface) -{ - mutex_lock(&clevo_keyboard_interface_modification_lock); - - if (strcmp(interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { - clevo_interfaces.wmi = NULL; - } else if (strcmp(interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { - clevo_interfaces.acpi = NULL; - } else { - mutex_unlock(&clevo_keyboard_interface_modification_lock); - return -EINVAL; - } - - if (active_clevo_interface == interface) { - tuxedo_keyboard_remove_driver(&clevo_keyboard_driver); - active_clevo_interface = NULL; - } - - - mutex_unlock(&clevo_keyboard_interface_modification_lock); - - return 0; -} -EXPORT_SYMBOL(clevo_keyboard_remove_interface); - static struct key_entry clevo_keymap[] = { // Keyboard backlight (RGB versions) { KE_KEY, CLEVO_EVENT_KB_LEDS_DECREASE, { KEY_KBDILLUMDOWN } }, @@ -148,22 +80,22 @@ static struct key_entry clevo_keymap[] = { { KE_END, 0 } }; -#define BRIGHTNESS_STEP 32 - // Keyboard struct -struct kbd_led_state_t { +static struct kbd_led_state_t { u8 has_mode; u8 mode; u8 whole_kbd_color; +} kbd_led_state = { + .has_mode = 1, + .mode = CLEVO_KB_MODE_DEFAULT, + .whole_kbd_color = 7, }; -struct blinking_pattern_t { +static struct kbd_backlight_mode_t { u8 key; u32 value; const char *const name; -}; - -static struct blinking_pattern_t kbd_backlight_modes[] = { +} kbd_backlight_modes[] = { { .key = 0, .value = 0x00000000, .name = "CUSTOM"}, { .key = 1, .value = 0x1002a000, .name = "BREATHE"}, { .key = 2, .value = 0x33010000, .name = "CYCLE"}, @@ -174,12 +106,6 @@ static struct blinking_pattern_t kbd_backlight_modes[] = { { .key = 7, .value = 0xB0000000, .name = "WAVE"} }; -static struct kbd_led_state_t kbd_led_state = { - .has_mode = 1, - .mode = CLEVO_KB_MODE_DEFAULT, - .whole_kbd_color = 7, -}; - // Sysfs Interface for the backlight blinking pattern static ssize_t show_kbd_backlight_modes_fs(struct device *child, struct device_attribute *attr, char *buffer) @@ -334,7 +260,7 @@ static int brightness_validator(const char *value, return param_set_int(value, brightness_param); } -void clevo_keyboard_event_callb(u32 event) +static void clevo_keyboard_event_callb(u32 event) { u32 key_event = event; @@ -384,7 +310,7 @@ static bool dmi_string_in(enum dmi_field f, const char *str) return strstr(info, str) != NULL; } -int clevo_keyboard_init(void) +static int clevo_keyboard_init(void) { bool performance_profile_set_workaround; @@ -467,10 +393,73 @@ static struct platform_driver platform_driver_clevo = { }, }; -struct tuxedo_keyboard_driver clevo_keyboard_driver = { +static struct tuxedo_keyboard_driver clevo_keyboard_driver = { .platform_driver = &platform_driver_clevo, .probe = clevo_keyboard_probe, .key_map = clevo_keymap, }; +u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) +{ + mutex_lock(&clevo_keyboard_interface_modification_lock); + + if (strcmp(new_interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { + clevo_interfaces.wmi = new_interface; + clevo_interfaces.wmi->event_callb = clevo_keyboard_event_callb; + + // Only use wmi if there is no other current interface + if (ZERO_OR_NULL_PTR(active_clevo_interface)) { + pr_debug("enable wmi events\n"); + clevo_interfaces.wmi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); + + active_clevo_interface = clevo_interfaces.wmi; + } + } else if (strcmp(new_interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { + clevo_interfaces.acpi = new_interface; + clevo_interfaces.acpi->event_callb = clevo_keyboard_event_callb; + + pr_debug("enable acpi events (takes priority)\n"); + clevo_interfaces.acpi->method_call(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); + active_clevo_interface = clevo_interfaces.acpi; + } else { + // Not recognized interface + pr_err("unrecognized interface\n"); + mutex_unlock(&clevo_keyboard_interface_modification_lock); + return -EINVAL; + } + + mutex_unlock(&clevo_keyboard_interface_modification_lock); + + if (active_clevo_interface != NULL) + tuxedo_keyboard_init_driver(&clevo_keyboard_driver); + + return 0; +} +EXPORT_SYMBOL(clevo_keyboard_add_interface); + +u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface) +{ + mutex_lock(&clevo_keyboard_interface_modification_lock); + + if (strcmp(interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { + clevo_interfaces.wmi = NULL; + } else if (strcmp(interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { + clevo_interfaces.acpi = NULL; + } else { + mutex_unlock(&clevo_keyboard_interface_modification_lock); + return -EINVAL; + } + + if (active_clevo_interface == interface) { + tuxedo_keyboard_remove_driver(&clevo_keyboard_driver); + active_clevo_interface = NULL; + } + + + mutex_unlock(&clevo_keyboard_interface_modification_lock); + + return 0; +} +EXPORT_SYMBOL(clevo_keyboard_remove_interface); + #endif // CLEVO_KEYBOARD_H From 59512ed1fb65aebebb78aa08a7b26a225fa02ccf Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 18:55:36 +0200 Subject: [PATCH 18/59] Cleanup --- src/clevo_keyboard.h | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 80c5dee..5c4522f 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -106,13 +106,6 @@ static struct kbd_backlight_mode_t { { .key = 7, .value = 0xB0000000, .name = "WAVE"} }; -// Sysfs Interface for the backlight blinking pattern -static ssize_t show_kbd_backlight_modes_fs(struct device *child, struct device_attribute *attr, - char *buffer) -{ - return sprintf(buffer, "%d\n", kbd_led_state.mode); -} - u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result) { if (IS_ERR_OR_NULL(active_clevo_interface)) { @@ -173,7 +166,7 @@ static int set_enabled_cmd(u8 state) return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, cmd, NULL); } -static int set_next_color_whole_kb(void) +static void set_next_color_whole_kb(void) { /* "Calculate" new to-be color */ u32 new_color_id; @@ -191,8 +184,6 @@ static int set_next_color_whole_kb(void) /* Set color on all four regions*/ clevo_leds_set_color_extern(new_color_code); kbd_led_state.whole_kbd_color = new_color_id; - - return 0; } static void set_kbd_backlight_mode(u8 kbd_backlight_mode) @@ -205,6 +196,13 @@ static void set_kbd_backlight_mode(u8 kbd_backlight_mode) } } +// Sysfs Interface for the keyboard backlight mode +static ssize_t list_kbd_backlight_modes_fs(struct device *child, struct device_attribute *attr, + char *buffer) +{ + return sprintf(buffer, "%d\n", kbd_led_state.mode); +} + static ssize_t set_kbd_backlight_mode_fs(struct device *child, struct device_attribute *attr, const char *buffer, size_t size) @@ -222,6 +220,9 @@ static ssize_t set_kbd_backlight_mode_fs(struct device *child, return size; } +// Sysfs attribute file permissions and method linking +static DEVICE_ATTR(kbd_backlight_mode, 0644, list_kbd_backlight_modes_fs, set_kbd_backlight_mode_fs); + static int kbd_backlight_mode_id_validator(const char *value, const struct kernel_param *kbd_backlight_mode_param) { @@ -243,7 +244,7 @@ static const struct kernel_param_ops param_ops_mode_ops = { static u8 param_kbd_backlight_mode = CLEVO_KB_MODE_DEFAULT; module_param_cb(kbd_backlight_mode, ¶m_ops_mode_ops, ¶m_kbd_backlight_mode, S_IRUSR); -MODULE_PARM_DESC(kbd_backlight_mode, "Set the keyboard backlight blinking pattern"); +MODULE_PARM_DESC(kbd_backlight_mode, "Set the keyboard backlight mode"); // TODO remove static int brightness_validator(const char *value, @@ -281,9 +282,6 @@ static void clevo_keyboard_event_callb(u32 event) } } -// Sysfs attribute file permissions and method linking -static DEVICE_ATTR(kbd_backlight_mode, 0644, show_kbd_backlight_modes_fs, set_kbd_backlight_mode_fs); - static void clevo_keyboard_init_device_interface(struct platform_device *dev) { // Setup sysfs @@ -310,7 +308,7 @@ static bool dmi_string_in(enum dmi_field f, const char *str) return strstr(info, str) != NULL; } -static int clevo_keyboard_init(void) +static void clevo_keyboard_init(void) { bool performance_profile_set_workaround; @@ -339,8 +337,6 @@ static int clevo_keyboard_init(void) TUXEDO_INFO("Performance profile 'performance' set workaround applied\n"); clevo_evaluate_method(CLEVO_CMD_OPT, 0x19000002, NULL); } - - return 0; } static int clevo_keyboard_probe(struct platform_device *dev) From 4e6d2f0a3c66a790b5bce563d570a1e898dc5344 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 24 Aug 2022 19:09:32 +0200 Subject: [PATCH 19/59] Nomilize name --- src/clevo_leds.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 7642568..f47a85b 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -113,7 +113,7 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led } static struct led_classdev clevo_led_cdev = { - .name = DRIVER_NAME ":white:kbd_backlight", + .name = "white:kbd_backlight", .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .brightness_set = &clevo_leds_set_brightness, .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT @@ -184,7 +184,7 @@ static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { static struct led_classdev_mc clevo_mcled_cdevs[3] = { { - .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.name = "rgb:kbd_backlight", .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, @@ -192,7 +192,7 @@ static struct led_classdev_mc clevo_mcled_cdevs[3] = { .subled_info = clevo_mcled_cdevs_subleds[0] }, { - .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.name = "rgb:kbd_backlight", .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, @@ -200,7 +200,7 @@ static struct led_classdev_mc clevo_mcled_cdevs[3] = { .subled_info = clevo_mcled_cdevs_subleds[1] }, { - .led_cdev.name = DRIVER_NAME ":rgb:kbd_backlight", + .led_cdev.name = "rgb:kbd_backlight", .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, From 4540824b008c0144e8077f9b30e981668f8d4c68 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 13:05:24 +0200 Subject: [PATCH 20/59] Cleanup --- src/clevo_leds.h | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index f47a85b..2021be8 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -20,6 +20,7 @@ #ifndef CLEVO_LEDS_H #define CLEVO_LEDS_H +#include #include enum clevo_kb_backlight_types { @@ -45,14 +46,14 @@ void clevo_leds_set_color_extern(u32 color); #include #include -#define CLEVO_KBD_BRIGHTNESS_MIN 0 -#define CLEVO_KBD_BRIGHTNESS_MAX 255 -#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_MIN 0x00 +#define CLEVO_KBD_BRIGHTNESS_MAX 0xff +#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) -#define CLEVO_KB_COLOR_DEFAULT_RED 0xFF -#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xFF -#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xFF -#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) +#define CLEVO_KB_COLOR_DEFAULT_RED 0xff +#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff +#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff +#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) // The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To // not break these, we set this as default for the time being, better having an extra sysfs entry without function than @@ -113,7 +114,7 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led } static struct led_classdev clevo_led_cdev = { - .name = "white:kbd_backlight", + .name = "white:" LED_FUNCTION_KBD_BACKLIGHT, .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .brightness_set = &clevo_leds_set_brightness, .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT @@ -123,19 +124,19 @@ static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { { { .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_RED, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 }, { .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 }, { .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 } @@ -143,19 +144,19 @@ static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { { { .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_RED, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 }, { .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 }, { .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 } @@ -163,19 +164,19 @@ static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { { { .color_index = LED_COLOR_ID_RED, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_RED, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 }, { .color_index = LED_COLOR_ID_GREEN, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_GREEN, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 }, { .color_index = LED_COLOR_ID_BLUE, - .brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, .intensity = CLEVO_KB_COLOR_DEFAULT_BLUE, .channel = CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 } @@ -184,7 +185,7 @@ static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { static struct led_classdev_mc clevo_mcled_cdevs[3] = { { - .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT, .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, @@ -192,7 +193,7 @@ static struct led_classdev_mc clevo_mcled_cdevs[3] = { .subled_info = clevo_mcled_cdevs_subleds[0] }, { - .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT, .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, @@ -200,7 +201,7 @@ static struct led_classdev_mc clevo_mcled_cdevs[3] = { .subled_info = clevo_mcled_cdevs_subleds[1] }, { - .led_cdev.name = "rgb:kbd_backlight", + .led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT, .led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, .led_cdev.brightness_set = &clevo_leds_set_brightness_mc, .led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT, From 7a388342650361ce11d1cf100a9970825a3107fa Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 13:06:12 +0200 Subject: [PATCH 21/59] Cleanup --- tuxedo_keyboard.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuxedo_keyboard.conf b/tuxedo_keyboard.conf index 57d0ea6..b006381 100644 --- a/tuxedo_keyboard.conf +++ b/tuxedo_keyboard.conf @@ -1 +1 @@ -options tuxedo-keyboard kbd_backlight_mode=0 brightness=255 +options tuxedo-keyboard kbd_backlight_mode=0 From 40f46087f54693bd0a52b14aa45c28009f811307 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 18:21:37 +0200 Subject: [PATCH 22/59] Implement temporal behaviour to work around KDE bug --- src/clevo_keyboard.h | 2 +- src/clevo_leds.h | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 5c4522f..057d1a3 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -55,7 +55,7 @@ static struct key_entry clevo_keymap[] = { { KE_KEY, CLEVO_EVENT_KB_LEDS_TOGGLE, { KEY_KBDILLUMTOGGLE } }, { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_MODE, { KEY_LIGHTS_TOGGLE } }, // Single cycle key (white only versions) - { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS, { KEY_KBDILLUMTOGGLE } }, //FIXME Cycle in driver or toggle in desktop environment? + { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS, { KEY_KBDILLUMTOGGLE } }, // Touchpad // The weirdly named touchpad toggle key that is implemented as KEY_F21 "everywhere" diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 2021be8..9891685 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -87,7 +87,7 @@ static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unu led_cdev->brightness = brightness; } -static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { +/*static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { int ret; u32 zone, color; struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); @@ -111,6 +111,40 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led return; } led_cdev->brightness = brightness; +}*/ + +// Temprary fix for KDE: KDE does only set one kbd_backlight brightness value, this version of the +// function uses clevos built in brightness setting to set the whole keyboard brightness at once. +// -> use clevo_evaluate_set_brightness() to set overall brightness via firmware instead of scaling +// the RGB values +// -> update all clevo_mcled_cdevs brightness levels to refect that the firmware method sets the +// the whole keyboard brightness and not just one zone +// This is a temporary fix until KDE handles multiple keyboard backlights correctly +static struct led_classdev_mc clevo_mcled_cdevs[3]; // forward declaration +static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + int ret; + u32 zone, color; + struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); + + ret = clevo_evaluate_set_brightness(brightness); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed\n"); + return; + } + clevo_mcled_cdevs[0].brightness = brightness; + clevo_mcled_cdevs[1].brightness = brightness; + clevo_mcled_cdevs[2].brightness = brightness; + + zone = mcled_cdev->subled_info[0].channel; + + color = (mcled_cdev->subled_info[0].intensity << 16) + + (mcled_cdev->subled_info[1].intensity << 8) + + mcled_cdev->subled_info[2].intensity; + + ret = clevo_evaluate_set_color(zone, color); + if (ret) { + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed\n"); + } } static struct led_classdev clevo_led_cdev = { From 60cd77e01a58f72f402bb111aa92eb81337408ee Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 18:22:48 +0200 Subject: [PATCH 23/59] Start rework for uniwill --- src/tuxedo_keyboard_common.h | 20 ------ src/uniwill_keyboard.h | 100 ------------------------------ src/uniwill_leds.h | 117 +++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 120 deletions(-) create mode 100644 src/uniwill_leds.h diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 60e62d8..35761cb 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -120,24 +120,4 @@ static u32 color_lookup(const struct color_list_t *color_list, const char *color return found_color; } -// Common parameters - -static int brightness_validator(const char *val, - const struct kernel_param *brightness_param); -static const struct kernel_param_ops param_ops_brightness_ops = { - .set = brightness_validator, - .get = param_get_int, -}; - -// TODO remove -static ushort param_brightness = 0xffff; // Default unset value (higher than max) -module_param_cb(brightness, ¶m_ops_brightness_ops, ¶m_brightness, - S_IRUSR); -MODULE_PARM_DESC(brightness, "Set the Keyboard Brightness"); - -#define COLOR_STRING_LEN 20 -static char param_color[COLOR_STRING_LEN]; -module_param_string(color, param_color, COLOR_STRING_LEN, S_IRUSR); -MODULE_PARM_DESC(color, "Preset color for the keyboard backlight as string"); - #endif diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 0e03e61..cf3fd48 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -32,14 +32,6 @@ #include #include "uniwill_interfaces.h" -#define UNIWILL_WMI_MGMT_GUID_BA "ABBC0F6D-8EA1-11D1-00A0-C90629100000" -#define UNIWILL_WMI_MGMT_GUID_BB "ABBC0F6E-8EA1-11D1-00A0-C90629100000" -#define UNIWILL_WMI_MGMT_GUID_BC "ABBC0F6F-8EA1-11D1-00A0-C90629100000" - -#define UNIWILL_WMI_EVENT_GUID_0 "ABBC0F70-8EA1-11D1-00A0-C90629100000" -#define UNIWILL_WMI_EVENT_GUID_1 "ABBC0F71-8EA1-11D1-00A0-C90629100000" -#define UNIWILL_WMI_EVENT_GUID_2 "ABBC0F72-8EA1-11D1-00A0-C90629100000" - #define UNIWILL_OSD_RADIOON 0x01A #define UNIWILL_OSD_RADIOOFF 0x01B #define UNIWILL_OSD_KB_LED_LEVEL0 0x03B @@ -56,21 +48,8 @@ #define UNIWILL_OSD_TOUCHPADWORKAROUND 0xFFF -#define UNIWILL_BRIGHTNESS_MIN 0x00 -#define UNIWILL_BRIGHTNESS_MAX 0xc8 -#define UNIWILL_BRIGHTNESS_DEFAULT UNIWILL_BRIGHTNESS_MAX * 0.30 -#define UNIWILL_COLOR_DEFAULT 0xffffff - struct tuxedo_keyboard_driver uniwill_keyboard_driver; -struct kbd_led_state_uw_t { - u32 brightness; - u32 color; -} kbd_led_state_uw = { - .brightness = UNIWILL_BRIGHTNESS_DEFAULT, - .color = UNIWILL_COLOR_DEFAULT, -}; - static u8 uniwill_kbd_bl_enable_state_on_start; static bool uniwill_kbd_bl_type_rgb_single_color = true; @@ -252,63 +231,6 @@ static void uniwill_write_kbd_bl_enable(u8 enable) uniwill_write_ec_ram(0x078c, backlight_data); } -/*static u32 uniwill_read_kbd_bl_br_state(u8 *brightness_state) -{ - u8 backlight_data; - u32 result; - - uniwill_read_ec_ram(0x078c, &backlight_data); - *brightness_state = (backlight_data & 0xf0) >> 4; - result = 0; - - return result; -}*/ - -static u32 uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) -{ - u32 result; - - uniwill_read_ec_ram(0x1803, red); - uniwill_read_ec_ram(0x1805, green); - uniwill_read_ec_ram(0x1808, blue); - - result = 0; - - return result; -} - -static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) -{ - if (red > 0xc8) red = 0xc8; - if (green > 0xc8) green = 0xc8; - if (blue > 0xc8) blue = 0xc8; - uniwill_write_ec_ram(0x1803, red); - uniwill_write_ec_ram(0x1805, green); - uniwill_write_ec_ram(0x1808, blue); - TUXEDO_DEBUG("Wrote kbd color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); -} - -static void uniwill_write_kbd_bl_state(void) { - // Get single colors from state - u32 color_red = ((kbd_led_state_uw.color >> 0x10) & 0xff); - u32 color_green = (kbd_led_state_uw.color >> 0x08) & 0xff; - u32 color_blue = (kbd_led_state_uw.color >> 0x00) & 0xff; - - u32 brightness_percentage = (kbd_led_state_uw.brightness * 100) / UNIWILL_BRIGHTNESS_MAX; - - // Scale color values to valid range - color_red = (color_red * 0xc8) / 0xff; - color_green = (color_green * 0xc8) / 0xff; - color_blue = (color_blue * 0xc8) / 0xff; - - // Scale the respective color values with brightness - color_red = (color_red * brightness_percentage) / 100; - color_green = (color_green * brightness_percentage) / 100; - color_blue = (color_blue * brightness_percentage) / 100; - - uniwill_write_kbd_bl_rgb(color_red, color_green, color_blue); -} - static void uniwill_write_kbd_bl_reset(void) { uniwill_write_ec_ram(0x078c, 0x10); @@ -520,28 +442,6 @@ static void uw_kbd_bl_init_ready_check(struct timer_list *t) schedule_work(&uw_kbd_bl_init_ready_check_work); } -static struct mc_subled cdev_kb_uw_mc_subled[3] = { - { .color_index = LED_COLOR_ID_RED, - .brightness = UNIWILL_BRIGHTNESS_DEFAULT, - .intensity = UNIWILL_BRIGHTNESS_MAX }, - { .color_index = LED_COLOR_ID_GREEN, - .brightness = UNIWILL_BRIGHTNESS_DEFAULT, - .intensity = UNIWILL_BRIGHTNESS_MAX }, - { .color_index = LED_COLOR_ID_BLUE, - .brightness = UNIWILL_BRIGHTNESS_DEFAULT, - .intensity = UNIWILL_BRIGHTNESS_MAX } -}; - -static struct led_classdev_mc cdev_kb_uw_mc = { - .led_cdev.name = KBUILD_MODNAME "::kbd_backlight", - .led_cdev.max_brightness = UNIWILL_BRIGHTNESS_MAX, - .led_cdev.brightness_set_blocking = &ledcdev_set_blocking_uw_mc, - .led_cdev.brightness_get = &ledcdev_get_uw, - .led_cdev.brightness = UNIWILL_BRIGHTNESS_DEFAULT, - .num_colors = 3, - .subled_info = cdev_kb_uw_mc_subled -}; - static int uw_kbd_bl_init(struct platform_device *dev) { int status = 0; diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h new file mode 100644 index 0000000..b630f6d --- /dev/null +++ b/src/uniwill_leds.h @@ -0,0 +1,117 @@ +/*! + * Copyright (c) 2018-2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-keyboard. + * + * tuxedo-keyboard 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 3 of the License, or + * (at your option) any later version. + * + * This software 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 software. If not, see . + */ + +#ifndef UNIWILL_LEDS_H +#define UNIWILL_LEDS_H + +#include +#include + +#define UNIWILL_KBD_BRIGHTNESS_MIN 0x00 +#define UNIWILL_KBD_BRIGHTNESS_MAX 0xff // Uniwill devices actually operate on a range + // from 0x00 - 0xc8 (200), but because + // userspace will get it wrong we do the + // conversion in driver. +#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) + +#define UNIWILL_KB_COLOR_DEFAULT_RED 0xff // Same applies as for brightness: Actuall +#define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff // range is 0x00 - 0xc8. Conversion is done in +#define UNIWILL_KB_COLOR_DEFAULT_BLUE 0xff // this driver. +#define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) + +enum uniwill_kb_backlight_types { + UNIWILL_KB_BACKLIGHT_TYPE_NONE, + UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR, + UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB, + UNIWILL_KB_BACKLIGHT_TYPE_PER_KEY_RGB +}; + +int uniwill_leds_init(struct platform_device *dev); +int uniwill_leds_remove(struct platform_device *dev); +enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type(void); +void uniwill_leds_set_brightness_extern(u32 brightness); +void uniwill_leds_set_color_extern(u32 color); + +// TODO The following should go into a seperate .c file, but for this to work more reworking is required in the tuxedo_keyboard structure. + +#include "clevo_leds.h" + +#include "clevo_interfaces.h" + +#include +#include + +#define FF_TO_UW_RANGE(x) (x * 0xc8 / 0xff) +#define UW_TO_FF_RANGE(x) (x * 0xff / 0xc8) + +static u32 uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) +{ + u32 result; + + uniwill_read_ec_ram(0x1803, red); + uniwill_read_ec_ram(0x1805, green); + uniwill_read_ec_ram(0x1808, blue); + + result = 0; + + return result; +} + +static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) +{ + if (red > 0xc8) red = 0xc8; + if (green > 0xc8) green = 0xc8; + if (blue > 0xc8) blue = 0xc8; + uniwill_write_ec_ram(0x1803, red); + uniwill_write_ec_ram(0x1805, green); + uniwill_write_ec_ram(0x1808, blue); + TUXEDO_DEBUG("Wrote kbd color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); +} + +static struct mc_subled clevo_mcled_cdev_subleds[3] = { + { + .color_index = LED_COLOR_ID_RED, + .brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .intensity = UNIWILL_KB_COLOR_DEFAULT_RED, + .channel = 0 + }, + { + .color_index = LED_COLOR_ID_GREEN, + .brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .intensity = UNIWILL_KB_COLOR_DEFAULT_GREEN, + .channel = 0 + }, + { + .color_index = LED_COLOR_ID_BLUE, + .brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .intensity = UNIWILL_KB_COLOR_DEFAULT_BLUE, + .channel = 0 + } +}; + +static struct led_classdev_mc uniwill_mcled_cdev = { + .led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT, + .led_cdev.max_brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .led_cdev.brightness = &uniwill_leds_set_brightness_mc, + .led_cdev.brightness = UNIWILL_KBD_BRIGHTNESS_DEFAULT, + .num_colors = 3, + .subled_info = cdev_kb_uw_mc_subled +}; + +#endif // UNIWILL_LEDS_H From 3c6451d9d8bc2ff9b1f221ed88f0a48703721958 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 18:31:33 +0200 Subject: [PATCH 24/59] Fix compilation issue --- src/clevo_leds.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 9891685..bb58624 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -131,9 +131,9 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed\n"); return; } - clevo_mcled_cdevs[0].brightness = brightness; - clevo_mcled_cdevs[1].brightness = brightness; - clevo_mcled_cdevs[2].brightness = brightness; + clevo_mcled_cdevs[0].led_cdev.brightness = brightness; + clevo_mcled_cdevs[1].led_cdev.brightness = brightness; + clevo_mcled_cdevs[2].led_cdev.brightness = brightness; zone = mcled_cdev->subled_info[0].channel; From 6d1f210db4a407884960ab19af10c8ba28d79ce9 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 25 Aug 2022 19:06:16 +0200 Subject: [PATCH 25/59] Make color cycle skip black --- src/clevo_keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 057d1a3..6dfd0bb 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -174,7 +174,7 @@ static void set_next_color_whole_kb(void) new_color_id = kbd_led_state.whole_kbd_color + 1; if (new_color_id >= color_list.size) { - new_color_id = 0; + new_color_id = 1; // Skip black } new_color_code = color_list.colors[new_color_id].code; From fd9fc525109d0c5004bd0e64c3ee0cb782fb7031 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 11:04:51 +0200 Subject: [PATCH 26/59] More specific name for sub command --- src/clevo_interfaces.h | 10 +++++----- src/clevo_leds.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index a624258..0a32c72 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -54,11 +54,11 @@ #define CLEVO_CMD_SET_EVENTS_ENABLED 0x46 -#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 0xF0000000 // 1-zone RGB and 3-zone RGB left -#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 0xF1000000 // 3-zone RGB center -#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 0xF2000000 // 3-Zone RGB right -#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_3 0xF3000000 // Unused on all known Clevo devices -#define CLEVO_CMD_SET_KB_LEDS_SUB_BRIGHTNESS 0xF4000000 +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 0xF0000000 // 1-zone RGB and 3-zone RGB left +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 0xF1000000 // 3-zone RGB center +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 0xF2000000 // 3-Zone RGB right +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_3 0xF3000000 // Unused on all known Clevo devices +#define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_BRIGHTNESS 0xF4000000 #define CLEVO_CMD_OPT 0x79 #define CLEVO_OPT_SUBCMD_SET_PERF_PROF 0x19 diff --git a/src/clevo_leds.h b/src/clevo_leds.h index bb58624..f187488 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -65,7 +65,7 @@ static int clevo_evaluate_set_brightness(u8 brightness) { pr_debug("Set brightness on %d\n", brightness); - return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, 0xF4000000 | brightness, NULL); + return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, CLEVO_CMD_SET_KB_LEDS_SUB_RGB_BRIGHTNESS | brightness, NULL); } static int clevo_evaluate_set_color(u32 zone, u32 color) From 0cfe09ac06e079c14bf61435c7b8ceac4177c855 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 18:58:44 +0200 Subject: [PATCH 27/59] Cleanup --- src/clevo_interfaces.h | 2 +- src/tuxedo_io/tuxedo_io.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 0a32c72..50d327b 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -61,7 +61,7 @@ #define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_BRIGHTNESS 0xF4000000 #define CLEVO_CMD_OPT 0x79 -#define CLEVO_OPT_SUBCMD_SET_PERF_PROF 0x19 +#define CLEVO_CMD_OPT_SUB_SET_PERF_PROF 0x19 struct clevo_interface_t { char *string_id; diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 22f51e4..e7ec2ac 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -148,7 +148,7 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned break; case W_CL_PERF_PROFILE: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); - clevo_arg = (CLEVO_OPT_SUBCMD_SET_PERF_PROF << 0x18) | (argument & 0xff); + clevo_arg = (CLEVO_CMD_OPT_SUB_SET_PERF_PROF << 0x18) | (argument & 0xff); clevo_evaluate_method(CLEVO_CMD_OPT, clevo_arg, &result); break; } From 1d5f679f66da090beb7e7a6de0c8b052d6b17308 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 19:05:04 +0200 Subject: [PATCH 28/59] Fix white only keyboards --- src/clevo_interfaces.h | 4 +-- src/clevo_keyboard.h | 4 +-- src/clevo_leds.h | 57 +++++++++++++++++++++++++----------------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 50d327b..9077032 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -50,10 +50,10 @@ #define CLEVO_CMD_SET_FLIGHTMODE_SW 0x20 #define CLEVO_CMD_SET_TOUCHPAD_SW 0x2a -#define CLEVO_CMD_SET_KB_LEDS 0x67 // used to set color, brightness, blinking pattern, etc. - #define CLEVO_CMD_SET_EVENTS_ENABLED 0x46 +#define CLEVO_CMD_SET_KB_WHITE_LEDS 0x27 // Set brightness of single color keyboard backlights +#define CLEVO_CMD_SET_KB_RGB_LEDS 0x67 // Used to set color, brightness, blinking pattern, etc. #define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_0 0xF0000000 // 1-zone RGB and 3-zone RGB left #define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_1 0xF1000000 // 3-zone RGB center #define CLEVO_CMD_SET_KB_LEDS_SUB_RGB_ZONE_2 0xF2000000 // 3-Zone RGB right diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 6dfd0bb..f68dbda 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -163,7 +163,7 @@ static int set_enabled_cmd(u8 state) cmd |= 0x07F001; } - return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, cmd, NULL); + return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, cmd, NULL); } static void set_next_color_whole_kb(void) @@ -190,7 +190,7 @@ static void set_kbd_backlight_mode(u8 kbd_backlight_mode) { TUXEDO_INFO("Set keyboard backlight mode on %s", kbd_backlight_modes[kbd_backlight_mode].name); - if (!clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, kbd_backlight_modes[kbd_backlight_mode].value, NULL)) { + if (!clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, kbd_backlight_modes[kbd_backlight_mode].value, NULL)) { // method was succesfull so update ur internal state struct kbd_led_state.mode = kbd_backlight_mode; } diff --git a/src/clevo_leds.h b/src/clevo_leds.h index f187488..65164d7 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -46,14 +46,18 @@ void clevo_leds_set_color_extern(u32 color); #include #include -#define CLEVO_KBD_BRIGHTNESS_MIN 0x00 -#define CLEVO_KBD_BRIGHTNESS_MAX 0xff -#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_MIN 0x00 +#define CLEVO_KBD_BRIGHTNESS_MAX 0xff +#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) -#define CLEVO_KB_COLOR_DEFAULT_RED 0xff -#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff -#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff -#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) +#define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness +#define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) + +#define CLEVO_KB_COLOR_DEFAULT_RED 0xff +#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff +#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff +#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) // The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To // not break these, we set this as default for the time being, better having an extra sysfs entry without function than @@ -61,27 +65,34 @@ void clevo_leds_set_color_extern(u32 color); static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; static bool leds_initiaized; -static int clevo_evaluate_set_brightness(u8 brightness) +static int clevo_evaluate_set_white_brightness(u8 brightness) { - pr_debug("Set brightness on %d\n", brightness); + pr_debug("Set white brightness on %d\n", brightness); - return clevo_evaluate_method (CLEVO_CMD_SET_KB_LEDS, CLEVO_CMD_SET_KB_LEDS_SUB_RGB_BRIGHTNESS | brightness, NULL); + return clevo_evaluate_method (CLEVO_CMD_SET_KB_WHITE_LEDS, brightness, NULL); } -static int clevo_evaluate_set_color(u32 zone, u32 color) +static int clevo_evaluate_set_rgb_brightness(u8 brightness) +{ + pr_debug("Set RGB brightness on %d\n", brightness); + + return clevo_evaluate_method (CLEVO_CMD_SET_KB_RGB_LEDS, CLEVO_CMD_SET_KB_LEDS_SUB_RGB_BRIGHTNESS | brightness, NULL); +} + +static int clevo_evaluate_set_rgb_color(u32 zone, u32 color) { u32 cset = ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | ((color & 0x00FF00) >> 8); u32 clevo_submethod_arg = zone | cset; pr_debug("Set Color 0x%08x for region 0x%08x\n", color, zone); - return clevo_evaluate_method(CLEVO_CMD_SET_KB_LEDS, clevo_submethod_arg, NULL); + return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, clevo_submethod_arg, NULL); } static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { - int ret = clevo_evaluate_set_brightness(brightness); + int ret = clevo_evaluate_set_white_brightness(brightness); if (ret) { - pr_debug("clevo_leds_set_brightness(): clevo_evaluate_set_brightness() failed\n"); + pr_debug("clevo_leds_set_brightness(): clevo_evaluate_set_white_brightness() failed\n"); return; } led_cdev->brightness = brightness; @@ -105,9 +116,9 @@ static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unu (mcled_cdev->subled_info[1].brightness << 8) + mcled_cdev->subled_info[2].brightness; - ret = clevo_evaluate_set_color(zone, color); + ret = clevo_evaluate_set_rgb_color(zone, color); if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed\n"); + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_rgb_color() failed\n"); return; } led_cdev->brightness = brightness; @@ -115,7 +126,7 @@ static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unu // Temprary fix for KDE: KDE does only set one kbd_backlight brightness value, this version of the // function uses clevos built in brightness setting to set the whole keyboard brightness at once. -// -> use clevo_evaluate_set_brightness() to set overall brightness via firmware instead of scaling +// -> use clevo_evaluate_set_rgb_brightness() to set overall brightness via firmware instead of scaling // the RGB values // -> update all clevo_mcled_cdevs brightness levels to refect that the firmware method sets the // the whole keyboard brightness and not just one zone @@ -126,9 +137,9 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led u32 zone, color; struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); - ret = clevo_evaluate_set_brightness(brightness); + ret = clevo_evaluate_set_rgb_brightness(brightness); if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed\n"); + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_rgb_brightness() failed\n"); return; } clevo_mcled_cdevs[0].led_cdev.brightness = brightness; @@ -141,17 +152,17 @@ static void clevo_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led (mcled_cdev->subled_info[1].intensity << 8) + mcled_cdev->subled_info[2].intensity; - ret = clevo_evaluate_set_color(zone, color); + ret = clevo_evaluate_set_rgb_color(zone, color); if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_color() failed\n"); + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_rgb_color() failed\n"); } } static struct led_classdev clevo_led_cdev = { .name = "white:" LED_FUNCTION_KBD_BACKLIGHT, - .max_brightness = CLEVO_KBD_BRIGHTNESS_MAX, + .max_brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX, .brightness_set = &clevo_leds_set_brightness, - .brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT + .brightness = CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT }; static struct mc_subled clevo_mcled_cdevs_subleds[3][3] = { From 1f9eb8fd10bb8ac80ebc2f5a3b18380959434001 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 19:12:39 +0200 Subject: [PATCH 29/59] Change default keyboard type as old RGB keyboards are not controllable from OS --- src/clevo_leds.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 65164d7..20b5f8c 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -59,10 +59,7 @@ void clevo_leds_set_color_extern(u32 color); #define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff #define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) -// The very first Clevos with keyboard backlight did have fixed color, but not yet the CLEVO_METHOD_ID_GET_SPECS. To -// not break these, we set this as default for the time being, better having an extra sysfs entry without function than -// a missing one. This is a temporary fix until we find a way to identify these early keyboard backlight devices. -static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; +static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_NONE; static bool leds_initiaized; static int clevo_evaluate_set_white_brightness(u8 brightness) From b9b3c12b643c73a210f222c049a62707cc403f53 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 19:13:38 +0200 Subject: [PATCH 30/59] Fix spelling and reset value --- src/clevo_leds.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 20b5f8c..5175e9e 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -60,7 +60,7 @@ void clevo_leds_set_color_extern(u32 color); #define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_NONE; -static bool leds_initiaized; +static bool leds_initialized = false; static int clevo_evaluate_set_white_brightness(u8 brightness) { @@ -315,7 +315,7 @@ int clevo_leds_init(struct platform_device *dev) } } - leds_initiaized = true; + leds_initialized = true; return 0; } EXPORT_SYMBOL(clevo_leds_init); @@ -335,6 +335,8 @@ int clevo_leds_remove(struct platform_device *dev) { } } + leds_initialized = false; + return 0; } EXPORT_SYMBOL(clevo_leds_remove); From 965e37a5c62329c785033be58b4af246da71dc22 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 31 Aug 2022 19:14:21 +0200 Subject: [PATCH 31/59] Fixed missing variable rename --- src/clevo_leds.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 5175e9e..cb18c54 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -321,7 +321,7 @@ int clevo_leds_init(struct platform_device *dev) EXPORT_SYMBOL(clevo_leds_init); int clevo_leds_remove(struct platform_device *dev) { - if (leds_initiaized) { + if (leds_initialized) { if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { led_classdev_unregister(&clevo_led_cdev); } From 640369f05ee469076670407722a53288884b0988 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 21 Sep 2022 18:14:10 +0200 Subject: [PATCH 32/59] Remove unused function --- src/clevo_keyboard.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index f68dbda..817e50f 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -246,21 +246,6 @@ static u8 param_kbd_backlight_mode = CLEVO_KB_MODE_DEFAULT; module_param_cb(kbd_backlight_mode, ¶m_ops_mode_ops, ¶m_kbd_backlight_mode, S_IRUSR); MODULE_PARM_DESC(kbd_backlight_mode, "Set the keyboard backlight mode"); -// TODO remove -static int brightness_validator(const char *value, - const struct kernel_param *brightness_param) -{ - int brightness = 0; - - if (kstrtoint(value, 10, &brightness) != 0 - || brightness < 0 - || brightness > 255) { - return -EINVAL; - } - - return param_set_int(value, brightness_param); -} - static void clevo_keyboard_event_callb(u32 event) { u32 key_event = event; From 6aacbedc257fe2dd4b322d86a18c8bb088f1a8cd Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 21 Sep 2022 18:14:54 +0200 Subject: [PATCH 33/59] Fix coding style issues --- src/clevo_leds.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index cb18c54..3fdcf70 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -22,6 +22,7 @@ #include #include +#include enum clevo_kb_backlight_types { CLEVO_KB_BACKLIGHT_TYPE_NONE = 0x00, @@ -34,7 +35,7 @@ enum clevo_kb_backlight_types { int clevo_leds_init(struct platform_device *dev); int clevo_leds_remove(struct platform_device *dev); enum clevo_kb_backlight_types clevo_leds_get_backlight_type(void); -void clevo_leds_set_brightness_extern(u32 brightness); +void clevo_leds_set_brightness_extern(enum led_brightness brightness); void clevo_leds_set_color_extern(u32 color); // TODO The following should go into a seperate .c file, but for this to work more reworking is required in the tuxedo_keyboard structure. @@ -43,7 +44,6 @@ void clevo_leds_set_color_extern(u32 color); #include "clevo_interfaces.h" -#include #include #define CLEVO_KBD_BRIGHTNESS_MIN 0x00 @@ -280,7 +280,7 @@ int clevo_leds_init(struct platform_device *dev) if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { pr_debug("Registering fixed color leds interface\n"); ret = led_classdev_register(&dev->dev, &clevo_led_cdev); - if(ret) { + if (ret) { pr_err("Registering fixed color leds interface failed\n"); return ret; } @@ -288,7 +288,7 @@ int clevo_leds_init(struct platform_device *dev) else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { pr_debug("Registering single zone rgb leds interface\n"); ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); - if(ret) { + if (ret) { pr_err("Registering single zone rgb leds interface failed\n"); return ret; } @@ -296,18 +296,18 @@ int clevo_leds_init(struct platform_device *dev) else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { pr_debug("Registering three zone rgb leds interface\n"); ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); - if(ret) { + if (ret) { pr_err("Registering three zone rgb zone 0 leds interface failed\n"); return ret; } ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[1]); - if(ret) { + if (ret) { pr_err("Registering three zone rgb zone 1 leds interface failed\n"); devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); return ret; } ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[2]); - if(ret) { + if (ret) { pr_err("Registering three zone rgb zone 2 leds interface failed\n"); devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[0]); devm_led_classdev_multicolor_unregister(&dev->dev, &clevo_mcled_cdevs[1]); @@ -346,7 +346,7 @@ enum clevo_kb_backlight_types clevo_leds_get_backlight_type() { } EXPORT_SYMBOL(clevo_leds_get_backlight_type); -void clevo_leds_set_brightness_extern(u32 brightness) { +void clevo_leds_set_brightness_extern(enum led_brightness brightness) { if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { clevo_led_cdev.brightness_set(&clevo_led_cdev, brightness); } From f2c442bc2a9ab1a86d3febcadd520948738e0aa4 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 21 Sep 2022 18:17:27 +0200 Subject: [PATCH 34/59] Fix return variables --- src/uniwill_wmi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 40dbc38..5c824f2 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -42,11 +42,11 @@ static bool uniwill_ec_direct = true; DEFINE_MUTEX(uniwill_ec_lock); -static u32 uw_wmi_ec_evaluate(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, u8 read_flag, u32 *return_buffer) +static int uw_wmi_ec_evaluate(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, u8 read_flag, u32 *return_buffer) { acpi_status status; union acpi_object *out_acpi; - u32 e_result = 0; + int e_result = 0; // Kernel buffer for input argument u32 *wmi_arg = (u32 *) kmalloc(sizeof(u32)*10, GFP_KERNEL); @@ -97,10 +97,10 @@ static u32 uw_wmi_ec_evaluate(u8 addr_low, u8 addr_high, u8 data_low, u8 data_hi /** * EC address read through WMI */ -static u32 uw_ec_read_addr_wmi(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) +static int uw_ec_read_addr_wmi(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) { u32 uw_data[10]; - u32 ret = uw_wmi_ec_evaluate(addr_low, addr_high, 0x00, 0x00, 1, uw_data); + int ret = uw_wmi_ec_evaluate(addr_low, addr_high, 0x00, 0x00, 1, uw_data); output->dword = uw_data[0]; // pr_debug("addr: 0x%02x%02x value: %0#4x (high: %0#4x) result: %d\n", addr_high, addr_low, output->bytes.data_low, output->bytes.data_high, ret); return ret; @@ -109,10 +109,10 @@ static u32 uw_ec_read_addr_wmi(u8 addr_low, u8 addr_high, union uw_ec_read_retur /** * EC address write through WMI */ -static u32 uw_ec_write_addr_wmi(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) +static int uw_ec_write_addr_wmi(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) { u32 uw_data[10]; - u32 ret = uw_wmi_ec_evaluate(addr_low, addr_high, data_low, data_high, 0, uw_data); + int ret = uw_wmi_ec_evaluate(addr_low, addr_high, data_low, data_high, 0, uw_data); output->dword = uw_data[0]; return ret; } @@ -120,9 +120,9 @@ static u32 uw_ec_write_addr_wmi(u8 addr_low, u8 addr_high, u8 data_low, u8 data_ /** * Direct EC address read */ -static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) +static int uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) { - u32 result; + int result; u8 tmp, count, flags; mutex_lock(&uniwill_ec_lock); @@ -163,9 +163,9 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re return result; } -static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) +static int uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) { - u32 result = 0; + int result = 0; u8 tmp, count, flags; mutex_lock(&uniwill_ec_lock); @@ -206,9 +206,9 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da return result; } -u32 uw_wmi_read_ec_ram(u16 addr, u8 *data) +int uw_wmi_read_ec_ram(u16 addr, u8 *data) { - u32 result; + int result; u8 addr_low, addr_high; union uw_ec_read_return output; @@ -228,9 +228,9 @@ u32 uw_wmi_read_ec_ram(u16 addr, u8 *data) return result; } -u32 uw_wmi_write_ec_ram(u16 addr, u8 data) +int uw_wmi_write_ec_ram(u16 addr, u8 data) { - u32 result; + int result; u8 addr_low, addr_high, data_low, data_high; union uw_ec_write_return output; From a0c999551848256f9e4c61622a57f5275df4129a Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 21 Sep 2022 18:18:35 +0200 Subject: [PATCH 35/59] First working but buggy implementation of leds interface for TongFang/Uniwill --- src/tuxedo_keyboard_common.h | 18 --- src/uniwill_interfaces.h | 16 ++- src/uniwill_keyboard.h | 242 +++++------------------------------ src/uniwill_leds.h | 219 +++++++++++++++++++++++++------ 4 files changed, 225 insertions(+), 270 deletions(-) diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 35761cb..aae510b 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -102,22 +102,4 @@ static struct color_list_t color_list = { } }; -/** - * Looks up a color in the color_list - * - * Returns found color value, or 0xffffffff if string did not match - */ -static u32 color_lookup(const struct color_list_t *color_list, const char *color_name) -{ - u32 found_color = 0xffffffff; - int i; - for (i = 0; i < color_list->size; ++i) { - if (strcmp(color_list->colors[i].name, color_name) == 0) { - found_color = color_list->colors[i].code; - } - } - - return found_color; -} - #endif diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index 3c1bf45..0c71eaa 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -35,10 +35,16 @@ #define UNIWILL_INTERFACE_WMI_STRID "uniwill_wmi" -typedef u32 (uniwill_read_ec_ram_t)(u16, u8*); -typedef u32 (uniwill_write_ec_ram_t)(u16, u8); +typedef int (uniwill_read_ec_ram_t)(u16, u8*); +typedef int (uniwill_write_ec_ram_t)(u16, u8); typedef void (uniwill_event_callb_t)(u32); +#define UW_EC_REG_KBD_BL_MAX_BRIGHTNESS 0x1801 +#define UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS 0x1802 +#define UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS 0x1803 +#define UW_EC_REG_KBD_BL_RGB_GREEN_BRIGHTNESS 0x1805 +#define UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS 0x1808 + struct uniwill_interface_t { char *string_id; uniwill_event_callb_t *event_callb; @@ -46,11 +52,11 @@ struct uniwill_interface_t { uniwill_write_ec_ram_t *write_ec_ram; }; -u32 uniwill_add_interface(struct uniwill_interface_t *new_interface); -u32 uniwill_remove_interface(struct uniwill_interface_t *interface); +int uniwill_add_interface(struct uniwill_interface_t *new_interface); +int uniwill_remove_interface(struct uniwill_interface_t *interface); uniwill_read_ec_ram_t uniwill_read_ec_ram; uniwill_write_ec_ram_t uniwill_write_ec_ram; -u32 uniwill_get_active_interface_id(char **id_str); +int uniwill_get_active_interface_id(char **id_str); union uw_ec_read_return { u32 dword; diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index cf3fd48..7682b3c 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -31,6 +31,7 @@ #include #include #include "uniwill_interfaces.h" +#include "uniwill_leds.h" #define UNIWILL_OSD_RADIOON 0x01A #define UNIWILL_OSD_RADIOOFF 0x01B @@ -77,9 +78,9 @@ static struct uniwill_interfaces_t { uniwill_event_callb_t uniwill_event_callb; -u32 uniwill_read_ec_ram(u16 address, u8 *data) +int uniwill_read_ec_ram(u16 address, u8 *data) { - u32 status; + int status; if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) status = uniwill_interfaces.wmi->read_ec_ram(address, data); @@ -92,9 +93,9 @@ u32 uniwill_read_ec_ram(u16 address, u8 *data) } EXPORT_SYMBOL(uniwill_read_ec_ram); -u32 uniwill_write_ec_ram(u16 address, u8 data) +int uniwill_write_ec_ram(u16 address, u8 data) { - u32 status; + int status; if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) status = uniwill_interfaces.wmi->write_ec_ram(address, data); @@ -109,7 +110,7 @@ EXPORT_SYMBOL(uniwill_write_ec_ram); static DEFINE_MUTEX(uniwill_interface_modification_lock); -u32 uniwill_add_interface(struct uniwill_interface_t *interface) +int uniwill_add_interface(struct uniwill_interface_t *interface) { mutex_lock(&uniwill_interface_modification_lock); @@ -131,7 +132,7 @@ u32 uniwill_add_interface(struct uniwill_interface_t *interface) } EXPORT_SYMBOL(uniwill_add_interface); -u32 uniwill_remove_interface(struct uniwill_interface_t *interface) +int uniwill_remove_interface(struct uniwill_interface_t *interface) { mutex_lock(&uniwill_interface_modification_lock); @@ -151,7 +152,7 @@ u32 uniwill_remove_interface(struct uniwill_interface_t *interface) } EXPORT_SYMBOL(uniwill_remove_interface); -u32 uniwill_get_active_interface_id(char **id_str) +int uniwill_get_active_interface_id(char **id_str) { if (IS_ERR_OR_NULL(uniwill_interfaces.wmi)) return -ENODEV; @@ -208,18 +209,6 @@ static struct notifier_block keyboard_notifier_block = { .notifier_call = keyboard_notifier_callb }; -static u8 uniwill_read_kbd_bl_enabled(void) -{ - u8 backlight_data; - u8 enabled = 0xff; - - uniwill_read_ec_ram(0x078c, &backlight_data); - enabled = (backlight_data >> 1) & 0x01; - enabled = !enabled; - - return enabled; -} - static void uniwill_write_kbd_bl_enable(u8 enable) { u8 backlight_data; @@ -231,11 +220,6 @@ static void uniwill_write_kbd_bl_enable(u8 enable) uniwill_write_ec_ram(0x078c, backlight_data); } -static void uniwill_write_kbd_bl_reset(void) -{ - uniwill_write_ec_ram(0x078c, 0x10); -} - void uniwill_event_callb(u32 code) { if (uniwill_keyboard_driver.input_device != NULL) @@ -254,145 +238,11 @@ void uniwill_event_callb(u32 code) input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 0); input_sync(uniwill_keyboard_driver.input_device); } - - // Keyboard backlight brightness toggle - if (uniwill_kbd_bl_type_rgb_single_color) { - switch (code) { - case UNIWILL_OSD_KB_LED_LEVEL0: - kbd_led_state_uw.brightness = 0x00; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL1: - kbd_led_state_uw.brightness = 0x20; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL2: - kbd_led_state_uw.brightness = 0x50; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL3: - kbd_led_state_uw.brightness = 0x80; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL4: - kbd_led_state_uw.brightness = 0xc8; - uniwill_write_kbd_bl_state(); - break; - // Also refresh keyboard state on cable switch event - case UNIWILL_OSD_DC_ADAPTER_CHANGE: - uniwill_write_kbd_bl_state(); - break; - } - } } -static ssize_t uw_brightness_show(struct device *child, - struct device_attribute *attr, char *buffer) -{ - return sprintf(buffer, "%d\n", kbd_led_state_uw.brightness); -} - -static enum led_brightness ledcdev_get_uw(struct led_classdev *led_cdev) { - return kbd_led_state_uw.brightness; -} - -static ssize_t uw_brightness_store(struct device *child, - struct device_attribute *attr, - const char *buffer, size_t size) -{ - u32 brightness_input; - int err = kstrtouint(buffer, 0, &brightness_input); - if (err) return err; - if (brightness_input > UNIWILL_BRIGHTNESS_MAX) return -EINVAL; - kbd_led_state_uw.brightness = (u8)brightness_input; - uniwill_write_kbd_bl_state(); - return size; -} - -static int ledcdev_set_blocking_uw_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct led_classdev_mc *led_cdev_mc = lcdev_to_mccdev(led_cdev); - - led_mc_calc_color_components(led_cdev_mc, brightness); - uniwill_write_kbd_bl_rgb(led_cdev_mc->subled_info[0].brightness, - led_cdev_mc->subled_info[1].brightness, - led_cdev_mc->subled_info[2].brightness); - - kbd_led_state_uw.color = ((led_cdev_mc->subled_info[0].intensity * 255 / 200) << 16) + - ((led_cdev_mc->subled_info[1].intensity * 255 / 200) << 8) + - (led_cdev_mc->subled_info[2].intensity * 255 / 200); - kbd_led_state_uw.brightness = brightness; - - return 0; -} - -static ssize_t uw_color_string_show(struct device *child, - struct device_attribute *attr, char *buffer) -{ - int i; - sprintf(buffer, "Color values:"); - for (i = 0; i < color_list.size; ++i) { - sprintf(buffer + strlen(buffer), " %s", - color_list.colors[i].name); - } - sprintf(buffer + strlen(buffer), "\n"); - return strlen(buffer); -} - -static ssize_t uw_color_string_store(struct device *child, - struct device_attribute *attr, - const char *buffer, size_t size) -{ - u32 color_value; - char *buffer_copy; - - buffer_copy = kmalloc(size + 1, GFP_KERNEL); - strcpy(buffer_copy, buffer); - color_value = color_lookup(&color_list, strstrip(buffer_copy)); - kfree(buffer_copy); - - if (color_value > 0xffffff) return -EINVAL; - kbd_led_state_uw.color = color_value; - uniwill_write_kbd_bl_state(); - return size; -} - -// Device attributes used by uw kbd -struct uw_kbd_dev_attrs_t { - struct device_attribute brightness; - struct device_attribute color_string; -} uw_kbd_dev_attrs = { - .brightness = __ATTR(brightness, 0644, uw_brightness_show, uw_brightness_store), - .color_string = __ATTR(color_string, 0644, uw_color_string_show, uw_color_string_store) -}; - -// Device attributes used for uw_kbd_bl_color -static struct attribute *uw_kbd_bl_color_attrs[] = { - &uw_kbd_dev_attrs.brightness.attr, - &uw_kbd_dev_attrs.color_string.attr, - NULL -}; - -static struct attribute_group uw_kbd_bl_color_attr_group = { - .name = "uw_kbd_bl_color", - .attrs = uw_kbd_bl_color_attrs -}; - static void uw_kbd_bl_init_set(void) { - if (uniwill_kbd_bl_type_rgb_single_color) { - // Reset keyboard backlight - uniwill_write_kbd_bl_reset(); - // Make sure reset finish before continue - msleep(100); - - // Disable backlight while initializing - // uniwill_write_kbd_bl_enable(0); - - // Update keyboard backlight according to the current state - uniwill_write_kbd_bl_state(); - } - - // Enable keyboard backlight + uniwill_leds_init_late(); uniwill_write_kbd_bl_enable(1); } @@ -406,6 +256,26 @@ static struct timer_list uw_kbd_bl_init_timer; static volatile int uw_kbd_bl_check_count = 40; static int uw_kbd_bl_init_check_interval_ms = 500; +static int uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) +{ + int result = 0; + + result = uniwill_read_ec_ram(UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS, red); + if (result) { + return result; + } + result = uniwill_read_ec_ram(UW_EC_REG_KBD_BL_RGB_GREEN_BRIGHTNESS, green); + if (result) { + return result; + } + result = uniwill_read_ec_ram(UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS, blue); + if (result) { + return result; + } + + return result; +} + static void uw_kbd_bl_init_ready_check_work_func(struct work_struct *work) { u8 uw_cur_red, uw_cur_green, uw_cur_blue; @@ -446,56 +316,16 @@ static int uw_kbd_bl_init(struct platform_device *dev) { int status = 0; - uniwill_kbd_bl_type_rgb_single_color = false - // New names - | dmi_match(DMI_BOARD_NAME, "POLARIS1501A1650TI") - | dmi_match(DMI_BOARD_NAME, "POLARIS1501A2060") - | dmi_match(DMI_BOARD_NAME, "POLARIS1501I1650TI") - | dmi_match(DMI_BOARD_NAME, "POLARIS1501I2060") - | dmi_match(DMI_BOARD_NAME, "POLARIS1701A1650TI") - | dmi_match(DMI_BOARD_NAME, "POLARIS1701A2060") - | dmi_match(DMI_BOARD_NAME, "POLARIS1701I1650TI") - | dmi_match(DMI_BOARD_NAME, "POLARIS1701I2060") -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) - | dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA02") - | dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI02") - | dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA03") - | dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI03") -#endif - - // Old names - // | dmi_match(DMI_BOARD_NAME, "Polaris15I01") - // | dmi_match(DMI_BOARD_NAME, "Polaris17I01") - // | dmi_match(DMI_BOARD_NAME, "Polaris15A01") - // | dmi_match(DMI_BOARD_NAME, "Polaris1501I2060") - // | dmi_match(DMI_BOARD_NAME, "Polaris1701I2060") - ; - #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) - TUXEDO_ERROR( - "Warning: Kernel version less that 4.18, keyboard backlight might not be properly recognized."); + TUXEDO_ERROR("Warning: Kernel version less that 4.18, keyboard backlight might not be properly recognized."); #endif - // Save previous enable state - uniwill_kbd_bl_enable_state_on_start = uniwill_read_kbd_bl_enabled(); + uniwill_leds_init_early(dev); if (uniwill_kbd_bl_type_rgb_single_color) { - // Initialize keyboard backlight driver state according to parameters - if (param_brightness > UNIWILL_BRIGHTNESS_MAX) param_brightness = UNIWILL_BRIGHTNESS_DEFAULT; - kbd_led_state_uw.brightness = param_brightness; - if (color_lookup(&color_list, param_color) <= (u32) 0xffffff) kbd_led_state_uw.color = color_lookup(&color_list, param_color); - else kbd_led_state_uw.color = UNIWILL_COLOR_DEFAULT; - - // Init sysfs bl attributes group - status = sysfs_create_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); - if (status) TUXEDO_ERROR("Failed to create sysfs group\n"); - // Start periodic checking of animation, set and enable bl when done timer_setup(&uw_kbd_bl_init_timer, uw_kbd_bl_init_ready_check, 0); mod_timer(&uw_kbd_bl_init_timer, jiffies + msecs_to_jiffies(uw_kbd_bl_init_check_interval_ms)); - - // Register leds sysfs interface - devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_uw_mc); } else { // For non-RGB versions // Enable keyboard backlight immediately (should it be disabled) @@ -721,10 +551,7 @@ static int uniwill_keyboard_probe(struct platform_device *dev) static int uniwill_keyboard_remove(struct platform_device *dev) { - - if (uniwill_kbd_bl_type_rgb_single_color) { - sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); - } + uniwill_leds_remove(dev); // Restore previous backlight enable state if (uniwill_kbd_bl_enable_state_on_start != 0xff) { @@ -752,11 +579,6 @@ static int uniwill_keyboard_suspend(struct platform_device *dev, pm_message_t st static int uniwill_keyboard_resume(struct platform_device *dev) { - if (uniwill_kbd_bl_type_rgb_single_color) { - uniwill_write_kbd_bl_reset(); - msleep(100); - uniwill_write_kbd_bl_state(); - } uniwill_write_kbd_bl_enable(1); return 0; } diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index b630f6d..5ad73e1 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -22,18 +22,8 @@ #include #include - -#define UNIWILL_KBD_BRIGHTNESS_MIN 0x00 -#define UNIWILL_KBD_BRIGHTNESS_MAX 0xff // Uniwill devices actually operate on a range - // from 0x00 - 0xc8 (200), but because - // userspace will get it wrong we do the - // conversion in driver. -#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) - -#define UNIWILL_KB_COLOR_DEFAULT_RED 0xff // Same applies as for brightness: Actuall -#define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff // range is 0x00 - 0xc8. Conversion is done in -#define UNIWILL_KB_COLOR_DEFAULT_BLUE 0xff // this driver. -#define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) +#include +#include enum uniwill_kb_backlight_types { UNIWILL_KB_BACKLIGHT_TYPE_NONE, @@ -42,49 +32,97 @@ enum uniwill_kb_backlight_types { UNIWILL_KB_BACKLIGHT_TYPE_PER_KEY_RGB }; -int uniwill_leds_init(struct platform_device *dev); +#define UNIWILL_KBD_BRIGHTNESS_MAX 0xff +#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) + +#define UNIWILL_KB_COLOR_DEFAULT_RED 0xff +#define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff +#define UNIWILL_KB_COLOR_DEFAULT_BLUE 0xff +#define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) + +int uniwill_leds_init_early(struct platform_device *dev); +int uniwill_leds_init_late(void); int uniwill_leds_remove(struct platform_device *dev); enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type(void); -void uniwill_leds_set_brightness_extern(u32 brightness); +void uniwill_leds_set_brightness_extern(enum led_brightness brightness); void uniwill_leds_set_color_extern(u32 color); // TODO The following should go into a seperate .c file, but for this to work more reworking is required in the tuxedo_keyboard structure. -#include "clevo_leds.h" +#include "uniwill_leds.h" -#include "clevo_interfaces.h" +#include "uniwill_interfaces.h" -#include #include -#define FF_TO_UW_RANGE(x) (x * 0xc8 / 0xff) -#define UW_TO_FF_RANGE(x) (x * 0xff / 0xc8) +static enum uniwill_kb_backlight_types uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR; +static bool uw_leds_initialized = false; +//static DECLARE_COMPLETION(init_done); -static u32 uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) +static int uniwill_write_kbd_bl_white(u8 brightness) { - u32 result; + //wait_for_completion(&init_done); - uniwill_read_ec_ram(0x1803, red); - uniwill_read_ec_ram(0x1805, green); - uniwill_read_ec_ram(0x1808, blue); + return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS, brightness); +} - result = 0; +static int uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) +{ + int result = 0; + + //wait_for_completion(&init_done); + + result = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS, red); + if (result) { + return result; + } + result = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_RGB_GREEN_BRIGHTNESS, green); + if (result) { + return result; + } + result = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS, blue); + if (result) { + return result; + } + + pr_debug("Wrote kbd color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); return result; } -static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) -{ - if (red > 0xc8) red = 0xc8; - if (green > 0xc8) green = 0xc8; - if (blue > 0xc8) blue = 0xc8; - uniwill_write_ec_ram(0x1803, red); - uniwill_write_ec_ram(0x1805, green); - uniwill_write_ec_ram(0x1808, blue); - TUXEDO_DEBUG("Wrote kbd color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); +static void uniwill_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { + int ret = uniwill_write_kbd_bl_white(brightness); + if (ret) { + pr_debug("uniwill_leds_set_brightness(): uniwill_write_kbd_bl_white() failed\n"); + return; + } + led_cdev->brightness = brightness; } -static struct mc_subled clevo_mcled_cdev_subleds[3] = { +static void uniwill_leds_set_brightness_mc(struct led_classdev *led_cdev, enum led_brightness brightness) { + int ret; + struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); + + led_mc_calc_color_components(mcled_cdev, brightness); + + ret = uniwill_write_kbd_bl_rgb(mcled_cdev->subled_info[0].brightness, + mcled_cdev->subled_info[1].brightness, + mcled_cdev->subled_info[2].brightness); + if (ret) { + pr_debug("uniwill_leds_set_brightness_mc(): uniwill_write_kbd_bl_rgb() failed\n"); + return; + } + led_cdev->brightness = brightness; +} + +static struct led_classdev uniwill_led_cdev = { + .name = "white:" LED_FUNCTION_KBD_BACKLIGHT, + .max_brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .brightness_set = &uniwill_leds_set_brightness, + .brightness = UNIWILL_KBD_BRIGHTNESS_DEFAULT +}; + +static struct mc_subled uw_mcled_cdev_subleds[3] = { { .color_index = LED_COLOR_ID_RED, .brightness = UNIWILL_KBD_BRIGHTNESS_MAX, @@ -108,10 +146,117 @@ static struct mc_subled clevo_mcled_cdev_subleds[3] = { static struct led_classdev_mc uniwill_mcled_cdev = { .led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT, .led_cdev.max_brightness = UNIWILL_KBD_BRIGHTNESS_MAX, - .led_cdev.brightness = &uniwill_leds_set_brightness_mc, + .led_cdev.brightness_set = &uniwill_leds_set_brightness_mc, .led_cdev.brightness = UNIWILL_KBD_BRIGHTNESS_DEFAULT, .num_colors = 3, - .subled_info = cdev_kb_uw_mc_subled + .subled_info = uw_mcled_cdev_subleds }; +int uniwill_leds_init_early(struct platform_device *dev) +{ + int ret; + + if ( dmi_match(DMI_BOARD_NAME, "POLARIS1501A1650TI") + || dmi_match(DMI_BOARD_NAME, "POLARIS1501A2060") + || dmi_match(DMI_BOARD_NAME, "POLARIS1501I1650TI") + || dmi_match(DMI_BOARD_NAME, "POLARIS1501I2060") + || dmi_match(DMI_BOARD_NAME, "POLARIS1701A1650TI") + || dmi_match(DMI_BOARD_NAME, "POLARIS1701A2060") + || dmi_match(DMI_BOARD_NAME, "POLARIS1701I1650TI") + || dmi_match(DMI_BOARD_NAME, "POLARIS1701I2060") +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) + || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA02") + || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI02") + || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA03") + || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI03") +#endif + ) { + uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB; + } + pr_debug("Keyboard backlight type: 0x%02x\n", uniwill_kb_backlight_type); + + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + pr_debug("Registering fixed color leds interface\n"); + ret = led_classdev_register(&dev->dev, &uniwill_led_cdev); + if (ret) { + pr_err("Registering fixed color leds interface failed\n"); + return ret; + } + } + else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + pr_debug("Registering single zone rgb leds interface\n"); + ret = devm_led_classdev_multicolor_register(&dev->dev, &uniwill_mcled_cdev); + if (ret) { + pr_err("Registering single zone rgb leds interface failed\n"); + return ret; + } + } + + uw_leds_initialized = true; + return 0; +} +EXPORT_SYMBOL(uniwill_leds_init_early); + +int uniwill_leds_init_late() +{ + int ret; + + ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xff); + if (ret) { + pr_err("Setting max keyboard brightness value failed\n"); + return ret; + } + + uniwill_leds_set_brightness_extern(UNIWILL_KBD_BRIGHTNESS_DEFAULT); + uniwill_leds_set_color_extern(UNIWILL_KB_COLOR_DEFAULT); + + //complete_all(&init_done); + + return 0; +} +EXPORT_SYMBOL(uniwill_leds_init_late); + +int uniwill_leds_remove(struct platform_device *dev) { + if (uw_leds_initialized) { + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + led_classdev_unregister(&uniwill_led_cdev); + } + else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + devm_led_classdev_multicolor_unregister(&dev->dev, &uniwill_mcled_cdev); + } + } + + uw_leds_initialized = false; + + return 0; +} +EXPORT_SYMBOL(uniwill_leds_remove); + +enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type() { + return uniwill_kb_backlight_type; +} +EXPORT_SYMBOL(uniwill_leds_get_backlight_type); + +void uniwill_leds_set_brightness_extern(enum led_brightness brightness) { + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + uniwill_led_cdev.brightness_set(&uniwill_led_cdev, brightness); + } + else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, brightness); + } +} +EXPORT_SYMBOL(uniwill_leds_set_brightness_extern); + +void uniwill_leds_set_color_extern(u32 color) { + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + uniwill_mcled_cdev.subled_info[0].intensity = (color >> 16) & 0xff; + uniwill_mcled_cdev.subled_info[1].intensity = (color >> 8) & 0xff; + uniwill_mcled_cdev.subled_info[2].intensity = color & 0xff; + uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, uniwill_mcled_cdev.led_cdev.brightness); + } +} +EXPORT_SYMBOL(uniwill_leds_set_color_extern); + +MODULE_LICENSE("GPL"); + #endif // UNIWILL_LEDS_H From b73152ba8bb6ae9df208773df5d81e713a18d116 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 23 Sep 2022 15:47:42 +0200 Subject: [PATCH 36/59] Fix resume behavior --- src/uniwill_interfaces.h | 3 +++ src/uniwill_keyboard.h | 27 +++++++++++++++----- src/uniwill_leds.h | 55 +++++++++++++++++++++++++++------------- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index 0c71eaa..9c03b89 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -39,6 +39,9 @@ typedef int (uniwill_read_ec_ram_t)(u16, u8*); typedef int (uniwill_write_ec_ram_t)(u16, u8); typedef void (uniwill_event_callb_t)(u32); +#define UW_EC_REG_KBD_BL_STATUS 0x078c +#define UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET 0x10 + #define UW_EC_REG_KBD_BL_MAX_BRIGHTNESS 0x1801 #define UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS 0x1802 #define UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS 0x1803 diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 7682b3c..03b539f 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -41,6 +41,7 @@ #define UNIWILL_OSD_KB_LED_LEVEL3 0x03E #define UNIWILL_OSD_KB_LED_LEVEL4 0x03F #define UNIWILL_OSD_DC_ADAPTER_CHANGE 0x0AB +#define UNIWILL_OSD_MODE_CHANGE_KEY_EVENT 0x0B0 #define UNIWILL_KEY_RFKILL 0x0A4 #define UNIWILL_KEY_KBDILLUMDOWN 0x0B1 @@ -65,6 +66,11 @@ static struct key_entry uniwill_wmi_keymap[] = { { KE_KEY, UNIWILL_KEY_KBDILLUMDOWN, { KEY_KBDILLUMDOWN } }, { KE_KEY, UNIWILL_KEY_KBDILLUMUP, { KEY_KBDILLUMUP } }, { KE_KEY, UNIWILL_KEY_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL0, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL1, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL2, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL3, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL4, { KEY_KBDILLUMTOGGLE } }, // Only used to put ev bits { KE_KEY, 0xffff, { KEY_F6 } }, { KE_KEY, 0xffff, { KEY_LEFTALT } }, @@ -214,10 +220,10 @@ static void uniwill_write_kbd_bl_enable(u8 enable) u8 backlight_data; enable = enable & 0x01; - uniwill_read_ec_ram(0x078c, &backlight_data); + uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &backlight_data); backlight_data = backlight_data & ~(1 << 1); backlight_data |= (!enable << 1); - uniwill_write_ec_ram(0x078c, backlight_data); + uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, backlight_data); } void uniwill_event_callb(u32 code) @@ -228,7 +234,7 @@ void uniwill_event_callb(u32 code) } // Special key combination when mode change key is pressed - if (code == 0xb0) { + if (code == UNIWILL_OSD_MODE_CHANGE_KEY_EVENT) { input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 1); input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTALT, 1); input_report_key(uniwill_keyboard_driver.input_device, KEY_F6, 1); @@ -238,11 +244,16 @@ void uniwill_event_callb(u32 code) input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 0); input_sync(uniwill_keyboard_driver.input_device); } + + // Refresh keyboard state on cable switch event + if (code == UNIWILL_OSD_DC_ADAPTER_CHANGE) { + uniwill_leds_restore_state_extern(); + } } -static void uw_kbd_bl_init_set(void) +static void uw_kbd_bl_init_set(struct platform_device *dev) { - uniwill_leds_init_late(); + uniwill_leds_init_late(dev); uniwill_write_kbd_bl_enable(1); } @@ -276,6 +287,8 @@ static int uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) return result; } +static struct platform_device *uw_kbd_bl_init_ready_check_work_func_args_dev; + static void uw_kbd_bl_init_ready_check_work_func(struct work_struct *work) { u8 uw_cur_red, uw_cur_green, uw_cur_blue; @@ -291,7 +304,7 @@ static void uw_kbd_bl_init_ready_check_work_func(struct work_struct *work) } if (prev_colors_same) { - uw_kbd_bl_init_set(); + uw_kbd_bl_init_set(uw_kbd_bl_init_ready_check_work_func_args_dev); del_timer(&uw_kbd_bl_init_timer); } else { if (uw_kbd_bl_check_count != 0) { @@ -324,6 +337,7 @@ static int uw_kbd_bl_init(struct platform_device *dev) if (uniwill_kbd_bl_type_rgb_single_color) { // Start periodic checking of animation, set and enable bl when done + uw_kbd_bl_init_ready_check_work_func_args_dev = dev; timer_setup(&uw_kbd_bl_init_timer, uw_kbd_bl_init_ready_check, 0); mod_timer(&uw_kbd_bl_init_timer, jiffies + msecs_to_jiffies(uw_kbd_bl_init_check_interval_ms)); } else { @@ -579,6 +593,7 @@ static int uniwill_keyboard_suspend(struct platform_device *dev, pm_message_t st static int uniwill_keyboard_resume(struct platform_device *dev) { + uniwill_leds_restore_state_extern(); uniwill_write_kbd_bl_enable(1); return 0; } diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index 5ad73e1..6be2dee 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -41,9 +41,10 @@ enum uniwill_kb_backlight_types { #define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) int uniwill_leds_init_early(struct platform_device *dev); -int uniwill_leds_init_late(void); +int uniwill_leds_init_late(struct platform_device *dev); int uniwill_leds_remove(struct platform_device *dev); enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type(void); +void uniwill_leds_restore_state_extern(void); void uniwill_leds_set_brightness_extern(enum led_brightness brightness); void uniwill_leds_set_color_extern(u32 color); @@ -192,32 +193,33 @@ int uniwill_leds_init_early(struct platform_device *dev) } } + // FIXME Race condition? uw_leds_initialized = true; return 0; } EXPORT_SYMBOL(uniwill_leds_init_early); -int uniwill_leds_init_late() +int uniwill_leds_init_late(struct platform_device *dev) { int ret; ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xff); if (ret) { pr_err("Setting max keyboard brightness value failed\n"); + uniwill_leds_remove(dev); return ret; } - uniwill_leds_set_brightness_extern(UNIWILL_KBD_BRIGHTNESS_DEFAULT); - uniwill_leds_set_color_extern(UNIWILL_KB_COLOR_DEFAULT); - - //complete_all(&init_done); + uniwill_leds_restore_state_extern(); return 0; } EXPORT_SYMBOL(uniwill_leds_init_late); int uniwill_leds_remove(struct platform_device *dev) { + // FIXME Race condition? if (uw_leds_initialized) { + uw_leds_initialized = false; if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { led_classdev_unregister(&uniwill_led_cdev); } @@ -226,8 +228,6 @@ int uniwill_leds_remove(struct platform_device *dev) { } } - uw_leds_initialized = false; - return 0; } EXPORT_SYMBOL(uniwill_leds_remove); @@ -237,22 +237,41 @@ enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type() { } EXPORT_SYMBOL(uniwill_leds_get_backlight_type); -void uniwill_leds_set_brightness_extern(enum led_brightness brightness) { - if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - uniwill_led_cdev.brightness_set(&uniwill_led_cdev, brightness); +void uniwill_leds_restore_state_extern(void) { + if (uw_leds_initialized) { + uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET); + msleep(100); // Make sure reset finish before continue + + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + uniwill_led_cdev.brightness_set(&uniwill_led_cdev, uniwill_led_cdev.brightness); + } + else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, uniwill_mcled_cdev.led_cdev.brightness); + } } - else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, brightness); +} +EXPORT_SYMBOL(uniwill_leds_restore_state_extern); + +void uniwill_leds_set_brightness_extern(enum led_brightness brightness) { + if (uw_leds_initialized) { + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + uniwill_led_cdev.brightness_set(&uniwill_led_cdev, brightness); + } + else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, brightness); + } } } EXPORT_SYMBOL(uniwill_leds_set_brightness_extern); void uniwill_leds_set_color_extern(u32 color) { - if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { - uniwill_mcled_cdev.subled_info[0].intensity = (color >> 16) & 0xff; - uniwill_mcled_cdev.subled_info[1].intensity = (color >> 8) & 0xff; - uniwill_mcled_cdev.subled_info[2].intensity = color & 0xff; - uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, uniwill_mcled_cdev.led_cdev.brightness); + if (uw_leds_initialized) { + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + uniwill_mcled_cdev.subled_info[0].intensity = (color >> 16) & 0xff; + uniwill_mcled_cdev.subled_info[1].intensity = (color >> 8) & 0xff; + uniwill_mcled_cdev.subled_info[2].intensity = color & 0xff; + uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, uniwill_mcled_cdev.led_cdev.brightness); + } } } EXPORT_SYMBOL(uniwill_leds_set_color_extern); From dd22af992474fd58cad0fa6bc9768cc0919a51f8 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 14:20:16 +0200 Subject: [PATCH 37/59] Add keyboard type check for old devices --- src/clevo_interfaces.h | 3 +++ src/clevo_leds.h | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 9077032..3666523 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -41,6 +41,9 @@ #define CLEVO_CMD_GET_EVENT 0x01 #define CLEVO_CMD_GET_SPECS 0x0D // Returns buffer -> only works with clevo_evaluate_method2 +#define CLEVO_CMD_GET_BIOS_FEATURES 0x52 +#define CLEVO_CMD_GET_BIOS_FEATURES_SUB_WHITE_ONLY_KB 0x40000000 +#define CLEVO_CMD_GET_BIOS_FEATURES_SUB_3_ZONE_RGB_KB 0x00400000 // The clevo set commands expect a parameter #define CLEVO_CMD_SET_FANSPEED_VALUE 0x68 diff --git a/src/clevo_leds.h b/src/clevo_leds.h index cb18c54..7070308 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -257,6 +257,7 @@ int clevo_leds_init(struct platform_device *dev) int ret; u32 status; union acpi_object *result; + u32 result_fallback; status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); if (!status) { @@ -270,7 +271,21 @@ int clevo_leds_init(struct platform_device *dev) ACPI_FREE(result); } else { - pr_err("CLEVO_CMD_GET_SPECS failed\n"); + pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); + + // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) + status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES, 0, &result_fallback); + if (!status) { + if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_3_ZONE_RGB_KB) { + clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB; + } + else if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_WHITE_ONLY_KB) { + clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; + } + } + else { + pr_notice("CLEVO_CMD_GET_BIOS_FEATURES failed\n"); + } } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); From c4b7644f83fe22e8ac73f725cc2fac4de9f0247c Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 14:32:43 +0200 Subject: [PATCH 38/59] Fix if case logic --- src/clevo_leds.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 7070308..42bfdfd 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -266,13 +266,15 @@ int clevo_leds_init(struct platform_device *dev) clevo_kb_backlight_type = result->buffer.pointer[0x0f]; } else { - pr_err("CLEVO_CMD_GET_SPECS return value has wrong type\n"); + pr_err("CLEVO_CMD_GET_SPECS does not exist on this device or return value has wrong type, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); + status = -EINVAL } ACPI_FREE(result); } else { pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); - + } + if (status) { // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES, 0, &result_fallback); if (!status) { @@ -284,7 +286,7 @@ int clevo_leds_init(struct platform_device *dev) } } else { - pr_notice("CLEVO_CMD_GET_BIOS_FEATURES failed\n"); + pr_notice("CLEVO_CMD_GET_BIOS_FEATURES does not exist on this device or failed\n"); } } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); From 8e2d526a8a572b44b587d060a703f1bbad1849fa Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 14:33:50 +0200 Subject: [PATCH 39/59] Add missing ; --- src/clevo_leds.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 42bfdfd..ab67098 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -267,7 +267,7 @@ int clevo_leds_init(struct platform_device *dev) } else { pr_err("CLEVO_CMD_GET_SPECS does not exist on this device or return value has wrong type, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); - status = -EINVAL + status = -EINVAL; } ACPI_FREE(result); } From 55b6b5ce940caae0d9bf2b0c58651ea56c05c55f Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 14:52:12 +0200 Subject: [PATCH 40/59] More debug output --- src/clevo_leds.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index ab67098..ea77717 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -262,8 +262,8 @@ int clevo_leds_init(struct platform_device *dev) status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); if (!status) { if (result->type == ACPI_TYPE_BUFFER) { - pr_debug("CLEVO_CMD_GET_SPECS successful\n"); - clevo_kb_backlight_type = result->buffer.pointer[0x0f]; + pr_debug("CLEVO_CMD_GET_SPECS result->buffer.pointer[0x0f]: 0x%02x\n", result->buffer.pointer[0x0f]); + clevo_kb_backlight_type = result->buffer.pointer[0x0f]; } else { pr_err("CLEVO_CMD_GET_SPECS does not exist on this device or return value has wrong type, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); @@ -278,6 +278,7 @@ int clevo_leds_init(struct platform_device *dev) // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES, 0, &result_fallback); if (!status) { + pr_debug("CLEVO_CMD_GET_BIOS_FEATURES result_fallback: 0x%08x\n", result_fallback); if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_3_ZONE_RGB_KB) { clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB; } From fafba1181734ade65860d045f977f18fee36c50f Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 15:09:13 +0200 Subject: [PATCH 41/59] Fix number of steps --- src/clevo_leds.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index ea77717..30945bb 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -52,6 +52,7 @@ void clevo_leds_set_color_extern(u32 color); #define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 #define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_OLD_DEVS 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off #define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) #define CLEVO_KB_COLOR_DEFAULT_RED 0xff @@ -284,6 +285,7 @@ int clevo_leds_init(struct platform_device *dev) } else if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_WHITE_ONLY_KB) { clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; + clevo_led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_OLD_DEVS; } } else { From 4dbaa4a83dcd44a47dd6928feedd70d089bab5fa Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 16:10:44 +0200 Subject: [PATCH 42/59] Check available steps for white only --- src/clevo_interfaces.h | 9 ++++++--- src/clevo_leds.h | 26 ++++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 3666523..fabeff5 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -41,9 +41,12 @@ #define CLEVO_CMD_GET_EVENT 0x01 #define CLEVO_CMD_GET_SPECS 0x0D // Returns buffer -> only works with clevo_evaluate_method2 -#define CLEVO_CMD_GET_BIOS_FEATURES 0x52 -#define CLEVO_CMD_GET_BIOS_FEATURES_SUB_WHITE_ONLY_KB 0x40000000 -#define CLEVO_CMD_GET_BIOS_FEATURES_SUB_3_ZONE_RGB_KB 0x00400000 +#define CLEVO_CMD_GET_BIOS_FEATURES_1 0x52 +#define CLEVO_CMD_GET_BIOS_FEATURES_1_SUB_WHITE_ONLY_KB 0x40000000 +#define CLEVO_CMD_GET_BIOS_FEATURES_1_SUB_3_ZONE_RGB_KB 0x00400000 + +#define CLEVO_CMD_GET_BIOS_FEATURES_2 0x7A +#define CLEVO_CMD_GET_BIOS_FEATURES_2_SUB_WHITE_ONLY_KB_MAX_5 0x4000 // The clevo set commands expect a parameter #define CLEVO_CMD_SET_FANSPEED_VALUE 0x68 diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 30945bb..672c885 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -52,7 +52,7 @@ void clevo_leds_set_color_extern(u32 color); #define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 #define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness -#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_OLD_DEVS 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off #define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) #define CLEVO_KB_COLOR_DEFAULT_RED 0xff @@ -273,23 +273,33 @@ int clevo_leds_init(struct platform_device *dev) ACPI_FREE(result); } else { - pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES\n"); + pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES_1\n"); } if (status) { // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) - status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES, 0, &result_fallback); + status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES_1, 0, &result_fallback); if (!status) { - pr_debug("CLEVO_CMD_GET_BIOS_FEATURES result_fallback: 0x%08x\n", result_fallback); - if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_3_ZONE_RGB_KB) { + pr_debug("CLEVO_CMD_GET_BIOS_FEATURES_1 result_fallback: 0x%08x\n", result_fallback); + if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_1_SUB_3_ZONE_RGB_KB) { clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB; } - else if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_SUB_WHITE_ONLY_KB) { + else if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_1_SUB_WHITE_ONLY_KB) { clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR; - clevo_led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_OLD_DEVS; + + status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES_2, 0, &result_fallback); + if (!status) { + pr_debug("CLEVO_CMD_GET_BIOS_FEATURES_2 result_fallback: 0x%08x\n", result_fallback); + if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_2_SUB_WHITE_ONLY_KB_MAX_5) { + clevo_led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5; + } + } + else { + pr_notice("CLEVO_CMD_GET_BIOS_FEATURES_2 does not exist on this device or failed\n"); + } } } else { - pr_notice("CLEVO_CMD_GET_BIOS_FEATURES does not exist on this device or failed\n"); + pr_notice("CLEVO_CMD_GET_BIOS_FEATURES_1 does not exist on this device or failed\n"); } } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); From 011ad1c5565c639a1dc6e22b74957fe5c361a5b3 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 24 Oct 2022 16:27:20 +0200 Subject: [PATCH 43/59] Fix default brightness --- src/clevo_leds.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 672c885..a0a7790 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -50,10 +50,11 @@ void clevo_leds_set_color_extern(u32 color); #define CLEVO_KBD_BRIGHTNESS_MAX 0xff #define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) -#define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 -#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness -#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off -#define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness +#define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) #define CLEVO_KB_COLOR_DEFAULT_RED 0xff #define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff @@ -259,6 +260,7 @@ int clevo_leds_init(struct platform_device *dev) u32 status; union acpi_object *result; u32 result_fallback; + u8 default_brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT; status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); if (!status) { @@ -304,7 +306,11 @@ int clevo_leds_init(struct platform_device *dev) } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); - clevo_leds_set_brightness_extern(CLEVO_KBD_BRIGHTNESS_DEFAULT); + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { + default_brightness = clevo_led_cdev.max_brightness / 2; + } + + clevo_leds_set_brightness_extern(default_brightness); clevo_leds_set_color_extern(CLEVO_KB_COLOR_DEFAULT); if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { From 69cdf54752a71a0429cac39e0a094b5e922b7a8b Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Tue, 25 Oct 2022 13:46:46 +0200 Subject: [PATCH 44/59] Restore led state on remove --- src/uniwill_leds.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index 6be2dee..6d7c305 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -155,6 +155,7 @@ static struct led_classdev_mc uniwill_mcled_cdev = { int uniwill_leds_init_early(struct platform_device *dev) { + // FIXME Use mutexes int ret; if ( dmi_match(DMI_BOARD_NAME, "POLARIS1501A1650TI") @@ -193,7 +194,6 @@ int uniwill_leds_init_early(struct platform_device *dev) } } - // FIXME Race condition? uw_leds_initialized = true; return 0; } @@ -201,6 +201,7 @@ EXPORT_SYMBOL(uniwill_leds_init_early); int uniwill_leds_init_late(struct platform_device *dev) { + // FIXME Use mutexes int ret; ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xff); @@ -217,9 +218,11 @@ int uniwill_leds_init_late(struct platform_device *dev) EXPORT_SYMBOL(uniwill_leds_init_late); int uniwill_leds_remove(struct platform_device *dev) { - // FIXME Race condition? + // FIXME Use mutexes if (uw_leds_initialized) { uw_leds_initialized = false; + uniwill_leds_set_brightness_extern(0x00); + ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xc8); if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { led_classdev_unregister(&uniwill_led_cdev); } From 8d67160ea874a80c78193bf7b426f4caf69d8c07 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Tue, 25 Oct 2022 14:06:38 +0200 Subject: [PATCH 45/59] Add missing error handling --- src/uniwill_leds.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index 6d7c305..2d3b8af 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -217,12 +217,20 @@ int uniwill_leds_init_late(struct platform_device *dev) } EXPORT_SYMBOL(uniwill_leds_init_late); -int uniwill_leds_remove(struct platform_device *dev) { +int uniwill_leds_remove(struct platform_device *dev) +{ // FIXME Use mutexes + int ret; + if (uw_leds_initialized) { uw_leds_initialized = false; + uniwill_leds_set_brightness_extern(0x00); ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xc8); + if (ret) { + pr_err("Resetting max keyboard brightness value failed\n"); + } + if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { led_classdev_unregister(&uniwill_led_cdev); } @@ -231,7 +239,7 @@ int uniwill_leds_remove(struct platform_device *dev) { } } - return 0; + return ret; } EXPORT_SYMBOL(uniwill_leds_remove); From 099be56b62c46220969da4db2b9d415f59158a45 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 26 Oct 2022 13:43:37 +0200 Subject: [PATCH 46/59] Add keyboard type detection based on EC --- src/uniwill_interfaces.h | 34 +++++++++++++++++++++------ src/uniwill_leds.h | 51 ++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index 4f8655d..5a2a285 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -40,14 +40,34 @@ typedef int (uniwill_write_ec_ram_t)(u16, u8); typedef int (uniwill_write_ec_ram_with_retry_t)(u16, u8, int); typedef void (uniwill_event_callb_t)(u32); -#define UW_EC_REG_KBD_BL_STATUS 0x078c -#define UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET 0x10 +// UW_EC_REG_* known relevant EC address exposing some information or function +// UW_EC_REG_*_BIT_* single bit from byte holding information, should be handled with bit-wise operations +// UW_EC_REG_*_VALUE_* discrete value of the whole byte with special meaning +// UW_EC_REG_*_SUBCMD_* writing this discrete value triggers special behaviour -#define UW_EC_REG_KBD_BL_MAX_BRIGHTNESS 0x1801 -#define UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS 0x1802 -#define UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS 0x1803 -#define UW_EC_REG_KBD_BL_RGB_GREEN_BRIGHTNESS 0x1805 -#define UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS 0x1808 +#define UW_EC_REG_KBD_BL_STATUS 0x078c +#define UW_EC_REG_KBD_BL_STATUS_BIT_WHITE_ONLY_KB 0x01 +#define UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET 0x10 + +#define UW_EC_REG_KBD_BL_MAX_BRIGHTNESS 0x1801 +#define UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS 0x1802 +#define UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS 0x1803 +#define UW_EC_REG_KBD_BL_RGB_GREEN_BRIGHTNESS 0x1805 +#define UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS 0x1808 + +#define UW_EC_REG_BAREBONE_ID 0x0740 +#define UW_EC_REG_BAREBONE_ID_VALUE_PFxxxxx 0x09 +#define UW_EC_REG_BAREBONE_ID_VALUE_PFxMxxx 0x0e +#define UW_EC_REG_BAREBONE_ID_VALUE_PH4TRX1 0x12 +#define UW_EC_REG_BAREBONE_ID_VALUE_PH4TUX1 0x13 +#define UW_EC_REG_BAREBONE_ID_VALUE_PH4TQx1 0x14 +#define UW_EC_REG_BAREBONE_ID_VALUE_PH6TRX1 0x15 +#define UW_EC_REG_BAREBONE_ID_VALUE_PH6TQxx 0x16 +#define UW_EC_REG_BAREBONE_ID_VALUE_PH4Axxx 0x17 + +#define UW_EC_REG_FEATURES_0 0x0765 +#define UW_EC_REG_FEATURES_1 0x0766 +#define UW_EC_REG_FEATURES_1_BIT_1_ZONE_RGB_KB 0x04 struct uniwill_interface_t { char *string_id; diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index 2d3b8af..a3bc911 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -56,7 +56,7 @@ void uniwill_leds_set_color_extern(u32 color); #include -static enum uniwill_kb_backlight_types uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR; +static enum uniwill_kb_backlight_types uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_NONE; static bool uw_leds_initialized = false; //static DECLARE_COMPLETION(init_done); @@ -157,23 +157,40 @@ int uniwill_leds_init_early(struct platform_device *dev) { // FIXME Use mutexes int ret; + u8 data; - if ( dmi_match(DMI_BOARD_NAME, "POLARIS1501A1650TI") - || dmi_match(DMI_BOARD_NAME, "POLARIS1501A2060") - || dmi_match(DMI_BOARD_NAME, "POLARIS1501I1650TI") - || dmi_match(DMI_BOARD_NAME, "POLARIS1501I2060") - || dmi_match(DMI_BOARD_NAME, "POLARIS1701A1650TI") - || dmi_match(DMI_BOARD_NAME, "POLARIS1701A2060") - || dmi_match(DMI_BOARD_NAME, "POLARIS1701I1650TI") - || dmi_match(DMI_BOARD_NAME, "POLARIS1701I2060") -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) - || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA02") - || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI02") - || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XA03") - || dmi_match(DMI_PRODUCT_SKU, "POLARIS1XI03") -#endif - ) { - uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB; + ret = uniwill_read_ec_ram(UW_EC_REG_BAREBONE_ID, &data); + if (ret) { + pr_err("Reading barebone ID failed.\n"); + return ret; + } + + if (data == UW_EC_REG_BAREBONE_ID_VALUE_PFxxxxx || + data == UW_EC_REG_BAREBONE_ID_VALUE_PFxMxxx || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH4TRX1 || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH4TUX1 || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH4TQx1 || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH6TRX1 || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH6TQxx || + data == UW_EC_REG_BAREBONE_ID_VALUE_PH4Axxx) { + ret = uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); + if (ret) { + pr_err("Reading keyboard backlight status failed.\n"); + return ret; + } + if (data & UW_EC_REG_KBD_BL_STATUS_BIT_WHITE_ONLY_KB) { + uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR; + } + } + else { + ret = uniwill_read_ec_ram(UW_EC_REG_FEATURES_1, &data); + if (ret) { + pr_err("Reading features 1 failed.\n"); + return ret; + } + if (data & UW_EC_REG_FEATURES_1_BIT_1_ZONE_RGB_KB) { + uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB; + } } pr_debug("Keyboard backlight type: 0x%02x\n", uniwill_kb_backlight_type); From a9ca7fae63faa06ce66b01520c3f6329943e8ccb Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 9 Nov 2022 17:14:55 +0100 Subject: [PATCH 47/59] Revert switch to kbuild --- Makefile | 6 +++++- src/Kbuild | 8 -------- 2 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 src/Kbuild diff --git a/Makefile b/Makefile index 5e908f8..c60cf4d 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := src/ +obj-m := ./src/tuxedo_keyboard.o \ + ./src/clevo_wmi.o \ + ./src/clevo_acpi.o \ + ./src/tuxedo_io/tuxedo_io.o \ + ./src/uniwill_wmi.o PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/src/Kbuild b/src/Kbuild deleted file mode 100644 index 0d77606..0000000 --- a/src/Kbuild +++ /dev/null @@ -1,8 +0,0 @@ -obj-m := tuxedo_keyboard.o \ - clevo_wmi.o \ - clevo_acpi.o \ - tuxedo_io/tuxedo_io.o \ - uniwill_wmi.o - -#clevo_wmi-y := clevo_leds.o -#clevo_acpi-y := clevo_leds.o From 96fcac547b485f7351b3efa3eeb52b2c55583d8f Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 9 Nov 2022 17:19:57 +0100 Subject: [PATCH 48/59] Add debug status print --- src/tuxedo_io/tuxedo_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 0206bee..30e5ff5 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -801,6 +801,8 @@ static int __init tuxedo_io_init(void) id_check_uniwill = uniwill_identify(); #ifdef DEBUG + pr_debug("DEBUG is defined\n") + if (id_check_clevo == 0 && id_check_uniwill == 0) { pr_debug("No matching hardware found on module load\n"); } From bbe7b1cbebb252f91ac057a3293775758a9db54c Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 9 Nov 2022 17:31:38 +0100 Subject: [PATCH 49/59] Remove leftover commented code --- src/uniwill_leds.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index a3bc911..83b1f5c 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -58,11 +58,9 @@ void uniwill_leds_set_color_extern(u32 color); static enum uniwill_kb_backlight_types uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_NONE; static bool uw_leds_initialized = false; -//static DECLARE_COMPLETION(init_done); static int uniwill_write_kbd_bl_white(u8 brightness) { - //wait_for_completion(&init_done); return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS, brightness); } @@ -71,8 +69,6 @@ static int uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) { int result = 0; - //wait_for_completion(&init_done); - result = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_RGB_RED_BRIGHTNESS, red); if (result) { return result; From caf4fd41b044a6a48fac53e7796c7dd710eb2e48 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 9 Nov 2022 17:32:12 +0100 Subject: [PATCH 50/59] Implement TF interface for white color keyboards --- src/uniwill_leds.h | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index 83b1f5c..aafdb66 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -32,8 +32,11 @@ enum uniwill_kb_backlight_types { UNIWILL_KB_BACKLIGHT_TYPE_PER_KEY_RGB }; -#define UNIWILL_KBD_BRIGHTNESS_MAX 0xff -#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) +#define UNIWILL_KBD_BRIGHTNESS_MAX 0xff +#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) + +#define UNIWILL_KBD_BRIGHTNESS_WHITE_MAX 0x2 +#define UNIWILL_KBD_BRIGHTNESS_WHITE_DEFAULT (UNIWILL_KBD_BRIGHTNESS_WHITE_MAX * 0.5) #define UNIWILL_KB_COLOR_DEFAULT_RED 0xff #define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff @@ -61,8 +64,13 @@ static bool uw_leds_initialized = false; static int uniwill_write_kbd_bl_white(u8 brightness) { + u8 data; - return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS, brightness); + uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); + msleep(100); + data |= UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET; + data |= brightness << 5; + return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, data); } static int uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) @@ -114,9 +122,9 @@ static void uniwill_leds_set_brightness_mc(struct led_classdev *led_cdev, enum l static struct led_classdev uniwill_led_cdev = { .name = "white:" LED_FUNCTION_KBD_BACKLIGHT, - .max_brightness = UNIWILL_KBD_BRIGHTNESS_MAX, + .max_brightness = UNIWILL_KBD_BRIGHTNESS_WHITE_MAX, .brightness_set = &uniwill_leds_set_brightness, - .brightness = UNIWILL_KBD_BRIGHTNESS_DEFAULT + .brightness = UNIWILL_KBD_BRIGHTNESS_WHITE_DEFAULT }; static struct mc_subled uw_mcled_cdev_subleds[3] = { @@ -262,8 +270,14 @@ enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type() { EXPORT_SYMBOL(uniwill_leds_get_backlight_type); void uniwill_leds_restore_state_extern(void) { + u8 data; + if (uw_leds_initialized) { - uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET); + // FIXME Not required if white backlight: set brightness does this anyway + uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); + msleep(100); + data |= UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET; + uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, data); msleep(100); // Make sure reset finish before continue if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { From e8bb59c9ff714eb8bcec9718687a62bc5785d30e Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 9 Nov 2022 17:50:19 +0100 Subject: [PATCH 51/59] Fixed missing semicolon --- src/tuxedo_io/tuxedo_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 30e5ff5..4444bc6 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -801,7 +801,7 @@ static int __init tuxedo_io_init(void) id_check_uniwill = uniwill_identify(); #ifdef DEBUG - pr_debug("DEBUG is defined\n") + pr_debug("DEBUG is defined\n"); if (id_check_clevo == 0 && id_check_uniwill == 0) { pr_debug("No matching hardware found on module load\n"); From 6eb394bcc2f228df2fd29f47f5b3589544b33d65 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 11 Nov 2022 18:55:41 +0100 Subject: [PATCH 52/59] Use TF provided steps for white only keyboard --- src/uniwill_leds.h | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index aafdb66..b315797 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -66,8 +66,19 @@ static int uniwill_write_kbd_bl_white(u8 brightness) { u8 data; + uniwill_read_ec_ram(UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS, &data); + // When keyboard backlight is off, new settings to 0x078c do not get applied automatically + // on Pulse Gen1/2 until next keypress or manual change to 0x1808 (immediate brightness + // value for some reason. + // Sidenote: IBP Gen6/7 has immediate brightness value on 0x1802 and not on 0x1808, but does + // not need this workaround. + if (!data) { + uniwill_write_ec_ram(UW_EC_REG_KBD_BL_RGB_BLUE_BRIGHTNESS, 0x01); + } + + data = 0; uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); - msleep(100); + data &= 0x0f; // lower bits must be preserved data |= UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET; data |= brightness << 5; return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, data); @@ -273,17 +284,16 @@ void uniwill_leds_restore_state_extern(void) { u8 data; if (uw_leds_initialized) { - // FIXME Not required if white backlight: set brightness does this anyway - uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); - msleep(100); - data |= UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET; - uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, data); - msleep(100); // Make sure reset finish before continue - if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { uniwill_led_cdev.brightness_set(&uniwill_led_cdev, uniwill_led_cdev.brightness); } else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { + // reset + uniwill_read_ec_ram(UW_EC_REG_KBD_BL_STATUS, &data); + data |= UW_EC_REG_KBD_BL_STATUS_SUBCMD_RESET; + uniwill_write_ec_ram(UW_EC_REG_KBD_BL_STATUS, data); + + // write uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, uniwill_mcled_cdev.led_cdev.brightness); } } From ddf41635da2687250aaf22732e66d5cac63b2ed7 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Mon, 14 Nov 2022 12:04:48 +0100 Subject: [PATCH 53/59] Change default brightness to 0 --- src/clevo_leds.h | 21 ++++++++++----------- src/uniwill_leds.h | 14 +++++++------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 14b5248..3391661 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -46,20 +46,19 @@ void clevo_leds_set_color_extern(u32 color); #include -#define CLEVO_KBD_BRIGHTNESS_MIN 0x00 -#define CLEVO_KBD_BRIGHTNESS_MAX 0xff -#define CLEVO_KBD_BRIGHTNESS_DEFAULT (CLEVO_KBD_BRIGHTNESS_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_MAX 0xff +#define CLEVO_KBD_BRIGHTNESS_DEFAULT 0x00 -#define CLEVO_KBD_BRIGHTNESS_WHITE_MIN 0x00 #define CLEVO_KBD_BRIGHTNESS_WHITE_MAX 0x02 // White only keyboards can only be off, half, or full brightness -#define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) -#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off -#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5_DEFAULT (CLEVO_KBD_BRIGHTNESS_WHITE_MAX * 0.5) +#define CLEVO_KBD_BRIGHTNESS_WHITE_DEFAULT 0x00 -#define CLEVO_KB_COLOR_DEFAULT_RED 0xff -#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff -#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff -#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5 0x05 // Devices <= Intel 7th gen had a different white control with 5 brightness values + off +#define CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5_DEFAULT 0x00 + +#define CLEVO_KB_COLOR_DEFAULT_RED 0xff +#define CLEVO_KB_COLOR_DEFAULT_GREEN 0xff +#define CLEVO_KB_COLOR_DEFAULT_BLUE 0xff +#define CLEVO_KB_COLOR_DEFAULT ((CLEVO_KB_COLOR_DEFAULT_RED << 16) + (CLEVO_KB_COLOR_DEFAULT_GREEN << 8) + CLEVO_KB_COLOR_DEFAULT_BLUE) static enum clevo_kb_backlight_types clevo_kb_backlight_type = CLEVO_KB_BACKLIGHT_TYPE_NONE; static bool leds_initialized = false; diff --git a/src/uniwill_leds.h b/src/uniwill_leds.h index b315797..63639fa 100644 --- a/src/uniwill_leds.h +++ b/src/uniwill_leds.h @@ -33,15 +33,15 @@ enum uniwill_kb_backlight_types { }; #define UNIWILL_KBD_BRIGHTNESS_MAX 0xff -#define UNIWILL_KBD_BRIGHTNESS_DEFAULT (UNIWILL_KBD_BRIGHTNESS_MAX * 0.5) +#define UNIWILL_KBD_BRIGHTNESS_DEFAULT 0x00 -#define UNIWILL_KBD_BRIGHTNESS_WHITE_MAX 0x2 -#define UNIWILL_KBD_BRIGHTNESS_WHITE_DEFAULT (UNIWILL_KBD_BRIGHTNESS_WHITE_MAX * 0.5) +#define UNIWILL_KBD_BRIGHTNESS_WHITE_MAX 0x02 +#define UNIWILL_KBD_BRIGHTNESS_WHITE_DEFAULT 0x00 -#define UNIWILL_KB_COLOR_DEFAULT_RED 0xff -#define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff -#define UNIWILL_KB_COLOR_DEFAULT_BLUE 0xff -#define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) +#define UNIWILL_KB_COLOR_DEFAULT_RED 0xff +#define UNIWILL_KB_COLOR_DEFAULT_GREEN 0xff +#define UNIWILL_KB_COLOR_DEFAULT_BLUE 0xff +#define UNIWILL_KB_COLOR_DEFAULT ((UNIWILL_KB_COLOR_DEFAULT_RED << 16) + (UNIWILL_KB_COLOR_DEFAULT_GREEN << 8) + UNIWILL_KB_COLOR_DEFAULT_BLUE) int uniwill_leds_init_early(struct platform_device *dev); int uniwill_leds_init_late(struct platform_device *dev); From b751619983664e2a5ba00d83c6268ed47c614f36 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 19 Jan 2023 20:25:20 +0100 Subject: [PATCH 54/59] Remove merge error --- src/uniwill_keyboard.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index c004ea3..9a3ce9f 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -982,10 +982,6 @@ static int uniwill_keyboard_remove(struct platform_device *dev) if (uw_charging_profile_loaded) sysfs_remove_group(&dev->dev.kobj, &uw_charging_profile_attr_group); - if (uniwill_kbd_bl_type_rgb_single_color) { - sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); - } - uniwill_leds_remove(dev); // Restore previous backlight enable state From 700807df808b0767c5839337bc58fe8d715fef6f Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Thu, 19 Jan 2023 20:49:30 +0100 Subject: [PATCH 55/59] Use new keyboard type check instead of dummy value --- src/uniwill_keyboard.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 9a3ce9f..02f8783 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -55,7 +55,6 @@ struct tuxedo_keyboard_driver uniwill_keyboard_driver; struct uniwill_device_features_t uniwill_device_features; static u8 uniwill_kbd_bl_enable_state_on_start; -static bool uniwill_kbd_bl_type_rgb_single_color = true; static struct key_entry uniwill_wmi_keymap[] = { // { KE_KEY, UNIWILL_OSD_RADIOON, { KEY_RFKILL } }, @@ -363,7 +362,7 @@ static int uw_kbd_bl_init(struct platform_device *dev) uniwill_leds_init_early(dev); - if (uniwill_kbd_bl_type_rgb_single_color) { + if (uniwill_leds_get_backlight_type() == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { // Start periodic checking of animation, set and enable bl when done uw_kbd_bl_init_ready_check_work_func_args_dev = dev; timer_setup(&uw_kbd_bl_init_timer, uw_kbd_bl_init_ready_check, 0); From f880587a0388c49a8e00a574f1cba273a51a1a47 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 25 Jan 2023 14:28:33 +0100 Subject: [PATCH 56/59] Fix comented function --- src/clevo_leds.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 3391661..32e41ca 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -101,9 +101,9 @@ static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unu u32 zone, color; struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev); - ret = clevo_evaluate_set_brightness(CLEVO_KBD_BRIGHTNESS_MAX); + ret = clevo_evaluate_set_rgb_brightness(CLEVO_KBD_BRIGHTNESS_MAX); if (ret) { - pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_brightness() failed\n"); + pr_debug("clevo_leds_set_brightness_mc(): clevo_evaluate_set_rgb_brightness() failed\n"); return; } From 4324bb204254a46bf1048c2030aedc5ece13d70b Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 25 Jan 2023 14:29:47 +0100 Subject: [PATCH 57/59] Simplyfy init function --- src/clevo_leds.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index 32e41ca..ee56234 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -259,7 +259,6 @@ int clevo_leds_init(struct platform_device *dev) u32 status; union acpi_object *result; u32 result_fallback; - u8 default_brightness = CLEVO_KBD_BRIGHTNESS_DEFAULT; status = clevo_evaluate_method2(CLEVO_CMD_GET_SPECS, 0, &result); if (!status) { @@ -275,8 +274,7 @@ int clevo_leds_init(struct platform_device *dev) } else { pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES_1\n"); - } - if (status) { + // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES_1, 0, &result_fallback); if (!status) { @@ -292,6 +290,7 @@ int clevo_leds_init(struct platform_device *dev) pr_debug("CLEVO_CMD_GET_BIOS_FEATURES_2 result_fallback: 0x%08x\n", result_fallback); if (result_fallback & CLEVO_CMD_GET_BIOS_FEATURES_2_SUB_WHITE_ONLY_KB_MAX_5) { clevo_led_cdev.max_brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5; + clevo_led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5_DEFAULT; } } else { @@ -305,12 +304,10 @@ int clevo_leds_init(struct platform_device *dev) } pr_debug("Keyboard backlight type: 0x%02x\n", clevo_kb_backlight_type); - if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { - default_brightness = clevo_led_cdev.max_brightness / 2; - } - - clevo_leds_set_brightness_extern(default_brightness); - clevo_leds_set_color_extern(CLEVO_KB_COLOR_DEFAULT); + if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) + clevo_leds_set_brightness_extern(clevo_led_cdev.brightness); + else + clevo_leds_set_color_extern(CLEVO_KB_COLOR_DEFAULT); if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { pr_debug("Registering fixed color leds interface\n"); From 8fc1f5a34550467fd4cc639d087e627c690c8565 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 25 Jan 2023 14:36:37 +0100 Subject: [PATCH 58/59] Fix case where WMI 13 is presend, but backlight identification is still happening the old way --- src/clevo_leds.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/clevo_leds.h b/src/clevo_leds.h index ee56234..18f2ab7 100644 --- a/src/clevo_leds.h +++ b/src/clevo_leds.h @@ -274,8 +274,10 @@ int clevo_leds_init(struct platform_device *dev) } else { pr_notice("CLEVO_CMD_GET_SPECS does not exist on this device or failed, trying CLEVO_CMD_GET_BIOS_FEATURES_1\n"); + } - // check for devices <= Intel 7th gen (only white only, 3 zone RGB, or no backlight on these devices) + if (status || clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_NONE) { + // check for devices <= Intel 8th gen (only white only, 3 zone RGB, or no backlight on these devices) status = clevo_evaluate_method(CLEVO_CMD_GET_BIOS_FEATURES_1, 0, &result_fallback); if (!status) { pr_debug("CLEVO_CMD_GET_BIOS_FEATURES_1 result_fallback: 0x%08x\n", result_fallback); From 60414b1c79e95c707024f16d871863484d9a3ab7 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 23 Feb 2023 10:01:33 +0100 Subject: [PATCH 59/59] Increase minor module versions according to changes --- src/clevo_acpi.c | 2 +- src/clevo_wmi.c | 2 +- src/tuxedo_io/tuxedo_io.c | 2 +- src/uniwill_wmi.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index aff7a49..e1abd8f 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -203,7 +203,7 @@ module_acpi_driver(clevo_acpi_driver); MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Clevo ACPI interface"); -MODULE_VERSION("0.0.3"); +MODULE_VERSION("0.1.0"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(acpi, clevo_acpi_device_ids); diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 22623a6..f7e0186 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -166,7 +166,7 @@ module_wmi_driver(clevo_wmi_driver); MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Clevo WMI interface"); -MODULE_VERSION("0.0.4"); +MODULE_VERSION("0.1.0"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(wmi, clevo_wmi_device_ids); diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index bba0df5..1121ebd 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -34,7 +34,7 @@ MODULE_DESCRIPTION("Hardware interface for TUXEDO laptops"); MODULE_AUTHOR("TUXEDO Computers GmbH "); -MODULE_VERSION("0.3.2"); +MODULE_VERSION("0.3.3"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CLEVO_INTERFACES(); diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index fc4d432..e75b7cd 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -371,7 +371,7 @@ module_wmi_driver(uniwill_wmi_driver); MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Uniwill WMI interface"); -MODULE_VERSION("0.0.2"); +MODULE_VERSION("0.0.3"); MODULE_LICENSE("GPL"); /*