Merge branch '84-ibsgen8-keyboard-backlight-driver' into 'master'

Resolve "IBSGen8: Keyboard backlight driver"

Closes #84

See merge request tuxedocomputers/development/packages/tuxedo-keyboard!61
This commit is contained in:
Christoffer 2023-07-21 14:54:16 +00:00
commit 02ab51e004
2 changed files with 84 additions and 20 deletions

View file

@ -30,6 +30,10 @@
#define CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS 0x8A #define CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS 0x8A
#define CLEVO_EVENT_KB_LEDS_TOGGLE 0x9F #define CLEVO_EVENT_KB_LEDS_TOGGLE 0x9F
#define CLEVO_EVENT_KB_LEDS_DECREASE2 0x20
#define CLEVO_EVENT_KB_LEDS_INCREASE2 0x21
#define CLEVO_EVENT_KB_LEDS_TOGGLE2 0x3f
#define CLEVO_EVENT_TOUCHPAD_TOGGLE 0x5D #define CLEVO_EVENT_TOUCHPAD_TOGGLE 0x5D
#define CLEVO_EVENT_TOUCHPAD_OFF 0xFC #define CLEVO_EVENT_TOUCHPAD_OFF 0xFC
#define CLEVO_EVENT_TOUCHPAD_ON 0xFD #define CLEVO_EVENT_TOUCHPAD_ON 0xFD
@ -46,6 +50,8 @@ static struct clevo_interfaces_t {
static struct clevo_interface_t *active_clevo_interface; static struct clevo_interface_t *active_clevo_interface;
static struct tuxedo_keyboard_driver clevo_keyboard_driver;
static DEFINE_MUTEX(clevo_keyboard_interface_modification_lock); static DEFINE_MUTEX(clevo_keyboard_interface_modification_lock);
static struct key_entry clevo_keymap[] = { static struct key_entry clevo_keymap[] = {
@ -57,6 +63,11 @@ static struct key_entry clevo_keymap[] = {
// Single cycle key (white only versions) (currently handled in driver) // Single cycle key (white only versions) (currently handled in driver)
// { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS, { KEY_KBDILLUMTOGGLE } }, // { KE_KEY, CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS, { KEY_KBDILLUMTOGGLE } },
// Alternative events (ex. 6 step white kbd)
{ KE_KEY, CLEVO_EVENT_KB_LEDS_DECREASE2, { KEY_KBDILLUMDOWN } },
{ KE_KEY, CLEVO_EVENT_KB_LEDS_INCREASE2, { KEY_KBDILLUMUP } },
{ KE_KEY, CLEVO_EVENT_KB_LEDS_TOGGLE2, { KEY_KBDILLUMTOGGLE } },
// Touchpad // Touchpad
// The weirdly named touchpad toggle key that is implemented as KEY_F21 "everywhere" // The weirdly named touchpad toggle key that is implemented as KEY_F21 "everywhere"
// (instead of KEY_TOUCHPAD_TOGGLE or on/off) // (instead of KEY_TOUCHPAD_TOGGLE or on/off)
@ -77,6 +88,11 @@ static struct key_entry clevo_keymap[] = {
{ KE_IGNORE, 0xfa, { KEY_UNKNOWN } }, // Appears by volume up/down { KE_IGNORE, 0xfa, { KEY_UNKNOWN } }, // Appears by volume up/down
{ KE_IGNORE, 0xfb, { KEY_UNKNOWN } }, // Appears by mute toggle { KE_IGNORE, 0xfb, { KEY_UNKNOWN } }, // Appears by mute toggle
// Only used to put ev bits
{ KE_KEY, 0xffff, { KEY_F6 } },
{ KE_KEY, 0xffff, { KEY_LEFTALT } },
{ KE_KEY, 0xffff, { KEY_LEFTMETA } },
{ KE_END, 0 } { KE_END, 0 }
}; };
@ -152,20 +168,6 @@ int clevo_get_active_interface_id(char **id_str)
} }
EXPORT_SYMBOL(clevo_get_active_interface_id); EXPORT_SYMBOL(clevo_get_active_interface_id);
static int set_enabled_cmd(u8 state)
{
u32 cmd = 0xE0000000;
TUXEDO_INFO("Set keyboard enabled to: %d\n", state);
if (state == 0) {
cmd |= 0x003001;
} else {
cmd |= 0x07F001;
}
return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, cmd, NULL);
}
static void set_next_color_whole_kb(void) static void set_next_color_whole_kb(void)
{ {
/* "Calculate" new to-be color */ /* "Calculate" new to-be color */
@ -254,7 +256,19 @@ static void clevo_keyboard_event_callb(u32 event)
switch (key_event) { switch (key_event) {
case CLEVO_EVENT_KB_LEDS_CYCLE_MODE: case CLEVO_EVENT_KB_LEDS_CYCLE_MODE:
if (clevo_leds_get_backlight_type() == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) {
// Special key combination. Opens TCC by default when installed.
input_report_key(clevo_keyboard_driver.input_device, KEY_LEFTMETA, 1);
input_report_key(clevo_keyboard_driver.input_device, KEY_LEFTALT, 1);
input_report_key(clevo_keyboard_driver.input_device, KEY_F6, 1);
input_sync(clevo_keyboard_driver.input_device);
input_report_key(clevo_keyboard_driver.input_device, KEY_F6, 0);
input_report_key(clevo_keyboard_driver.input_device, KEY_LEFTALT, 0);
input_report_key(clevo_keyboard_driver.input_device, KEY_LEFTMETA, 0);
input_sync(clevo_keyboard_driver.input_device);
} else {
set_next_color_whole_kb(); set_next_color_whole_kb();
}
break; break;
case CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS: case CLEVO_EVENT_KB_LEDS_CYCLE_BRIGHTNESS:
clevo_leds_notify_brightness_change_extern(); clevo_leds_notify_brightness_change_extern();
@ -304,7 +318,6 @@ static void clevo_keyboard_init(void)
set_kbd_backlight_mode(kbd_led_state.mode); set_kbd_backlight_mode(kbd_led_state.mode);
clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL);
set_enabled_cmd(1);
// Workaround for firmware issue not setting selected performance profile. // Workaround for firmware issue not setting selected performance profile.
// Explicitly set "performance" perf. profile on init regardless of what is chosen // Explicitly set "performance" perf. profile on init regardless of what is chosen
@ -354,8 +367,7 @@ static int clevo_keyboard_remove(struct platform_device *dev)
static int clevo_keyboard_suspend(struct platform_device *dev, pm_message_t state) static int clevo_keyboard_suspend(struct platform_device *dev, pm_message_t state)
{ {
// turning the keyboard off prevents default colours showing on resume clevo_leds_suspend(dev);
set_enabled_cmd(0);
return 0; return 0;
} }
@ -364,7 +376,7 @@ static int clevo_keyboard_resume(struct platform_device *dev)
clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL); clevo_evaluate_method(CLEVO_CMD_SET_EVENTS_ENABLED, 0, NULL);
clevo_leds_restore_state_extern(); // Sometimes clevo devices forget their last state after clevo_leds_restore_state_extern(); // Sometimes clevo devices forget their last state after
// suspend, so let the kernel ensure it. // suspend, so let the kernel ensure it.
set_enabled_cmd(1); clevo_leds_resume(dev);
return 0; return 0;
} }

