linux-leds.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: leo60228 <leo@60228.dev>
To: hdegoede@redhat.com, platform-driver-x86@vger.kernel.org,
	linux-leds@vger.kernel.org
Cc: leo60228 <leo@60228.dev>
Subject: [PATCH v2] platform/x86: add support for Acer Predator LEDs
Date: Tue, 15 Jun 2021 20:51:47 -0400	[thread overview]
Message-ID: <20210616005147.26212-1-leo@60228.dev> (raw)
In-Reply-To: <20210615221931.18148-1-leo@60228.dev>

The Acer Predator Helios 500's keyboard has four zones of RGB LEDs.

This driver allows them to be controlled from Linux.

Signed-off-by: leo60228 <leo@60228.dev>
---
In addition to some smaller concerns from review, v2 registers
multicolor LEDs instead of independent red, green, and blue ones.

 MAINTAINERS                     |   6 ++
 drivers/platform/x86/Kconfig    |  13 +++
 drivers/platform/x86/Makefile   |   1 +
 drivers/platform/x86/acer-led.c | 143 ++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 drivers/platform/x86/acer-led.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bc0ceef87..f647ea81c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -327,6 +327,12 @@ S:	Maintained
 W:	http://piie.net/?section=acerhdf
 F:	drivers/platform/x86/acerhdf.c
 
+ACER PREDATOR LAPTOP LEDS
+M:	leo60228 <leo@60228.dev>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/acer-led.c
+
 ACER WMI LAPTOP EXTRAS
 M:	"Lee, Chun-Yi" <jlee@suse.com>
 L:	platform-driver-x86@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 60592fb88..a6d6ed2ac 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -190,6 +190,19 @@ config ACER_WMI
 	  If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
 	  here.
 
+config ACER_LED
+	tristate "Acer Predator Laptop LEDs"
+	depends on ACPI
+	depends on ACPI_WMI
+	depends on LEDS_CLASS_MULTICOLOR
+	depends on NEW_LEDS
+	help
+	  This is a driver for the RGB keyboard LEDs in Acer Predator laptops.
+	  It was designed for the Acer Predator Helios 500.
+
+	  If you choose to compile this driver as a module the module will be
+	  called acer-led.
+
 config AMD_PMC
 	tristate "AMD SoC PMC driver"
 	depends on ACPI && PCI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index dcc8cdb95..36722207b 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GIGABYTE_WMI)		+= gigabyte-wmi.o
 obj-$(CONFIG_ACERHDF)		+= acerhdf.o
 obj-$(CONFIG_ACER_WIRELESS)	+= acer-wireless.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
+obj-$(CONFIG_ACER_LED)		+= acer-led.o
 
 # AMD
 obj-$(CONFIG_AMD_PMC)		+= amd-pmc.o
