platform-driver-x86.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Luke D. Jones" <luke@ljones.dev>
To: hdegoede@redhat.com
Cc: markgross@kernel.org, platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org, "Luke D. Jones" <luke@ljones.dev>
Subject: [PATCH v2 1/6] asus-wmi: Implement TUF laptop keyboard RGB control
Date: Mon,  8 Aug 2022 15:04:15 +1200	[thread overview]
Message-ID: <20220808030420.8633-2-luke@ljones.dev> (raw)
In-Reply-To: <20220808030420.8633-1-luke@ljones.dev>

Adds support for TUF laptop RGB control via the multicolor LED API.

As this is the bas for adjusting only the RGB values, it sets the
default mode of the keyboard to static since there is no way to read
any existing settings from the device. These defaults overwrite the
booted state of the keyboard when the module is loaded.

Signed-off-by: Luke D. Jones <luke@ljones.dev>
---
 drivers/platform/x86/asus-wmi.c            | 80 ++++++++++++++++++++++
 include/linux/platform_data/x86/asus-wmi.h |  3 +
 2 files changed, 83 insertions(+)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 0e7fbed8a50d..233e73f4313d 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -25,6 +25,7 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/kernel.h>
 #include <linux/leds.h>
+#include <linux/led-class-multicolor.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
@@ -117,6 +118,9 @@ static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
 
 static int throttle_thermal_policy_write(struct asus_wmi *);
 
+static int tuf_rgb_brightness_set(struct led_classdev *cdev,
+							enum led_brightness brightness);
+
 static bool ashs_present(void)
 {
 	int i = 0;
@@ -190,6 +194,14 @@ struct fan_curve_data {
 	u8 percents[FAN_CURVE_POINTS];
 };
 
+struct keyboard_rgb_led {
+	struct mc_subled subled_info[3]; /* r g b */
+	struct led_classdev_mc dev;
+	u8 save;
+	u8 mode;
+	u8 speed;
+};
+
 struct asus_wmi {
 	int dsts_id;
 	int spec;
@@ -234,6 +246,8 @@ struct asus_wmi {
 	bool dgpu_disable_available;
 	bool dgpu_disable;
 
+	struct keyboard_rgb_led keyboard_rgb_mode;
+
 	bool throttle_thermal_policy_available;
 	u8 throttle_thermal_policy_mode;
 
@@ -1028,12 +1042,40 @@ static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev)
 	return result & ASUS_WMI_DSTS_LIGHTBAR_MASK;
 }
 
+static int tuf_rgb_brightness_set(struct led_classdev *cdev,
+	enum led_brightness brightness)
+{
+	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 device *dev = &asus->platform_device->dev;
+	u8 r, g, b;
+	int err;
+	u32 ret;
+
+	led_mc_calc_color_components(mc_cdev, brightness);
+	r = mc_cdev->subled_info[0].brightness;
+	g = mc_cdev->subled_info[1].brightness;
+	b = mc_cdev->subled_info[2].brightness;
+
+	/* Writing out requires some defaults. This will overwrite boot mode */
+	err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, ASUS_WMI_DEVID_TUF_RGB_MODE,
+				rgb->save | (rgb->mode << 8) | (r << 16) | (g << 24),
+				(b) | (rgb->speed << 8),
+				&ret);
+	if (err)
+		dev_err(dev, "Unable to set TUF RGB data?\n");
+
+	return err;
+}
+
 static void asus_wmi_led_exit(struct asus_wmi *asus)
 {
 	led_classdev_unregister(&asus->kbd_led);
 	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);
 
 	if (asus->led_workqueue)
 		destroy_workqueue(asus->led_workqueue);
@@ -1105,6 +1147,44 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 					   &asus->lightbar_led);
 	}
 
+	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 device *dev = &asus->platform_device->dev;
+		u8 led_brightness = 255;
+
+		/*
+		 * asus::kbd_backlight still controls a base 3-level backlight and when
+		 * it is on 0, the RGB is not visible at all. RGB should be treated as
+		 * an additional step.
+		 */
+		mc_cdev->led_cdev.name = "asus::multicolour::kbd_backlight";
+		mc_cdev->led_cdev.flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN;
+		mc_cdev->led_cdev.brightness_set_blocking = tuf_rgb_brightness_set;
+		mc_cdev->led_cdev.brightness_get = NULL;
+
+		mc_cdev->subled_info = mc_led_info;
+		mc_led_info[0].intensity = 127;
+		mc_led_info[0].color_index = LED_COLOR_ID_RED;
+		mc_led_info[1].color_index = LED_COLOR_ID_GREEN;
+		mc_led_info[2].color_index = LED_COLOR_ID_BLUE;
+		mc_cdev->num_colors = 3;
+
+		/*
+		 * 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;
+
+		mc_cdev->led_cdev.brightness = led_brightness;
+		mc_cdev->led_cdev.max_brightness = led_brightness;
+		led_mc_calc_color_components(mc_cdev, led_brightness);
+
+		rv = led_classdev_multicolor_register(dev, mc_cdev);
+	}
+
 error:
 	if (rv)
 		asus_wmi_led_exit(asus);
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index a571b47ff362..d63c9945a17d 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -98,6 +98,9 @@
 /* dgpu on/off */
 #define ASUS_WMI_DEVID_DGPU		0x00090020
 
+/* TUF laptop RGB control */
+#define ASUS_WMI_DEVID_TUF_RGB_MODE	0x00100056
+
 /* DSTS masks */
 #define ASUS_WMI_DSTS_STATUS_BIT	0x00000001
 #define ASUS_WMI_DSTS_UNKNOWN_BIT	0x00000002
-- 
2.37.1


  reply	other threads:[~2022-08-08  3:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-08  3:04 [PATCH v2 0/6] asus-wmi: Add support for RGB keyboards Luke D. Jones
2022-08-08  3:04 ` Luke D. Jones [this message]
2022-08-08  3:04 ` [PATCH v2 2/6] asus-wmi: Implement TUF laptop keyboard LED modes Luke D. Jones
2022-08-08 16:01   ` Andy Shevchenko
2022-08-08 21:43     ` Luke Jones
2022-08-09  7:20       ` Andy Shevchenko
2022-08-08  3:04 ` [PATCH v2 3/6] asus-wmi: Implement TUF laptop keyboard power states Luke D. Jones
2022-08-08 16:08   ` Andy Shevchenko
2022-08-08 23:27     ` Luke Jones
2022-08-09  8:29       ` Andy Shevchenko
2022-08-09 22:25         ` Luke Jones
2022-08-08  3:04 ` [PATCH v2 4/6] asus-wmi: Document previously added attributes Luke D. Jones
2022-08-08 16:11   ` Andy Shevchenko
2022-08-08  3:04 ` [PATCH v2 5/6] asus-wmi: Convert all attr-show to use sysfs_emit Luke D. Jones
2022-08-08 16:13   ` Andy Shevchenko
2022-08-08  3:04 ` [PATCH v2 6/6] asus-wmi: Add support for dGPU-only mode Luke D. Jones
2022-08-08  8:38   ` Luke Jones
2022-08-08 15:44   ` Andy Shevchenko
2022-08-08  3:26 ` [PATCH v2 0/6] asus-wmi: Add support for RGB keyboards Luke Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220808030420.8633-2-luke@ljones.dev \
    --to=luke@ljones.dev \
    --cc=hdegoede@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=markgross@kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).