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

Commit d7d717fa authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds

* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
  leds: ledtrig-timer - on deactivation hardware blinking should be disabled
  leds: Add suspend/resume to the core class
  leds: Add WM8350 LED driver
  leds: leds-pcs9532 - Move i2c work to a workqueque
  leds: leds-pca9532 - fix memory leak and properly handle errors
  leds: Fix wrong loop direction on removal in leds-ams-delta
  leds: fix Cobalt Raq LED dependency
  leds: Fix sparse warning in leds-ams-delta
  leds: Fixup kdoc comment to match parameter names
  leds: Make header variable naming consistent
  leds: eds-pca9532: mark pca9532_event() static
  leds: ALIX.2 LEDs driver
parents b64dc5a4 ce70a245
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -63,6 +63,12 @@ config LEDS_WRAP
	help
	help
	  This option enables support for the PCEngines WRAP programmable LEDs.
	  This option enables support for the PCEngines WRAP programmable LEDs.


config LEDS_ALIX2
	tristate "LED Support for ALIX.2 and ALIX.3 series"
	depends on LEDS_CLASS && X86 && EXPERIMENTAL
	help
	  This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.

config LEDS_H1940
config LEDS_H1940
	tristate "LED Support for iPAQ H1940 device"
	tristate "LED Support for iPAQ H1940 device"
	depends on LEDS_CLASS && ARCH_H1940
	depends on LEDS_CLASS && ARCH_H1940
@@ -77,7 +83,7 @@ config LEDS_COBALT_QUBE


config LEDS_COBALT_RAQ
config LEDS_COBALT_RAQ
	bool "LED Support for the Cobalt Raq series"
	bool "LED Support for the Cobalt Raq series"
	depends on LEDS_CLASS && MIPS_COBALT
	depends on LEDS_CLASS=y && MIPS_COBALT
	select LEDS_TRIGGERS
	select LEDS_TRIGGERS
	help
	help
	  This option enables support for the Cobalt Raq series LEDs.
	  This option enables support for the Cobalt Raq series LEDs.
@@ -158,6 +164,13 @@ config LEDS_PCA955X
	  LED driver chips accessed via the I2C bus.  Supported
	  LED driver chips accessed via the I2C bus.  Supported
	  devices include PCA9550, PCA9551, PCA9552, and PCA9553.
	  devices include PCA9550, PCA9551, PCA9552, and PCA9553.


config LEDS_WM8350
	tristate "LED Support for WM8350 AudioPlus PMIC"
	depends on LEDS_CLASS && MFD_WM8350
	help
	  This option enables support for LEDs driven by the Wolfson
	  Microelectronics WM8350 AudioPlus PMIC.

config LEDS_DA903X
config LEDS_DA903X
	tristate "LED Support for DA9030/DA9034 PMIC"
	tristate "LED Support for DA9030/DA9034 PMIC"
	depends on LEDS_CLASS && PMIC_DA903X
	depends on LEDS_CLASS && PMIC_DA903X
+2 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
obj-$(CONFIG_LEDS_ALIX2)		+= leds-alix2.o
obj-$(CONFIG_LEDS_H1940)		+= leds-h1940.o
obj-$(CONFIG_LEDS_H1940)		+= leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE)		+= leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_QUBE)		+= leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ)		+= leds-cobalt-raq.o
obj-$(CONFIG_LEDS_COBALT_RAQ)		+= leds-cobalt-raq.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X)		+= leds-pca955x.o
obj-$(CONFIG_LEDS_PCA955X)		+= leds-pca955x.o
obj-$(CONFIG_LEDS_DA903X)		+= leds-da903x.o
obj-$(CONFIG_LEDS_DA903X)		+= leds-da903x.o
obj-$(CONFIG_LEDS_HP_DISK)		+= leds-hp-disk.o
obj-$(CONFIG_LEDS_HP_DISK)		+= leds-hp-disk.o
obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o


