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);