diff --git a/drivers/platform/x86/acer-led.c b/drivers/platform/x86/acer-led.c
new file mode 100644
index 000000000..d618830e0
--- /dev/null
+++ b/drivers/platform/x86/acer-led.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Acer LED Driver
+ *
+ * Copyright (C) 2021 leo60228
+ */
+
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/leds.h>
+#include <linux/led-class-multicolor.h>
+#include <linux/wmi.h>
+
+MODULE_AUTHOR("leo60228");
+MODULE_DESCRIPTION("Acer LED Driver");
+MODULE_LICENSE("GPL");
+
+#define ACER_LED_METHOD_GUID "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56"
+
+struct acer_led_zone {
+	char name[32];
+	int id;
+	struct mc_subled channels[3];
+	struct led_classdev_mc cdev;
+};
+
+struct acer_led_priv {
+	struct acer_led_zone zones[4];
+};
+
+struct led_zone_set_param {
+	u8 zone;
+	u8 red;
+	u8 green;
+	u8 blue;
+} __packed;
+
+static int acer_led_set(struct led_classdev *lcdev,
+			enum led_brightness value)
+{
+	struct led_classdev_mc *mccdev;
+	struct acer_led_zone *zone;
+	struct led_zone_set_param set_params;
+	struct acpi_buffer set_input;
+	int err;
+	acpi_status status;
+
+	mccdev = lcdev_to_mccdev(lcdev);
+
+	err = led_mc_calc_color_components(mccdev, value);
+	if (err)
+		return err;
+
+	zone = container_of(mccdev, struct acer_led_zone, cdev);
+
+	set_params = (struct led_zone_set_param) {
+		.zone = BIT(zone->id),
+		.red = zone->channels[0].brightness,
+		.green = zone->channels[1].brightness,
+		.blue = zone->channels[2].brightness,
+	};
+	set_input = (struct acpi_buffer) {
+		sizeof(set_params),
+		&set_params
+	};
+
+	status = wmi_evaluate_method(
+		ACER_LED_METHOD_GUID, 0, 0x6, &set_input, NULL);
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	return 0;
+}
+
+static int acer_led_setup_zone(struct wmi_device *wdev,
+			       struct acer_led_zone *zone)
+{
+	snprintf(zone->name, sizeof(zone->name), ":kbd_backlight-%d",
+		 zone->id + 1);
+
+	zone->channels[0].color_index = LED_COLOR_ID_RED;
+	zone->channels[0].channel = 0;
+	zone->channels[1].color_index = LED_COLOR_ID_GREEN;
+	zone->channels[1].channel = 1;
+	zone->channels[2].color_index = LED_COLOR_ID_BLUE;
+	zone->channels[2].channel = 2;
+
+	zone->cdev.num_colors = 3;
+	zone->cdev.subled_info = zone->channels;
+
+	zone->cdev.led_cdev.name = zone->name;
+	zone->cdev.led_cdev.max_brightness = 255;
+	zone->cdev.led_cdev.brightness_set_blocking = acer_led_set;
+
+	return devm_led_classdev_multicolor_register(&wdev->dev, &zone->cdev);
+}
+
+static int acer_led_setup(struct wmi_device *wdev)
+{
+	struct acer_led_priv *priv = dev_get_drvdata(&wdev->dev);
+	int i, err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(priv->zones); i++) {
+		priv->zones[i].id = i;
+
+		err = acer_led_setup_zone(wdev, &priv->zones[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int acer_led_probe(struct wmi_device *wdev, const void *context)
+{
+	struct acer_led_priv *priv;
+
+	priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_set_drvdata(&wdev->dev, priv);
+
+	return acer_led_setup(wdev);
+}
+
+static const struct wmi_device_id acer_led_id_table[] = {
+	{ .guid_string = ACER_LED_METHOD_GUID },
+	{ },
+};
+
+static struct wmi_driver acer_led_driver = {
+	.driver = {
+		.name = "acer-led",
+	},
+	.id_table = acer_led_id_table,
+	.probe = acer_led_probe,
+};
+
+module_wmi_driver(acer_led_driver);
+
+MODULE_DEVICE_TABLE(wmi, acer_led_id_table);
-- 
2.28.0


  parent reply	other threads:[~2021-06-16  0:51 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20210615221931.18148-1-leo@60228.dev>
2021-06-15 23:24 ` [PATCH] platform/x86: add support for Acer Predator LEDs Barnabás Pőcze
     [not found]   ` <CAPRrO0xZunTfYYSOg-Gvk18FMHPufAURZ=fWjQN1bmP=RuuzGA@mail.gmail.com>
2021-06-16  0:21     ` Barnabás Pőcze
2021-06-16  0:24       ` leo60228
2021-06-16  0:51 ` leo60228 [this message]
2021-06-16 15:43   ` [PATCH v2] " Enrico Weigelt, metux IT consult
2021-06-16 15:56     ` leo60228
2021-06-16 17:20       ` Enrico Weigelt, metux IT consult
2021-06-16 17:50         ` Hans de Goede
2021-06-21 19:23           ` Enrico Weigelt, metux IT consult
2021-06-21 19:43             ` Hans de Goede
2021-06-22 10:19               ` input devices vs. keyboard backlights [WAS: [PATCH v2] platform/x86: add support for Acer Predator LEDs] Enrico Weigelt, metux IT consult
2021-06-22 10:46                 ` Hans de Goede

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=20210616005147.26212-1-leo@60228.dev \
    --to=leo@60228.dev \
    --cc=hdegoede@redhat.com \
    --cc=linux-leds@vger.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).