Skip to content

Commit

Permalink
platform/x86: asus-wmi: Implement TUF laptop keyboard LED modes
Browse files Browse the repository at this point in the history
Adds support for changing the laptop keyboard LED mode and colour.

The modes are visible effects such as static, rainbow, pulsing,
colour cycles.

These sysfs attributes are added to asus::kbd_backlight:
- kbd_rgb_mode
- kbd_rgb_mode_index

Signed-off-by: Luke D. Jones <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Hans de Goede <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
  • Loading branch information
flukejones authored and jwrdegoede committed Aug 26, 2022
1 parent 12ff4c8 commit e305a71
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
74 changes: 73 additions & 1 deletion drivers/platform/x86/asus-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ struct asus_wmi {
bool dgpu_disable_available;
bool gpu_mux_mode_available;

bool kbd_rgb_mode_available;

bool throttle_thermal_policy_available;
u8 throttle_thermal_policy_mode;

Expand Down Expand Up @@ -722,6 +724,69 @@ static ssize_t gpu_mux_mode_store(struct device *dev,
}
static DEVICE_ATTR_RW(gpu_mux_mode);

/* TUF Laptop Keyboard RGB Modes **********************************************/
static ssize_t kbd_rgb_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
u32 cmd, mode, r, g, b, speed;
int err;

if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
return -EINVAL;

cmd = !!cmd;

/* These are the known usable modes across all TUF/ROG */
if (mode >= 12 || mode == 9)
mode = 10;

switch (speed) {
case 0:
speed = 0xe1;
break;
case 1:
speed = 0xeb;
break;
case 2:
speed = 0xf5;
break;
default:
speed = 0xeb;
}

err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, ASUS_WMI_DEVID_TUF_RGB_MODE,
cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL);
if (err)
return err;

return count;
}
static DEVICE_ATTR_WO(kbd_rgb_mode);

static ssize_t kbd_rgb_mode_index_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
return sysfs_emit(buf, "%s\n", "cmd mode red green blue speed");
}
static DEVICE_ATTR_RO(kbd_rgb_mode_index);

static struct attribute *kbd_rgb_mode_attrs[] = {
&dev_attr_kbd_rgb_mode.attr,
&dev_attr_kbd_rgb_mode_index.attr,
NULL,
};

static const struct attribute_group kbd_rgb_mode_group = {
.attrs = kbd_rgb_mode_attrs,
};

const struct attribute_group *kbd_rgb_mode_groups[] = {
NULL,
NULL,
};

/* Battery ********************************************************************/

/* The battery maximum charging percentage */
Expand Down Expand Up @@ -1040,7 +1105,10 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)

static int asus_wmi_led_init(struct asus_wmi *asus)
{
int rv = 0, led_val;
int rv = 0, num_rgb_groups = 0, led_val;

if (asus->kbd_rgb_mode_available)
kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group;

asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
if (!asus->led_workqueue)
Expand Down Expand Up @@ -1068,6 +1136,9 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
asus->kbd_led.brightness_get = kbd_led_get;
asus->kbd_led.max_brightness = 3;

if (num_rgb_groups != 0)
asus->kbd_led.groups = kbd_rgb_mode_groups;

rv = led_classdev_register(&asus->platform_device->dev,
&asus->kbd_led);
if (rv)
Expand Down Expand Up @@ -3589,6 +3660,7 @@ static int asus_wmi_add(struct platform_device *pdev)
asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX);
asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE);
asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD);

err = fan_boost_mode_check_present(asus);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/platform_data/x86/asus-wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@
/* gpu mux switch, 0 = dGPU, 1 = Optimus */
#define ASUS_WMI_DEVID_GPU_MUX 0x00090016

/* TUF laptop RGB modes/colours */
#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056

/* DSTS masks */
#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
Expand Down

0 comments on commit e305a71

Please sign in to comment.