Fix resume behavior

This commit is contained in:
Werner Sembach 2022-09-23 15:47:42 +02:00
parent a0c9995518
commit b73152ba8b
3 changed files with 61 additions and 24 deletions

View file

@ -39,6 +39,9 @@ typedef int (uniwill_read_ec_ram_t)(u16, u8*);
typedef int (uniwill_write_ec_ram_t)(u16, u8); typedef int (uniwill_write_ec_ram_t)(u16, u8);
typedef void (uniwill_event_callb_t)(u32); 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_MAX_BRIGHTNESS 0x1801
#define UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS 0x1802 #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_RED_BRIGHTNESS 0x1803

View file

@ -41,6 +41,7 @@
#define UNIWILL_OSD_KB_LED_LEVEL3 0x03E #define UNIWILL_OSD_KB_LED_LEVEL3 0x03E
#define UNIWILL_OSD_KB_LED_LEVEL4 0x03F #define UNIWILL_OSD_KB_LED_LEVEL4 0x03F
#define UNIWILL_OSD_DC_ADAPTER_CHANGE 0x0AB #define UNIWILL_OSD_DC_ADAPTER_CHANGE 0x0AB
#define UNIWILL_OSD_MODE_CHANGE_KEY_EVENT 0x0B0
#define UNIWILL_KEY_RFKILL 0x0A4 #define UNIWILL_KEY_RFKILL 0x0A4
#define UNIWILL_KEY_KBDILLUMDOWN 0x0B1 #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_KBDILLUMDOWN, { KEY_KBDILLUMDOWN } },
{ KE_KEY, UNIWILL_KEY_KBDILLUMUP, { KEY_KBDILLUMUP } }, { KE_KEY, UNIWILL_KEY_KBDILLUMUP, { KEY_KBDILLUMUP } },
{ KE_KEY, UNIWILL_KEY_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE } }, { 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 // Only used to put ev bits
{ KE_KEY, 0xffff, { KEY_F6 } }, { KE_KEY, 0xffff, { KEY_F6 } },
{ KE_KEY, 0xffff, { KEY_LEFTALT } }, { KE_KEY, 0xffff, { KEY_LEFTALT } },
@ -214,10 +220,10 @@ static void uniwill_write_kbd_bl_enable(u8 enable)
u8 backlight_data; u8 backlight_data;
enable = enable & 0x01; 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 = backlight_data & ~(1 << 1);
backlight_data |= (!enable << 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) 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 // 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_LEFTMETA, 1);
input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTALT, 1); input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTALT, 1);
input_report_key(uniwill_keyboard_driver.input_device, KEY_F6, 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_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 0);
input_sync(uniwill_keyboard_driver.input_device); 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); 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; 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) static void uw_kbd_bl_init_ready_check_work_func(struct work_struct *work)
{ {
u8 uw_cur_red, uw_cur_green, uw_cur_blue; 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) { 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); del_timer(&uw_kbd_bl_init_timer);
} else { } else {
if (uw_kbd_bl_check_count != 0) { 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) { if (uniwill_kbd_bl_type_rgb_single_color) {
// Start periodic checking of animation, set and enable bl when done // 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); 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)); mod_timer(&uw_kbd_bl_init_timer, jiffies + msecs_to_jiffies(uw_kbd_bl_init_check_interval_ms));
} else { } 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) static int uniwill_keyboard_resume(struct platform_device *dev)
{ {
uniwill_leds_restore_state_extern();
uniwill_write_kbd_bl_enable(1); uniwill_write_kbd_bl_enable(1);
return 0; return 0;
} }

View file

@ -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) #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_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); int uniwill_leds_remove(struct platform_device *dev);
enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type(void); 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_brightness_extern(enum led_brightness brightness);
void uniwill_leds_set_color_extern(u32 color); 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; uw_leds_initialized = true;
return 0; return 0;
} }
EXPORT_SYMBOL(uniwill_leds_init_early); EXPORT_SYMBOL(uniwill_leds_init_early);
int uniwill_leds_init_late() int uniwill_leds_init_late(struct platform_device *dev)
{ {
int ret; int ret;
ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xff); ret = uniwill_write_ec_ram(UW_EC_REG_KBD_BL_MAX_BRIGHTNESS, 0xff);
if (ret) { if (ret) {
pr_err("Setting max keyboard brightness value failed\n"); pr_err("Setting max keyboard brightness value failed\n");
uniwill_leds_remove(dev);
return ret; return ret;
} }
uniwill_leds_set_brightness_extern(UNIWILL_KBD_BRIGHTNESS_DEFAULT); uniwill_leds_restore_state_extern();
uniwill_leds_set_color_extern(UNIWILL_KB_COLOR_DEFAULT);
//complete_all(&init_done);
return 0; return 0;
} }
EXPORT_SYMBOL(uniwill_leds_init_late); EXPORT_SYMBOL(uniwill_leds_init_late);
int uniwill_leds_remove(struct platform_device *dev) { int uniwill_leds_remove(struct platform_device *dev) {
// FIXME Race condition?
if (uw_leds_initialized) { if (uw_leds_initialized) {
uw_leds_initialized = false;
if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) { if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) {
led_classdev_unregister(&uniwill_led_cdev); led_classdev_unregister(&uniwill_led_cdev);
} }
@ -226,8 +228,6 @@ int uniwill_leds_remove(struct platform_device *dev) {
} }
} }
uw_leds_initialized = false;
return 0; return 0;
} }
EXPORT_SYMBOL(uniwill_leds_remove); EXPORT_SYMBOL(uniwill_leds_remove);
@ -237,23 +237,42 @@ enum uniwill_kb_backlight_types uniwill_leds_get_backlight_type() {
} }
EXPORT_SYMBOL(uniwill_leds_get_backlight_type); EXPORT_SYMBOL(uniwill_leds_get_backlight_type);
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);
}
}
}
EXPORT_SYMBOL(uniwill_leds_restore_state_extern);
void uniwill_leds_set_brightness_extern(enum led_brightness brightness) { 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) { if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR) {
uniwill_led_cdev.brightness_set(&uniwill_led_cdev, brightness); uniwill_led_cdev.brightness_set(&uniwill_led_cdev, brightness);
} }
else if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { 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); uniwill_mcled_cdev.led_cdev.brightness_set(&uniwill_mcled_cdev.led_cdev, brightness);
} }
}
} }
EXPORT_SYMBOL(uniwill_leds_set_brightness_extern); EXPORT_SYMBOL(uniwill_leds_set_brightness_extern);
void uniwill_leds_set_color_extern(u32 color) { void uniwill_leds_set_color_extern(u32 color) {
if (uw_leds_initialized) {
if (uniwill_kb_backlight_type == UNIWILL_KB_BACKLIGHT_TYPE_1_ZONE_RGB) { 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[0].intensity = (color >> 16) & 0xff;
uniwill_mcled_cdev.subled_info[1].intensity = (color >> 8) & 0xff; uniwill_mcled_cdev.subled_info[1].intensity = (color >> 8) & 0xff;
uniwill_mcled_cdev.subled_info[2].intensity = color & 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); 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); EXPORT_SYMBOL(uniwill_leds_set_color_extern);