mirror of
https://github.com/wessel-novacustom/clevo-keyboard.git
synced 2024-11-15 03:34:01 +01:00
First working but buggy implementation of leds interface for TongFang/Uniwill
This commit is contained in:
parent
f2c442bc2a
commit
a0c9995518
|
@ -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
|
#endif
|
||||||
|
|
|
@ -35,10 +35,16 @@
|
||||||
|
|
||||||
#define UNIWILL_INTERFACE_WMI_STRID "uniwill_wmi"
|
#define UNIWILL_INTERFACE_WMI_STRID "uniwill_wmi"
|
||||||
|
|
||||||
typedef u32 (uniwill_read_ec_ram_t)(u16, u8*);
|
typedef int (uniwill_read_ec_ram_t)(u16, u8*);
|
||||||
typedef u32 (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_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 {
|
struct uniwill_interface_t {
|
||||||
char *string_id;
|
char *string_id;
|
||||||
uniwill_event_callb_t *event_callb;
|
uniwill_event_callb_t *event_callb;
|
||||||
|
@ -46,11 +52,11 @@ struct uniwill_interface_t {
|
||||||
uniwill_write_ec_ram_t *write_ec_ram;
|
uniwill_write_ec_ram_t *write_ec_ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 uniwill_add_interface(struct uniwill_interface_t *new_interface);
|
int uniwill_add_interface(struct uniwill_interface_t *new_interface);
|
||||||
u32 uniwill_remove_interface(struct uniwill_interface_t *interface);
|
int uniwill_remove_interface(struct uniwill_interface_t *interface);
|
||||||
uniwill_read_ec_ram_t uniwill_read_ec_ram;
|
uniwill_read_ec_ram_t uniwill_read_ec_ram;
|
||||||
uniwill_write_ec_ram_t uniwill_write_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 {
|
union uw_ec_read_return {
|
||||||
u32 dword;
|
u32 dword;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include "uniwill_interfaces.h"
|
#include "uniwill_interfaces.h"
|
||||||
|
#include "uniwill_leds.h"
|
||||||
|
|
||||||
#define UNIWILL_OSD_RADIOON 0x01A
|
#define UNIWILL_OSD_RADIOON 0x01A
|
||||||
#define UNIWILL_OSD_RADIOOFF 0x01B
|
#define UNIWILL_OSD_RADIOOFF 0x01B
|
||||||
|
@ -77,9 +78,9 @@ static struct uniwill_interfaces_t {
|
||||||
|
|
||||||
uniwill_event_callb_t uniwill_event_callb;
|
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))
|
if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi))
|
||||||
status = uniwill_interfaces.wmi->read_ec_ram(address, data);
|
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);
|
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))
|
if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi))
|
||||||
status = uniwill_interfaces.wmi->write_ec_ram(address, data);
|
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);
|
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);
|
mutex_lock(&uniwill_interface_modification_lock);
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ u32 uniwill_add_interface(struct uniwill_interface_t *interface)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(uniwill_add_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);
|
mutex_lock(&uniwill_interface_modification_lock);
|
||||||
|
|
||||||
|
@ -151,7 +152,7 @@ u32 uniwill_remove_interface(struct uniwill_interface_t *interface)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(uniwill_remove_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))
|
if (IS_ERR_OR_NULL(uniwill_interfaces.wmi))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -208,18 +209,6 @@ static struct notifier_block keyboard_notifier_block = {
|
||||||
.notifier_call = keyboard_notifier_callb
|
.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)
|
static void uniwill_write_kbd_bl_enable(u8 enable)
|
||||||
{
|
{
|
||||||
u8 backlight_data;
|
u8 backlight_data;
|
||||||
|
@ -231,11 +220,6 @@ static void uniwill_write_kbd_bl_enable(u8 enable)
|
||||||
uniwill_write_ec_ram(0x078c, backlight_data);
|
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)
|
void uniwill_event_callb(u32 code)
|
||||||
{
|
{
|
||||||
if (uniwill_keyboard_driver.input_device != NULL)
|
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_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 0);
|
||||||
input_sync(uniwill_keyboard_driver.input_device);
|
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)
|
static void uw_kbd_bl_init_set(void)
|
||||||
{
|
{
|
||||||
if (uniwill_kbd_bl_type_rgb_single_color) {
|
uniwill_leds_init_late();
|
||||||
// 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_write_kbd_bl_enable(1);
|
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 volatile int uw_kbd_bl_check_count = 40;
|
||||||
static int uw_kbd_bl_init_check_interval_ms = 500;
|
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)
|
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;
|
||||||
|
@ -446,56 +316,16 @@ static int uw_kbd_bl_init(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
int status = 0;
|
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)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
|
||||||
TUXEDO_ERROR(
|
TUXEDO_ERROR("Warning: Kernel version less that 4.18, keyboard backlight might not be properly recognized.");
|
||||||
"Warning: Kernel version less that 4.18, keyboard backlight might not be properly recognized.");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Save previous enable state
|
uniwill_leds_init_early(dev);
|
||||||
uniwill_kbd_bl_enable_state_on_start = uniwill_read_kbd_bl_enabled();
|
|
||||||
|
|
||||||
if (uniwill_kbd_bl_type_rgb_single_color) {
|
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
|
// 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);
|
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));
|
||||||
|
|
||||||
// Register leds sysfs interface
|
|
||||||
devm_led_classdev_multicolor_register(&dev->dev, &cdev_kb_uw_mc);
|
|
||||||
} else {
|
} else {
|
||||||
// For non-RGB versions
|
// For non-RGB versions
|
||||||
// Enable keyboard backlight immediately (should it be disabled)
|
// 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)
|
static int uniwill_keyboard_remove(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
|
uniwill_leds_remove(dev);
|
||||||
if (uniwill_kbd_bl_type_rgb_single_color) {
|
|
||||||
sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore previous backlight enable state
|
// Restore previous backlight enable state
|
||||||
if (uniwill_kbd_bl_enable_state_on_start != 0xff) {
|
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)
|
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);
|
uniwill_write_kbd_bl_enable(1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,8 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/leds.h>
|
||||||
#define UNIWILL_KBD_BRIGHTNESS_MIN 0x00
|
#include <linux/completion.h>
|
||||||
#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 {
|
enum uniwill_kb_backlight_types {
|
||||||
UNIWILL_KB_BACKLIGHT_TYPE_NONE,
|
UNIWILL_KB_BACKLIGHT_TYPE_NONE,
|
||||||
|
@ -42,49 +32,97 @@ enum uniwill_kb_backlight_types {
|
||||||
UNIWILL_KB_BACKLIGHT_TYPE_PER_KEY_RGB
|
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);
|
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_set_brightness_extern(u32 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);
|
||||||
|
|
||||||
// TODO The following should go into a seperate .c file, but for this to work more reworking is required in the tuxedo_keyboard structure.
|
// 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 <linux/leds.h>
|
|
||||||
#include <linux/led-class-multicolor.h>
|
#include <linux/led-class-multicolor.h>
|
||||||
|
|
||||||
#define FF_TO_UW_RANGE(x) (x * 0xc8 / 0xff)
|
static enum uniwill_kb_backlight_types uniwill_kb_backlight_type = UNIWILL_KB_BACKLIGHT_TYPE_FIXED_COLOR;
|
||||||
#define UW_TO_FF_RANGE(x) (x * 0xff / 0xc8)
|
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);
|
return uniwill_write_ec_ram(UW_EC_REG_KBD_BL_WHITE_BRIGHTNESS, brightness);
|
||||||
uniwill_read_ec_ram(0x1805, green);
|
}
|
||||||
uniwill_read_ec_ram(0x1808, blue);
|
|
||||||
|
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 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 (red > 0xc8) red = 0xc8;
|
if (ret) {
|
||||||
if (green > 0xc8) green = 0xc8;
|
pr_debug("uniwill_leds_set_brightness(): uniwill_write_kbd_bl_white() failed\n");
|
||||||
if (blue > 0xc8) blue = 0xc8;
|
return;
|
||||||
uniwill_write_ec_ram(0x1803, red);
|
}
|
||||||
uniwill_write_ec_ram(0x1805, green);
|
led_cdev->brightness = brightness;
|
||||||
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] = {
|
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,
|
.color_index = LED_COLOR_ID_RED,
|
||||||
.brightness = UNIWILL_KBD_BRIGHTNESS_MAX,
|
.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 = {
|
static struct led_classdev_mc uniwill_mcled_cdev = {
|
||||||
.led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT,
|
.led_cdev.name = "rgb:" LED_FUNCTION_KBD_BACKLIGHT,
|
||||||
.led_cdev.max_brightness = UNIWILL_KBD_BRIGHTNESS_MAX,
|
.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,
|
.led_cdev.brightness = UNIWILL_KBD_BRIGHTNESS_DEFAULT,
|
||||||
.num_colors = 3,
|
.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
|
#endif // UNIWILL_LEDS_H
|
||||||
|
|
Loading…
Reference in a new issue