View file

@ -34,6 +34,8 @@ enum clevo_kb_backlight_types {
int clevo_leds_init(struct platform_device *dev); int clevo_leds_init(struct platform_device *dev);
int clevo_leds_remove(struct platform_device *dev); int clevo_leds_remove(struct platform_device *dev);
int clevo_leds_suspend(struct platform_device *dev);
int clevo_leds_resume(struct platform_device *dev);
enum clevo_kb_backlight_types clevo_leds_get_backlight_type(void); enum clevo_kb_backlight_types clevo_leds_get_backlight_type(void);
void clevo_leds_restore_state_extern(void); void clevo_leds_restore_state_extern(void);
void clevo_leds_notify_brightness_change_extern(void); void clevo_leds_notify_brightness_change_extern(void);
@ -101,6 +103,20 @@ static int clevo_evaluate_set_rgb_color(u32 zone, u32 color)
return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, clevo_submethod_arg, NULL); return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, clevo_submethod_arg, NULL);
} }
static int clevo_evaluate_set_keyboard_status(u8 state)
{
u32 cmd = 0xE0000000;
TUXEDO_INFO("Set keyboard enabled to: %d\n", state);
if (state == 0) {
cmd |= 0x003001;
} else {
cmd |= 0x07F001;
}
return clevo_evaluate_method(CLEVO_CMD_SET_KB_RGB_LEDS, cmd, NULL);
}
static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) { static void clevo_leds_set_brightness(struct led_classdev *led_cdev __always_unused, enum led_brightness brightness) {
int ret = clevo_evaluate_set_white_brightness(brightness); int ret = clevo_evaluate_set_white_brightness(brightness);
if (ret) { if (ret) {
@ -288,9 +304,17 @@ int clevo_leds_init(struct platform_device *dev)
if (result->type == ACPI_TYPE_BUFFER) { if (result->type == ACPI_TYPE_BUFFER) {
pr_debug("CLEVO_CMD_GET_SPECS result->buffer.pointer[0x0f]: 0x%02x\n", 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]; clevo_kb_backlight_type = result->buffer.pointer[0x0f];
if (clevo_kb_backlight_type) if (clevo_kb_backlight_type) {
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;
clevo_led_cdev.brightness = CLEVO_KBD_BRIGHTNESS_WHITE_MAX_5_DEFAULT;
}
}
break; break;
else { } else {
pr_debug("clevo_kb_backlight_type 0x00 probably wrong, retrying...\n"); pr_debug("clevo_kb_backlight_type 0x00 probably wrong, retrying...\n");
msleep(50); msleep(50);
} }
@ -350,6 +374,7 @@ int clevo_leds_init(struct platform_device *dev)
} }
} }
else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB) {
clevo_evaluate_set_keyboard_status(1);
pr_debug("Registering single zone rgb leds interface\n"); pr_debug("Registering single zone rgb leds interface\n");
ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]);
if (ret) { if (ret) {
@ -358,6 +383,7 @@ int clevo_leds_init(struct platform_device *dev)
} }
} }
else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) { else if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB) {
clevo_evaluate_set_keyboard_status(1);
pr_debug("Registering three zone rgb leds interface\n"); pr_debug("Registering three zone rgb leds interface\n");
ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]); ret = devm_led_classdev_multicolor_register(&dev->dev, &clevo_mcled_cdevs[0]);
if (ret) { if (ret) {
@ -384,6 +410,32 @@ int clevo_leds_init(struct platform_device *dev)
} }
EXPORT_SYMBOL(clevo_leds_init); EXPORT_SYMBOL(clevo_leds_init);
int clevo_leds_suspend(struct platform_device *dev)
{
switch (clevo_kb_backlight_type) {
case CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB:
case CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB:
clevo_evaluate_set_keyboard_status(0);
break;
default:
}
return 0;
}
EXPORT_SYMBOL(clevo_leds_suspend);
int clevo_leds_resume(struct platform_device *dev)
{
switch (clevo_kb_backlight_type) {
case CLEVO_KB_BACKLIGHT_TYPE_1_ZONE_RGB:
case CLEVO_KB_BACKLIGHT_TYPE_3_ZONE_RGB:
clevo_evaluate_set_keyboard_status(1);
break;
default:
}
return 0;
}
EXPORT_SYMBOL(clevo_leds_resume);
int clevo_leds_remove(struct platform_device *dev) { int clevo_leds_remove(struct platform_device *dev) {
if (leds_initialized) { if (leds_initialized) {
if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) { if (clevo_kb_backlight_type == CLEVO_KB_BACKLIGHT_TYPE_FIXED_COLOR) {