# LED Triggers
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
+23 −1
Original line number Original line Diff line number Diff line
@@ -91,9 +91,29 @@ void led_classdev_resume(struct led_classdev *led_cdev)
}
}
EXPORT_SYMBOL_GPL(led_classdev_resume);
EXPORT_SYMBOL_GPL(led_classdev_resume);


static int led_suspend(struct device *dev, pm_message_t state)
{
	struct led_classdev *led_cdev = dev_get_drvdata(dev);

	if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
		led_classdev_suspend(led_cdev);

	return 0;
}

static int led_resume(struct device *dev)
{
	struct led_classdev *led_cdev = dev_get_drvdata(dev);

	if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
		led_classdev_resume(led_cdev);

	return 0;
}

/**
/**
 * led_classdev_register - register a new object of led_classdev class.
 * led_classdev_register - register a new object of led_classdev class.
 * @dev: The device to register.
 * @parent: The device to register.
 * @led_cdev: the led_classdev structure for this device.
 * @led_cdev: the led_classdev structure for this device.
 */
 */
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
@@ -174,6 +194,8 @@ static int __init leds_init(void)
	leds_class = class_create(THIS_MODULE, "leds");
	leds_class = class_create(THIS_MODULE, "leds");
	if (IS_ERR(leds_class))
	if (IS_ERR(leds_class))
		return PTR_ERR(leds_class);
		return PTR_ERR(leds_class);
	leds_class->suspend = led_suspend;
	leds_class->resume = led_resume;
	return 0;
	return 0;
}
}


+181 −0
Original line number Original line Diff line number Diff line
/*
 * LEDs driver for PCEngines ALIX.2 and ALIX.3
 *
 * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
 */

#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/string.h>

static int force = 0;
module_param(force, bool, 0444);
MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs");

struct alix_led {
	struct led_classdev cdev;
	unsigned short port;
	unsigned int on_value;
	unsigned int off_value;
};

static void alix_led_set(struct led_classdev *led_cdev,
			 enum led_brightness brightness)
{
	struct alix_led *led_dev =
		container_of(led_cdev, struct alix_led, cdev);

	if (brightness)
		outl(led_dev->on_value, led_dev->port);
	else
		outl(led_dev->off_value, led_dev->port);
}

static struct alix_led alix_leds[] = {
	{
		.cdev = {
			.name = "alix:1",
			.brightness_set = alix_led_set,
		},
		.port = 0x6100,
		.on_value = 1 << 22,
		.off_value = 1 << 6,
	},
	{
		.cdev = {
			.name = "alix:2",
			.brightness_set = alix_led_set,
		},
		.port = 0x6180,
		.on_value = 1 << 25,
		.off_value = 1 << 9,
	},
	{
		.cdev = {
			.name = "alix:3",
			.brightness_set = alix_led_set,
		},
		.port = 0x6180,
		.on_value = 1 << 27,
		.off_value = 1 << 11,
	},
};

static int __init alix_led_probe(struct platform_device *pdev)
{
	int i;
	int ret;

	for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
		alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
		ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
		if (ret < 0)
			goto fail;
	}
	return 0;

fail:
	while (--i >= 0)
		led_classdev_unregister(&alix_leds[i].cdev);
	return ret;
}

static int alix_led_remove(struct platform_device *pdev)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
		led_classdev_unregister(&alix_leds[i].cdev);
	return 0;
}

static struct platform_driver alix_led_driver = {
	.remove = alix_led_remove,
	.driver = {
		.name = KBUILD_MODNAME,
		.owner = THIS_MODULE,
	},
};

