lkml.org 
[lkml]   [2022]   [Aug]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 2/6] asus-wmi: Implement TUF laptop keyboard LED modes
    Date
    Adds support for changing the laptop keyboard LED modes. These
    are visible effects such as static, rainbow, pulsing, colour cycles.

    These sysfs attributes are added to asus-nb-wmi:
    - keyboard_rgb_save
    - keyboard_rgb_mode
    - keyboard_rgb_speed

    Signed-off-by: Luke D. Jones <luke@ljones.dev>
    ---
    .../ABI/testing/sysfs-platform-asus-wmi | 30 +++++
    drivers/platform/x86/asus-wmi.c | 127 ++++++++++++++++--
    2 files changed, 149 insertions(+), 8 deletions(-)

    diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi
    index 04885738cf15..a9128fa5cc65 100644
    --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi
    +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi
    @@ -57,3 +57,33 @@ Description:
    * 0 - default,
    * 1 - overboost,
    * 2 - silent
    +
    +What: /sys/devices/platform/<platform>/keyboard_rgb_save
    +Date: Aug 2022
    +KernelVersion: 6.1
    +Contact: "Luke Jones" <luke@ljones.dev>
    +Description:
    + Set or save the RGB mode details (write-only):
    + * 0 - set, the settings will be lost on boot
    + * 1 - save, the settings will be retained on boot
    +
    +What: /sys/devices/platform/<platform>/keyboard_rgb_mode
    +Date: Aug 2022
    +KernelVersion: 6.1
    +Contact: "Luke Jones" <luke@ljones.dev>
    +Description:
    + Set the mode of the RGB keyboard, the mode will not apply until the
    + keyboard_rgb_save attribute is set (write-only):
    + * 0 to 12, each is an RGB such as static, rainbow, pulse.
    + Not all keyboards accept every mode.
    +
    +What: /sys/devices/platform/<platform>/keyboard_rgb_speed
    +Date: Aug 2022
    +KernelVersion: 6.1
    +Contact: "Luke Jones" <luke@ljones.dev>
    +Description:
    + Set the speed of the selected RGB effect, the speed will not apply
    + until the keyboard_rgb_save attribute is set (write-only):
    + * 0 - slow
    + * 1 - medium
    + * 2 - fast
    \ No newline at end of file
    diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
    index 233e73f4313d..fa0cc2895a66 100644
    --- a/drivers/platform/x86/asus-wmi.c
    +++ b/drivers/platform/x86/asus-wmi.c
    @@ -246,7 +246,8 @@ struct asus_wmi {
    bool dgpu_disable_available;
    bool dgpu_disable;

    - struct keyboard_rgb_led keyboard_rgb_mode;
    + bool keyboard_rgb_mode_available;
    + struct keyboard_rgb_led keyboard_rgb_led;

    bool throttle_thermal_policy_available;
    u8 throttle_thermal_policy_mode;
    @@ -748,6 +749,102 @@ static ssize_t egpu_enable_store(struct device *dev,

    static DEVICE_ATTR_RW(egpu_enable);

    +/* TUF Laptop Keyboard RGB Modes **********************************************/
    +static int keyboard_rgb_check_present(struct asus_wmi *asus)
    +{
    + u32 result;
    + int err;
    +
    + asus->keyboard_rgb_mode_available = false;
    +
    + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_TUF_RGB_MODE, &result);
    + if (err) {
    + if (err == -ENODEV)
    + return 0;
    + return err;
    + }
    +
    + if (result & ASUS_WMI_DSTS_PRESENCE_BIT)
    + asus->keyboard_rgb_mode_available = true;
    +
    + return 0;
    +}
    +
    +static ssize_t keyboard_rgb_save_store(struct device *device,
    + struct device_attribute *attr,
    + const char *buf, size_t count)
    +{
    + u8 save;
    + int err;
    +
    + struct asus_wmi *asus = dev_get_drvdata(device);
    + struct led_classdev *cdev = &asus->keyboard_rgb_led.dev.led_cdev;
    +
    + if (sscanf(buf, "%hhd", &save) != 1)
    + return -EINVAL;
    +
    + asus->keyboard_rgb_led.save = !!save;
    +
    + err = tuf_rgb_brightness_set(cdev, cdev->brightness);
    + if (err)
    + return err;
    +
    + return count;
    +}
    +static DEVICE_ATTR_WO(keyboard_rgb_save);
    +
    +static ssize_t keyboard_rgb_mode_store(struct device *device,
    + struct device_attribute *attr,
    + const char *buf, size_t count)
    +{
    + u8 mode;
    +
    + struct asus_wmi *asus = dev_get_drvdata(device);
    +
    + if (sscanf(buf, "%hhd", &mode) != 1)
    + return -EINVAL;
    +
    + /* These are the known usable modes across all TUF/ROG */
    + if (mode >= 12 || mode == 10)
    + asus->keyboard_rgb_led.mode = 10;
    + else
    + asus->keyboard_rgb_led.mode = mode;
    +
    + return count;
    +}
    +static DEVICE_ATTR_WO(keyboard_rgb_mode);
    +
    +
    +static ssize_t keyboard_rgb_speed_store(struct device *device,
    + struct device_attribute *attr,
    + const char *buf, size_t count)
    +{
    + u8 speed;
    +
    + struct asus_wmi *asus = dev_get_drvdata(device);
    +
    + if (sscanf(buf, "%hhd", &speed) != 1)
    + return -EINVAL;
    +
    + switch (speed) {
    + case 0:
    + asus->keyboard_rgb_led.speed = 0xe1;
    + break;
    + case 1:
    + asus->keyboard_rgb_led.speed = 0xeb;
    + break;
    + case 2:
    + asus->keyboard_rgb_led.speed = 0xf5;
    + break;
    + default:
    + asus->keyboard_rgb_led.speed = 0xeb;
    + break;
    + }
    +
    + return count;
    +}
    +static DEVICE_ATTR_WO(keyboard_rgb_speed);
    +
    /* Battery ********************************************************************/

    /* The battery maximum charging percentage */
    @@ -1047,7 +1144,7 @@ static int tuf_rgb_brightness_set(struct led_classdev *cdev,
    {
    struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
    struct keyboard_rgb_led *rgb = container_of(mc_cdev, struct keyboard_rgb_led, dev);
    - struct asus_wmi *asus = container_of(rgb, struct asus_wmi, keyboard_rgb_mode);
    + struct asus_wmi *asus = container_of(rgb, struct asus_wmi, keyboard_rgb_led);
    struct device *dev = &asus->platform_device->dev;
    u8 r, g, b;
    int err;
    @@ -1075,7 +1172,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
    led_classdev_unregister(&asus->tpd_led);
    led_classdev_unregister(&asus->wlan_led);
    led_classdev_unregister(&asus->lightbar_led);
    - led_classdev_multicolor_unregister(&asus->keyboard_rgb_mode.dev);
    + led_classdev_multicolor_unregister(&asus->keyboard_rgb_led.dev);

    if (asus->led_workqueue)
    destroy_workqueue(asus->led_workqueue);
    @@ -1148,8 +1245,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
    }

    if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE)) {
    - struct mc_subled *mc_led_info = asus->keyboard_rgb_mode.subled_info;
    - struct led_classdev_mc *mc_cdev = &asus->keyboard_rgb_mode.dev;
    + struct mc_subled *mc_led_info = asus->keyboard_rgb_led.subled_info;
    + struct led_classdev_mc *mc_cdev = &asus->keyboard_rgb_led.dev;
    struct device *dev = &asus->platform_device->dev;
    u8 led_brightness = 255;

    @@ -1174,9 +1271,9 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
    * It's not possible to get last set data from device so set defaults
    * to make it safe for a user to change either RGB or modes.
    */
    - asus->keyboard_rgb_mode.save = 1;
    - asus->keyboard_rgb_mode.mode = 0;
    - asus->keyboard_rgb_mode.speed = 0xeb;
    + asus->keyboard_rgb_led.save = 1;
    + asus->keyboard_rgb_led.mode = 0;
    + asus->keyboard_rgb_led.speed = 0xeb;

    mc_cdev->led_cdev.brightness = led_brightness;
    mc_cdev->led_cdev.max_brightness = led_brightness;
    @@ -3338,6 +3435,9 @@ static struct attribute *platform_attributes[] = {
    &dev_attr_touchpad.attr,
    &dev_attr_egpu_enable.attr,
    &dev_attr_dgpu_disable.attr,
    + &dev_attr_keyboard_rgb_save.attr,
    + &dev_attr_keyboard_rgb_mode.attr,
    + &dev_attr_keyboard_rgb_speed.attr,
    &dev_attr_lid_resume.attr,
    &dev_attr_als_enable.attr,
    &dev_attr_fan_boost_mode.attr,
    @@ -3368,6 +3468,12 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
    ok = asus->egpu_enable_available;
    else if (attr == &dev_attr_dgpu_disable.attr)
    ok = asus->dgpu_disable_available;
    + else if (attr == &dev_attr_keyboard_rgb_save.attr)
    + ok = asus->keyboard_rgb_mode_available;
    + else if (attr == &dev_attr_keyboard_rgb_mode.attr)
    + ok = asus->keyboard_rgb_mode_available;
    + else if (attr == &dev_attr_keyboard_rgb_speed.attr)
    + ok = asus->keyboard_rgb_mode_available;
    else if (attr == &dev_attr_fan_boost_mode.attr)
    ok = asus->fan_boost_mode_available;
    else if (attr == &dev_attr_throttle_thermal_policy.attr)
    @@ -3637,6 +3743,10 @@ static int asus_wmi_add(struct platform_device *pdev)
    if (err)
    goto fail_dgpu_disable;

    + err = keyboard_rgb_check_present(asus);
    + if (err)
    + goto fail_keyboard_rgb_mode;
    +
    err = fan_boost_mode_check_present(asus);
    if (err)
    goto fail_fan_boost_mode;
    @@ -3751,6 +3861,7 @@ static int asus_wmi_add(struct platform_device *pdev)
    fail_fan_boost_mode:
    fail_egpu_enable:
    fail_dgpu_disable:
    +fail_keyboard_rgb_mode:
    fail_platform:
    fail_panel_od:
    kfree(asus);
    --
    2.37.1
    \
     
     \ /
      Last update: 2022-08-09 04:52    [W:4.117 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site