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