Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c0eb510 authored by Corentin Chary's avatar Corentin Chary Committed by Len Brown
Browse files

eeepc-laptop: add touchpad led



This led can be found on Eeepc 1005 series.

Signed-off-by: default avatarCorentin Chary <corentincj@iksaif.net>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent edf62452
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -334,6 +334,8 @@ config EEEPC_LAPTOP
	depends on HOTPLUG_PCI
	select BACKLIGHT_CLASS_DEVICE
	select HWMON
	select LEDS_CLASS
	select NEW_LEDS
	---help---
	  This driver supports the Fn-Fx keys on Eee PC laptops.

+67 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/rfkill.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/leds.h>

#define EEEPC_LAPTOP_VERSION	"0.1"

@@ -506,6 +507,39 @@ static struct attribute_group platform_attribute_group = {
	.attrs = platform_attributes
};

/*
 * LEDs
 */
/*
 * 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, we avoid messing with the Asus ACPI stuff during a
 * potentially bad time, such as a timer interrupt.
 */
static int tpd_led_wk;

static void tpd_led_update(struct work_struct *ignored)
{
	int value = tpd_led_wk;
	set_acpi(CM_ASL_TPD, value);
}

static struct workqueue_struct *led_workqueue;
static DECLARE_WORK(tpd_led_work, tpd_led_update);

static void tpd_led_set(struct led_classdev *led_cdev,
			enum led_brightness value)
{
	tpd_led_wk = (value > 0) ? 1 : 0;
	queue_work(led_workqueue, &tpd_led_work);
}

static struct led_classdev tpd_led = {
	.name           = "eeepc::touchpad",
	.brightness_set = tpd_led_set,
	.max_brightness = 1
};

/*
 * Hotkey functions
 */
@@ -1034,6 +1068,14 @@ static void eeepc_hwmon_exit(void)
	eeepc_hwmon_device = NULL;
}

static void eeepc_led_exit(void)
{
	if (led_workqueue)
		destroy_workqueue(led_workqueue);
	if (tpd_led.dev)
		led_classdev_unregister(&tpd_led);
}

static int eeepc_new_rfkill(struct rfkill **rfkill,
			    const char *name, struct device *dev,
			    enum rfkill_type type, int cm)
@@ -1190,6 +1232,24 @@ static int eeepc_input_init(struct device *dev)
	return 0;
}

static int eeepc_led_init(struct device *dev)
{
	int rv;

	if (get_acpi(CM_ASL_TPD) == -ENODEV)
		return 0;

	rv = led_classdev_register(dev, &tpd_led);
	if (rv)
		return rv;

	led_workqueue = create_singlethread_workqueue("led_workqueue");
	if (!led_workqueue)
		return -ENOMEM;

	return 0;
}

static int __devinit eeepc_hotk_add(struct acpi_device *device)
{
	struct device *dev;
@@ -1248,6 +1308,10 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device)
	if (result)
		goto fail_hwmon;

	result = eeepc_led_init(dev);
	if (result)
		goto fail_led;

	result = eeepc_rfkill_init(dev);
	if (result)
		goto fail_rfkill;
@@ -1255,6 +1319,8 @@ static int __devinit eeepc_hotk_add(struct acpi_device *device)
	return 0;

fail_rfkill:
	eeepc_led_exit();
fail_led:
	eeepc_hwmon_exit();
fail_hwmon:
	eeepc_input_exit();
@@ -1284,6 +1350,7 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
	eeepc_rfkill_exit();
	eeepc_input_exit();
	eeepc_hwmon_exit();
	eeepc_led_exit();
	sysfs_remove_group(&platform_device->dev.kobj,
			   &platform_attribute_group);
	platform_device_unregister(platform_device);