static int __init alix_present(void)
{
	const unsigned long bios_phys = 0x000f0000;
	const size_t bios_len = 0x00010000;
	const char alix_sig[] = "PC Engines ALIX.";
	const size_t alix_sig_len = sizeof(alix_sig) - 1;

	const char *bios_virt;
	const char *scan_end;
	const char *p;
	int ret = 0;

	if (force) {
		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
		       "assume system has ALIX.2 style LEDs\n",
		       KBUILD_MODNAME);
		ret = 1;
		goto out;
	}

	bios_virt = phys_to_virt(bios_phys);
	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
	for (p = bios_virt; p < scan_end; p++) {
		const char *tail;

		if (memcmp(p, alix_sig, alix_sig_len) != 0) {
			continue;
		}

		tail = p + alix_sig_len;
		if ((tail[0] == '2' || tail[0] == '3') && tail[1] == '\0') {
			printk(KERN_INFO
			       "%s: system is recognized as \"%s\"\n",
			       KBUILD_MODNAME, p);
			ret = 1;
			break;
		}
	}

out:
	return ret;
}

static struct platform_device *pdev;

static int __init alix_led_init(void)
{
	int ret;

	if (!alix_present()) {
		ret = -ENODEV;
		goto out;
	}

	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
	if (!IS_ERR(pdev)) {
		ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
		if (ret)
			platform_device_unregister(pdev);
	} else
		ret = PTR_ERR(pdev);

out:
	return ret;
}

static void __exit alix_led_exit(void)
{
	platform_device_unregister(pdev);
	platform_driver_unregister(&alix_led_driver);
}

module_init(alix_led_init);
module_exit(alix_led_exit);

MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
MODULE_LICENSE("GPL");
+3 −30
Original line number Original line Diff line number Diff line
@@ -79,37 +79,12 @@ static struct ams_delta_led ams_delta_leds[] = {
	},
	},
};
};


#ifdef CONFIG_PM
static int ams_delta_led_suspend(struct platform_device *dev,
		pm_message_t state)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
		led_classdev_suspend(&ams_delta_leds[i].cdev);

	return 0;
}

static int ams_delta_led_resume(struct platform_device *dev)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
		led_classdev_resume(&ams_delta_leds[i].cdev);

	return 0;
}
#else
#define ams_delta_led_suspend NULL
#define ams_delta_led_resume NULL
#endif

static int ams_delta_led_probe(struct platform_device *pdev)
static int ams_delta_led_probe(struct platform_device *pdev)
{
{
	int i, ret;
	int i, ret;


	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) {
	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) {
		ams_delta_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
		ret = led_classdev_register(&pdev->dev,
		ret = led_classdev_register(&pdev->dev,
				&ams_delta_leds[i].cdev);
				&ams_delta_leds[i].cdev);
		if (ret < 0)
		if (ret < 0)
@@ -127,7 +102,7 @@ static int ams_delta_led_remove(struct platform_device *pdev)
{
{
	int i;
	int i;


	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i--)
	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
		led_classdev_unregister(&ams_delta_leds[i].cdev);
		led_classdev_unregister(&ams_delta_leds[i].cdev);


	return 0;
	return 0;
@@ -136,8 +111,6 @@ static int ams_delta_led_remove(struct platform_device *pdev)
static struct platform_driver ams_delta_led_driver = {
static struct platform_driver ams_delta_led_driver = {
	.probe		= ams_delta_led_probe,
	.probe		= ams_delta_led_probe,
	.remove		= ams_delta_led_remove,
	.remove		= ams_delta_led_remove,
	.suspend	= ams_delta_led_suspend,
	.resume		= ams_delta_led_resume,
	.driver		= {
	.driver		= {
		.name = "ams-delta-led",
		.name = "ams-delta-led",
		.owner = THIS_MODULE,
		.owner = THIS_MODULE,
@@ -151,7 +124,7 @@ static int __init ams_delta_led_init(void)


static void __exit ams_delta_led_exit(void)
static void __exit ams_delta_led_exit(void)
{
{
	return platform_driver_unregister(&ams_delta_led_driver);
	platform_driver_unregister(&ams_delta_led_driver);
}
}


module_init(ams_delta_led_init);
module_init(ams_delta_led_init);
Loading