From: Thomas Tuttle <thinkinginbinary@gmail.com>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Richard Purdie <rpurdie@rpsys.net>
Subject: [PATCH] Integrate asus_acpi LED's with new LED subsystem
Date: Thu, 6 Jul 2006 15:31:57 -0400 [thread overview]
Message-ID: <20060706193157.GC14043@phoenix> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 561 bytes --]
(Sorry to repost... just going through the motions of ChangeLog and
Signed-off-by headers.)
Here is a patch to the asus_acpi driver that links the Asus laptop LED's
into the new LED subsystem. It creates LED class devices named
asus:mail, asus:wireless, and asus:touchpad, depending on if the laptop
supports the mled, wled, and tled LED's.
Since it's so new, I added a config option to turn it on and off. It's
worked for me, though I have an Asus M2N, which only has the mail and
wireless LED's.
Signed-off-by: Thomas Tuttle <thinkinginbinary@gmail.com>
[-- Attachment #1.2: asus-acpi-led-subsystem.patch --]
[-- Type: text/plain, Size: 7583 bytes --]
diff -udrN linux-2.6.17-git25/drivers/acpi/asus_acpi.c linux-2.6.17-git25-mine/drivers/acpi/asus_acpi.c
--- linux-2.6.17-git25/drivers/acpi/asus_acpi.c 2006-07-05 22:11:37.000000000 -0400
+++ linux-2.6.17-git25-mine/drivers/acpi/asus_acpi.c 2006-07-05 22:26:51.000000000 -0400
@@ -27,14 +27,19 @@
* Johann Wiesner - Small compile fixes
* John Belmonte - ACPI code for Toshiba laptop was a good starting point.
* �ric Burghard - LED display support for W1N
+ * Thomas Tuttle - LED subsystem integration
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
+#ifdef CONFIG_ACPI_ASUS_NEW_LED
+#include <linux/leds.h>
+#endif
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#include <asm/uaccess.h>
@@ -916,6 +921,145 @@
return 0;
}
+#ifdef CONFIG_ACPI_ASUS_NEW_LED
+
+/* These functions are called by the LED subsystem to update the desired
+ * state of the LED's. */
+static void led_set_mled(struct led_classdev *led_cdev,
+ enum led_brightness value);
+static void led_set_wled(struct led_classdev *led_cdev,
+ enum led_brightness value);
+static void led_set_tled(struct led_classdev *led_cdev,
+ enum led_brightness value);
+
+/* LED class devices. */
+static struct led_classdev led_cdev_mled =
+ { .name = "asus:mail", .brightness_set = led_set_mled };
+static struct led_classdev led_cdev_wled =
+ { .name = "asus:wireless", .brightness_set = led_set_wled };
+static struct led_classdev led_cdev_tled =
+ { .name = "asus:touchpad", .brightness_set = led_set_tled };
+
+/* These functions actually update the LED's, and are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, I avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt. */
+static void led_update_mled(void *private);
+static void led_update_wled(void *private);
+static void led_update_tled(void *private);
+
+/* Desired values of LED's. */
+static int led_mled_value = 0;
+static int led_wled_value = 0;
+static int led_tled_value = 0;
+
+/* LED workqueue. */
+static struct workqueue_struct *led_workqueue;
+
+/* LED update work structs. */
+DECLARE_WORK(led_mled_work, led_update_mled, NULL);
+DECLARE_WORK(led_wled_work, led_update_wled, NULL);
+DECLARE_WORK(led_tled_work, led_update_tled, NULL);
+
+/* LED subsystem callbacks. */
+static void led_set_mled(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ led_mled_value = value;
+ queue_work(led_workqueue, &led_mled_work);
+}
+
+static void led_set_wled(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ led_wled_value = value;
+ queue_work(led_workqueue, &led_wled_work);
+}
+
+static void led_set_tled(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ led_tled_value = value;
+ queue_work(led_workqueue, &led_tled_work);
+}
+
+/* LED work functions. */
+static void led_update_mled(void *private) {
+ char *ledname = hotk->methods->mt_mled;
+ int led_out = led_mled_value ? 1 : 0;
+ hotk->status = (led_out) ? (hotk->status | MLED_ON) : (hotk->status & ~MLED_ON);
+ led_out = 1 - led_out;
+ if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
+ printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+ ledname);
+}
+
+static void led_update_wled(void *private) {
+ char *ledname = hotk->methods->mt_wled;
+ int led_out = led_wled_value ? 1 : 0;
+ hotk->status = (led_out) ? (hotk->status | WLED_ON) : (hotk->status & ~WLED_ON);
+ if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
+ printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+ ledname);
+}
+
+static void led_update_tled(void *private) {
+ char *ledname = hotk->methods->mt_tled;
+ int led_out = led_tled_value ? 1 : 0;
+ hotk->status = (led_out) ? (hotk->status | TLED_ON) : (hotk->status & ~TLED_ON);
+ if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
+ printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+ ledname);
+}
+
+/* Registers LED class devices and sets up workqueue. */
+static int led_initialize(struct device *parent)
+{
+ int result;
+
+ if (hotk->methods->mt_mled) {
+ result = led_classdev_register(parent, &led_cdev_mled);
+ if (result)
+ return result;
+ }
+
+ if (hotk->methods->mt_wled) {
+ result = led_classdev_register(parent, &led_cdev_wled);
+ if (result)
+ return result;
+ }
+
+ if (hotk->methods->mt_tled) {
+ result = led_classdev_register(parent, &led_cdev_tled);
+ if (result)
+ return result;
+ }
+
+ led_workqueue = create_singlethread_workqueue("led_workqueue");
+
+ return 0;
+}
+
+/* Destroys the workqueue and unregisters the LED class devices. */
+static void led_terminate(void)
+{
+ destroy_workqueue(led_workqueue);
+
+ if (hotk->methods->mt_tled) {
+ led_classdev_unregister(&led_cdev_tled);
+ }
+
+ if (hotk->methods->mt_wled) {
+ led_classdev_unregister(&led_cdev_wled);
+ }
+
+ if (hotk->methods->mt_mled) {
+ led_classdev_unregister(&led_cdev_mled);
+ }
+}
+
+#endif
+
static int asus_hotk_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *proc;
@@ -1299,6 +1443,10 @@
/* LED display is off by default */
hotk->ledd_status = 0xFFF;
+#ifdef CONFIG_ACPI_ASUS_NEW_LED
+ result = led_initialize(acpi_get_physical_device(device->handle));
+#endif
+
end:
if (result) {
kfree(hotk);
@@ -1314,6 +1462,10 @@
if (!device || !acpi_driver_data(device))
return -EINVAL;
+#ifdef CONFIG_ACPI_ASUS_NEW_LED
+ led_terminate();
+#endif
+
status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
asus_hotk_notify);
if (ACPI_FAILURE(status))
diff -udrN linux-2.6.17-git25/drivers/acpi/Kconfig linux-2.6.17-git25-mine/drivers/acpi/Kconfig
--- linux-2.6.17-git25/drivers/acpi/Kconfig 2006-07-05 22:44:33.000000000 -0400
+++ linux-2.6.17-git25-mine/drivers/acpi/Kconfig 2006-07-05 22:44:43.000000000 -0400
@@ -199,6 +199,15 @@
something works not quite as expected, please use the mailing list
available on the above page (acpi4asus-user@lists.sourceforge.net)
+config ACPI_ASUS_NEW_LED
+ bool "ASUS/Medion LED subsystem integration"
+ depends on ACPI_ASUS
+ depends on LEDS_CLASS
+ help
+ This adds support for the new LED subsystem to the asus_acpi
+ driver. The LED's will show up as asus:mail, asus:wireless,
+ and asus:touchpad, as applicable to your laptop.
+
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
[-- Attachment #2: Type: application/pgp-signature, Size: 191 bytes --]
next reply other threads:[~2006-07-06 19:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-06 19:31 Thomas Tuttle [this message]
2006-07-06 22:39 ` [PATCH] Integrate asus_acpi LED's with new LED subsystem Richard Purdie
2006-07-07 1:11 ` Thomas Tuttle
2006-07-06 22:49 ` Andrew Morton
2006-07-07 1:20 ` Thomas Tuttle
2006-07-07 8:46 ` Richard Purdie
2006-07-24 21:24 ` Johannes Engel
2006-07-06 23:50 ` Pavel Machek
2006-07-07 1:44 ` Thomas Tuttle
2006-07-07 9:38 ` Pavel Machek
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=20060706193157.GC14043@phoenix \
--to=thinkinginbinary@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rpurdie@rpsys.net \
/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).